|
|
1.1.1.3 root 1: /* Deprecated/legacy */ 1.1.1.6 ! root 2: ! 3: 1.1.1.4 root 4: // des.cpp - modified by Wei Dai from Phil Karn's des.c 5: // The original code and all modifications are in the public domain. 1.1.1.3 root 6: 1.1.1.4 root 7: /* 8: * This is a major rewrite of my old public domain DES code written 9: * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 10: * public domain code. I pretty much kept my key scheduling code, but 11: * the actual encrypt/decrypt routines are taken from from Richard 12: * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." 13: * 14: * This code is in the public domain. I would appreciate bug reports and 15: * enhancements. 16: * 17: * Phil Karn KA9Q, [email protected], August 1994. 18: */ 19: 1.1.1.5 root 20: /* Adapted for TrueCrypt */ 1.1.1.4 root 21: 22: #include <memory.h> 23: #include "Common/Tcdefs.h" 24: #include "Common/Endian.h" 1.1.1.2 root 25: #include "Des.h" 1.1 root 26: 1.1.1.4 root 27: #define word32 unsigned __int32 28: #define byte unsigned __int8 29: 30: static word32 rotlFixed (word32 x, unsigned int y) 31: { 32: return (word32)((x<<y) | (x>>(sizeof(word32)*8-y))); 33: } 34: 35: static word32 rotrFixed (word32 x, unsigned int y) 36: { 37: return (word32)((x>>y) | (x<<(sizeof(word32)*8-y))); 38: } 39: 40: 41: /* Tables defined in the Data Encryption Standard documents 42: * Three of these tables, the initial permutation, the final 43: * permutation and the expansion operator, are regular enough that 44: * for speed, we hard-code them. They're here for reference only. 45: * Also, the S and P boxes are used by a separate program, gensp.c, 46: * to build the combined SP box, Spbox[]. They're also here just 47: * for reference. 48: */ 49: #ifdef notdef 50: /* initial permutation IP */ 51: static byte ip[] = { 52: 58, 50, 42, 34, 26, 18, 10, 2, 53: 60, 52, 44, 36, 28, 20, 12, 4, 54: 62, 54, 46, 38, 30, 22, 14, 6, 55: 64, 56, 48, 40, 32, 24, 16, 8, 56: 57, 49, 41, 33, 25, 17, 9, 1, 57: 59, 51, 43, 35, 27, 19, 11, 3, 58: 61, 53, 45, 37, 29, 21, 13, 5, 59: 63, 55, 47, 39, 31, 23, 15, 7 60: }; 61: 62: /* final permutation IP^-1 */ 63: static byte fp[] = { 64: 40, 8, 48, 16, 56, 24, 64, 32, 65: 39, 7, 47, 15, 55, 23, 63, 31, 66: 38, 6, 46, 14, 54, 22, 62, 30, 67: 37, 5, 45, 13, 53, 21, 61, 29, 68: 36, 4, 44, 12, 52, 20, 60, 28, 69: 35, 3, 43, 11, 51, 19, 59, 27, 70: 34, 2, 42, 10, 50, 18, 58, 26, 71: 33, 1, 41, 9, 49, 17, 57, 25 72: }; 73: /* expansion operation matrix */ 74: static byte ei[] = { 75: 32, 1, 2, 3, 4, 5, 76: 4, 5, 6, 7, 8, 9, 77: 8, 9, 10, 11, 12, 13, 78: 12, 13, 14, 15, 16, 17, 79: 16, 17, 18, 19, 20, 21, 80: 20, 21, 22, 23, 24, 25, 81: 24, 25, 26, 27, 28, 29, 82: 28, 29, 30, 31, 32, 1 83: }; 84: /* The (in)famous S-boxes */ 85: static byte sbox[8][64] = { 86: /* S1 */ 87: 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 88: 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 89: 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 90: 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, 91: 92: /* S2 */ 93: 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 94: 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 95: 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 96: 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, 97: 98: /* S3 */ 99: 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 100: 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 101: 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 102: 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, 103: 104: /* S4 */ 105: 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 106: 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 107: 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 108: 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, 109: 110: /* S5 */ 111: 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 112: 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 113: 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 114: 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, 115: 116: /* S6 */ 117: 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 118: 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 119: 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 120: 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, 121: 122: /* S7 */ 123: 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 124: 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 125: 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 126: 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, 127: 128: /* S8 */ 129: 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 130: 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 131: 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 132: 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 133: }; 134: 135: /* 32-bit permutation function P used on the output of the S-boxes */ 136: static byte p32i[] = { 137: 16, 7, 20, 21, 138: 29, 12, 28, 17, 139: 1, 15, 23, 26, 140: 5, 18, 31, 10, 141: 2, 8, 24, 14, 142: 32, 27, 3, 9, 143: 19, 13, 30, 6, 144: 22, 11, 4, 25 145: }; 146: #endif 147: 148: /* permuted choice table (key) */ 149: static const byte pc1[] = { 150: 57, 49, 41, 33, 25, 17, 9, 151: 1, 58, 50, 42, 34, 26, 18, 152: 10, 2, 59, 51, 43, 35, 27, 153: 19, 11, 3, 60, 52, 44, 36, 154: 155: 63, 55, 47, 39, 31, 23, 15, 156: 7, 62, 54, 46, 38, 30, 22, 157: 14, 6, 61, 53, 45, 37, 29, 158: 21, 13, 5, 28, 20, 12, 4 159: }; 160: 161: /* number left rotations of pc1 */ 162: static const byte totrot[] = { 163: 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 164: }; 165: 166: /* permuted choice key (table) */ 167: static const byte pc2[] = { 168: 14, 17, 11, 24, 1, 5, 169: 3, 28, 15, 6, 21, 10, 170: 23, 19, 12, 4, 26, 8, 171: 16, 7, 27, 20, 13, 2, 172: 41, 52, 31, 37, 47, 55, 173: 30, 40, 51, 45, 33, 48, 174: 44, 49, 39, 56, 34, 53, 175: 46, 42, 50, 36, 29, 32 176: }; 177: 178: /* End of DES-defined tables */ 179: 180: /* bit 0 is left-most in byte */ 181: static const int bytebit[] = { 182: 0200,0100,040,020,010,04,02,01 183: }; 184: 185: static const word32 Spbox[8][64] = { 186: { 187: 0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, 188: 0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, 189: 0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, 190: 0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, 191: 0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, 192: 0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, 193: 0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, 194: 0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, 195: { 196: 0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, 197: 0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, 198: 0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, 199: 0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, 200: 0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, 201: 0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, 202: 0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, 203: 0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, 204: { 205: 0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, 206: 0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, 207: 0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, 208: 0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, 209: 0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, 210: 0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, 211: 0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, 212: 0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, 213: { 214: 0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, 215: 0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, 216: 0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, 217: 0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, 218: 0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, 219: 0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, 220: 0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, 221: 0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, 222: { 223: 0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, 224: 0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, 225: 0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, 226: 0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, 227: 0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, 228: 0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, 229: 0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, 230: 0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, 231: { 232: 0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, 233: 0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, 234: 0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, 235: 0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, 236: 0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, 237: 0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, 238: 0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, 239: 0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, 240: { 241: 0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, 242: 0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, 243: 0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, 244: 0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, 245: 0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, 246: 0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, 247: 0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, 248: 0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, 249: { 250: 0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, 251: 0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, 252: 0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, 253: 0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, 254: 0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, 255: 0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, 256: 0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, 257: 0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} 258: }; 259: 260: /* Set key (initialize key schedule array) */ 261: static void RawSetKey (int encryption, const byte *key, word32 *scheduledKey) 262: { 263: byte buffer[56+56+8]; 264: byte *const pc1m=buffer; /* place to modify pc1 into */ 265: byte *const pcr=pc1m+56; /* place to rotate pc1 into */ 266: byte *const ks=pcr+56; 267: register int i,j,l; 268: int m; 269: 270: for (j=0; j<56; j++) { /* convert pc1 to bits of key */ 271: l=pc1[j]-1; /* integer bit location */ 272: m = l & 07; /* find bit */ 273: pc1m[j]=(key[l>>3] & /* find which key byte l is in */ 274: bytebit[m]) /* and which bit of that byte */ 275: ? 1 : 0; /* and store 1-bit result */ 276: } 277: for (i=0; i<16; i++) { /* key chunk for each iteration */ 278: memset(ks,0,8); /* Clear key schedule */ 279: for (j=0; j<56; j++) /* rotate pc1 the right amount */ 280: pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; 281: /* rotate left and right halves independently */ 282: for (j=0; j<48; j++){ /* select bits individually */ 283: /* check bit that goes to ks[j] */ 284: if (pcr[pc2[j]-1]){ 285: /* mask it in if it's there */ 286: l= j % 6; 287: ks[j/6] |= bytebit[l] >> 2; 288: } 289: } 290: /* Now convert to odd/even interleaved form for use in F */ 291: scheduledKey[2*i] = ((word32)ks[0] << 24) 292: | ((word32)ks[2] << 16) 293: | ((word32)ks[4] << 8) 294: | ((word32)ks[6]); 295: scheduledKey[2*i+1] = ((word32)ks[1] << 24) 296: | ((word32)ks[3] << 16) 297: | ((word32)ks[5] << 8) 298: | ((word32)ks[7]); 299: } 300: 301: if (!encryption) // reverse key schedule order 302: for (i=0; i<16; i+=2) 303: { 304: word32 b = scheduledKey[i]; 305: scheduledKey[i] = scheduledKey[32-2-i]; 306: scheduledKey[32-2-i] = b; 307: 308: b = scheduledKey[i+1]; 309: scheduledKey[i+1] = scheduledKey[32-1-i]; 310: scheduledKey[32-1-i] = b; 311: } 312: 313: burn (buffer, sizeof (buffer)); 314: } 315: 316: static void RawProcessBlock(word32 *l_, word32 *r_, const word32 *k) 317: { 318: word32 l = *l_, r = *r_; 319: const word32 *kptr=k; 320: unsigned i; 321: 322: for (i=0; i<8; i++) 323: { 324: word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; 325: l ^= Spbox[6][(work) & 0x3f] 326: ^ Spbox[4][(work >> 8) & 0x3f] 327: ^ Spbox[2][(work >> 16) & 0x3f] 328: ^ Spbox[0][(work >> 24) & 0x3f]; 329: work = r ^ kptr[4*i+1]; 330: l ^= Spbox[7][(work) & 0x3f] 331: ^ Spbox[5][(work >> 8) & 0x3f] 332: ^ Spbox[3][(work >> 16) & 0x3f] 333: ^ Spbox[1][(work >> 24) & 0x3f]; 334: 335: work = rotrFixed(l, 4U) ^ kptr[4*i+2]; 336: r ^= Spbox[6][(work) & 0x3f] 337: ^ Spbox[4][(work >> 8) & 0x3f] 338: ^ Spbox[2][(work >> 16) & 0x3f] 339: ^ Spbox[0][(work >> 24) & 0x3f]; 340: work = l ^ kptr[4*i+3]; 341: r ^= Spbox[7][(work) & 0x3f] 342: ^ Spbox[5][(work >> 8) & 0x3f] 343: ^ Spbox[3][(work >> 16) & 0x3f] 344: ^ Spbox[1][(work >> 24) & 0x3f]; 345: } 346: 347: *l_ = l; *r_ = r; 348: } 349: 350: void TripleDesSetKey (const byte *userKey, unsigned int length, TDES_KEY *ks) 351: { 352: RawSetKey (1, userKey + 0, ks->k1); 353: RawSetKey (1, userKey + 8, ks->k2); 354: RawSetKey (1, userKey + 16, ks->k3); 355: RawSetKey (0, userKey + 16, ks->k1d); 356: RawSetKey (0, userKey + 8, ks->k2d); 357: RawSetKey (0, userKey + 0, ks->k3d); 358: } 359: 360: void TripleDesEncrypt (byte *inBlock, byte *outBlock, TDES_KEY *key, int encrypt) 361: { 362: word32 left = BE32 (((word32 *)inBlock)[0]); 363: word32 right = BE32 (((word32 *)inBlock)[1]); 364: word32 work; 365: 366: right = rotlFixed(right, 4U); 367: work = (left ^ right) & 0xf0f0f0f0; 368: left ^= work; 369: right = rotrFixed(right^work, 20U); 370: work = (left ^ right) & 0xffff0000; 371: left ^= work; 372: right = rotrFixed(right^work, 18U); 373: work = (left ^ right) & 0x33333333; 374: left ^= work; 375: right = rotrFixed(right^work, 6U); 376: work = (left ^ right) & 0x00ff00ff; 377: left ^= work; 378: right = rotlFixed(right^work, 9U); 379: work = (left ^ right) & 0xaaaaaaaa; 380: left = rotlFixed(left^work, 1U); 381: right ^= work; 382: 383: RawProcessBlock (&left, &right, encrypt ? key->k1 : key->k1d); 384: RawProcessBlock (&right, &left, !encrypt ? key->k2 : key->k2d); 385: RawProcessBlock (&left, &right, encrypt ? key->k3 : key->k3d); 386: 387: right = rotrFixed(right, 1U); 388: work = (left ^ right) & 0xaaaaaaaa; 389: right ^= work; 390: left = rotrFixed(left^work, 9U); 391: work = (left ^ right) & 0x00ff00ff; 392: right ^= work; 393: left = rotlFixed(left^work, 6U); 394: work = (left ^ right) & 0x33333333; 395: right ^= work; 396: left = rotlFixed(left^work, 18U); 397: work = (left ^ right) & 0xffff0000; 398: right ^= work; 399: left = rotlFixed(left^work, 20U); 400: work = (left ^ right) & 0xf0f0f0f0; 401: right ^= work; 402: left = rotrFixed(left^work, 4U); 403: 404: ((word32 *)outBlock)[0] = BE32 (right); 405: ((word32 *)outBlock)[1] = BE32 (left); 406: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.