|
|
1.1.1.3 ! root 1: /* The source code contained in this file has been derived from the source code ! 2: of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and ! 3: additions to that source code contained in this file are Copyright (c) 2004 ! 4: TrueCrypt Team and Copyright (c) 2004 TrueCrypt Foundation. Unmodified ! 5: parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation ! 6: release. Please see the file license.txt for full license details. */ 1.1 root 7: 8: #include "TCdefs.h" 9: 10: #include <memory.h> 11: #include "sha1.h" 1.1.1.3 ! root 12: #include "rmd160.h" 1.1 root 13: #include "pkcs5.h" 14: 15: void truncate 16: ( 17: char *d1, /* data to be truncated */ 18: char *d2, /* truncated data */ 19: int len /* length in bytes to keep */ 20: ) 21: { 22: int i; 23: for (i = 0; i < len; i++) 24: d2[i] = d1[i]; 25: } 26: 27: 28: /* Function to compute the digest */ 29: void 30: hmac_sha 31: ( 32: char *k, /* secret key */ 33: int lk, /* length of the key in bytes */ 34: char *d, /* data */ 35: int ld, /* length of data in bytes */ 36: char *out, /* output buffer, at least "t" bytes */ 37: int t 38: ) 39: { 40: SHA1_CTX ictx, octx; 41: char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE]; 42: char key[SHA_DIGESTSIZE]; 43: char buf[SHA_BLOCKSIZE]; 44: int i; 45: 46: if (lk > SHA_BLOCKSIZE) 47: { 48: 49: SHA1_CTX tctx; 50: 51: SHA1Init (&tctx); 52: SHA1Update (&tctx, (unsigned char *) k, lk); 53: SHA1Final ((unsigned char *) key, &tctx); 54: 55: k = key; 56: lk = SHA_DIGESTSIZE; 57: } 58: 59: /**** Inner Digest ****/ 60: 61: SHA1Init (&ictx); 62: 63: /* Pad the key for inner digest */ 64: for (i = 0; i < lk; ++i) 65: buf[i] = (char) (k[i] ^ 0x36); 66: for (i = lk; i < SHA_BLOCKSIZE; ++i) 67: buf[i] = 0x36; 68: 69: SHA1Update (&ictx, (unsigned char *) buf, SHA_BLOCKSIZE); 70: SHA1Update (&ictx, (unsigned char *) d, ld); 71: 72: SHA1Final ((unsigned char *) isha, &ictx); 73: 74: /**** Outter Digest ****/ 75: 76: SHA1Init (&octx); 77: 78: for (i = 0; i < lk; ++i) 79: buf[i] = (char) (k[i] ^ 0x5C); 80: for (i = lk; i < SHA_BLOCKSIZE; ++i) 81: buf[i] = 0x5C; 82: 83: SHA1Update (&octx, (unsigned char *) buf, SHA_BLOCKSIZE); 84: SHA1Update (&octx, (unsigned char *) isha, SHA_DIGESTSIZE); 85: 86: SHA1Final ((unsigned char *) osha, &octx); 87: 88: /* truncate and print the results */ 89: t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t; 90: truncate (osha, out, t); 91: } 92: 93: 94: void 95: derive_u_sha (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) 96: { 97: char j[SHA_DIGESTSIZE], k[SHA_DIGESTSIZE]; 98: char init[128]; 99: char counter[4]; 100: int c, i; 101: 102: /* iteration 1 */ 103: memset (counter, 0, 4); 104: counter[3] = (char) b; 105: memcpy (init, salt, salt_len); /* salt */ 106: memcpy (&init[salt_len], counter, 4); /* big-endian block number */ 107: hmac_sha (pwd, pwd_len, init, salt_len + 4, j, SHA_DIGESTSIZE); 108: memcpy (u, j, SHA_DIGESTSIZE); 109: 110: /* remaining iterations */ 111: for (c = 1; c < iterations; c++) 112: { 113: hmac_sha (pwd, pwd_len, j, SHA_DIGESTSIZE, k, SHA_DIGESTSIZE); 114: for (i = 0; i < SHA_DIGESTSIZE; i++) 115: { 116: u[i] ^= k[i]; 117: j[i] = k[i]; 118: } 119: } 120: } 121: 122: void 123: derive_sha_key (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) 124: { 125: char u[SHA_DIGESTSIZE]; 126: int b, l, r; 127: 128: if (dklen % SHA_DIGESTSIZE) 129: { 130: l = 1 + dklen / SHA_DIGESTSIZE; 131: } 132: else 133: { 134: l = dklen / SHA_DIGESTSIZE; 135: } 136: 137: r = dklen - (l - 1) * SHA_DIGESTSIZE; 138: 139: /* first l - 1 blocks */ 140: for (b = 1; b < l; b++) 141: { 142: derive_u_sha (pwd, pwd_len, salt, salt_len, iterations, u, b); 143: memcpy (dk, u, SHA_DIGESTSIZE); 144: dk += SHA_DIGESTSIZE; 145: } 146: 147: /* last block */ 148: derive_u_sha (pwd, pwd_len, salt, salt_len, iterations, u, b); 149: memcpy (dk, u, r); 150: } 151: 152: 1.1.1.3 ! root 153: #define RMD160_DIGESTSIZE 20 1.1 root 154: 1.1.1.3 ! root 155: void hmac_rmd160 (unsigned char *key, int keylen, unsigned char *input, int len, unsigned char *digest) ! 156: { ! 157: RMD160_CTX context; ! 158: unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ ! 159: unsigned char k_opad[65]; /* outer padding - key XORd with opad */ ! 160: unsigned char tk[RMD160_DIGESTSIZE]; ! 161: int i; ! 162: ! 163: /* if key is longer than 64 bytes reset it to key=SHA1(key) */ ! 164: if (keylen > 64) { ! 165: RMD160_CTX tctx; ! 166: ! 167: RMD160Init(&tctx); ! 168: RMD160Update(&tctx, key, keylen); ! 169: RMD160Final(tk, &tctx); ! 170: ! 171: key = tk; ! 172: keylen = RMD160_DIGESTSIZE; ! 173: } ! 174: ! 175: /* The HMAC_SHA1 transform looks like: ! 176: ! 177: RMD160(K XOR opad, RMD160(K XOR ipad, text)) ! 178: ! 179: where K is an n byte key ! 180: ipad is the byte 0x36 repeated 64 times ! 181: opad is the byte 0x5c repeated 64 times ! 182: and text is the data being protected */ ! 183: ! 184: /* start out by storing key in pads */ ! 185: memset(k_ipad, 0x36, sizeof(k_ipad)); ! 186: memset(k_opad, 0x5c, sizeof(k_opad)); ! 187: ! 188: /* XOR key with ipad and opad values */ ! 189: for (i=0; i<keylen; i++) { ! 190: k_ipad[i] ^= key[i]; ! 191: k_opad[i] ^= key[i]; ! 192: } ! 193: ! 194: /* perform inner RIPEMD-160 */ ! 195: ! 196: RMD160Init(&context); /* init context for 1st pass */ ! 197: RMD160Update(&context, k_ipad, 64); /* start with inner pad */ ! 198: RMD160Update(&context, input, len); /* then text of datagram */ ! 199: RMD160Final(digest, &context); /* finish up 1st pass */ ! 200: ! 201: /* perform outer RIPEMD-160 */ ! 202: RMD160Init(&context); /* init context for 2nd pass */ ! 203: RMD160Update(&context, k_opad, 64); /* start with outer pad */ ! 204: /* then results of 1st hash */ ! 205: RMD160Update(&context, digest, RMD160_DIGESTSIZE); ! 206: RMD160Final(digest, &context); /* finish up 2nd pass */ 1.1 root 207: 1.1.1.3 ! root 208: memset(k_ipad, 0x00, sizeof(k_ipad)); ! 209: memset(k_opad, 0x00, sizeof(k_opad)); 1.1 root 210: } 211: 212: void 1.1.1.3 ! root 213: derive_u_rmd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) 1.1 root 214: { 1.1.1.3 ! root 215: char j[RMD160_DIGESTSIZE], k[RMD160_DIGESTSIZE]; 1.1 root 216: char init[128]; 217: char counter[4]; 218: int c, i; 219: 220: /* iteration 1 */ 221: memset (counter, 0, 4); 222: counter[3] = (char) b; 223: memcpy (init, salt, salt_len); /* salt */ 224: memcpy (&init[salt_len], counter, 4); /* big-endian block number */ 1.1.1.3 ! root 225: hmac_rmd160 (pwd, pwd_len, init, salt_len + 4, j); ! 226: memcpy (u, j, RMD160_DIGESTSIZE); 1.1 root 227: 228: /* remaining iterations */ 229: for (c = 1; c < iterations; c++) 230: { 1.1.1.3 ! root 231: hmac_rmd160 (pwd, pwd_len, j, RMD160_DIGESTSIZE, k); ! 232: for (i = 0; i < RMD160_DIGESTSIZE; i++) 1.1 root 233: { 234: u[i] ^= k[i]; 235: j[i] = k[i]; 236: } 237: } 238: } 239: 240: void 1.1.1.3 ! root 241: derive_rmd160_key (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) 1.1 root 242: { 1.1.1.3 ! root 243: char u[RMD160_DIGESTSIZE]; 1.1 root 244: int b, l, r; 245: 1.1.1.3 ! root 246: if (dklen % RMD160_DIGESTSIZE) 1.1 root 247: { 1.1.1.3 ! root 248: l = 1 + dklen / RMD160_DIGESTSIZE; 1.1 root 249: } 250: else 251: { 1.1.1.3 ! root 252: l = dklen / RMD160_DIGESTSIZE; 1.1 root 253: } 254: 1.1.1.3 ! root 255: r = dklen - (l - 1) * RMD160_DIGESTSIZE; 1.1 root 256: 257: /* first l - 1 blocks */ 258: for (b = 1; b < l; b++) 259: { 1.1.1.3 ! root 260: derive_u_rmd160 (pwd, pwd_len, salt, salt_len, iterations, u, b); ! 261: memcpy (dk, u, RMD160_DIGESTSIZE); ! 262: dk += RMD160_DIGESTSIZE; 1.1 root 263: } 264: 265: /* last block */ 1.1.1.3 ! root 266: derive_u_rmd160 (pwd, pwd_len, salt, salt_len, iterations, u, b); 1.1 root 267: memcpy (dk, u, r); 268: } 269: 270: 271: 272: /* rfc2104 & 2202 */ 273: 274: char *hmac_test_keys[3] = 275: { 276: "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 277: "Jefe", 278: "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" 279: }; 280: 281: 282: char *hmac_test_data[3] = 283: { 284: "Hi There", 285: "what do ya want for nothing?", 286: "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 287: "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 288: "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" 289: }; 290: 291: 292: char *hmac_sha_test_vectors[3] = 293: { 294: "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00", 295: "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79", 296: "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" 297: }; 298: 1.1.1.3 ! root 299: char *hmac_rmd160_test_keys[] = ! 300: { ! 301: "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x01\x23\x45\x67", ! 302: "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10\x00\x11\x22\x33" ! 303: }; ! 304: ! 305: char *hmac_rmd160_test_data[] = ! 306: { ! 307: "message digest", ! 308: "12345678901234567890123456789012345678901234567890123456789012345678901234567890" ! 309: }; ! 310: ! 311: char *hmac_rmd160_test_vectors[] = ! 312: { ! 313: "\xf8\x36\x62\xcc\x8d\x33\x9c\x22\x7e\x60\x0f\xcd\x63\x6c\x57\xd2\x57\x1b\x1c\x34", ! 314: "\x85\xf1\x64\x70\x3e\x61\xa6\x31\x31\xbe\x7e\x45\x95\x8e\x07\x94\x12\x39\x04\xf9" ! 315: }; ! 316: 1.1 root 317: BOOL 318: test_hmac_sha1 () 319: { 320: BOOL bOK = TRUE; 321: int i; 322: 323: for (i = 0; i < 3; i++) 324: { 325: char digest[SHA_DIGESTSIZE]; 326: hmac_sha (hmac_test_keys[i], strlen (hmac_test_keys[i]), hmac_test_data[i], strlen (hmac_test_data[i]), digest, SHA_DIGESTSIZE); 327: if (memcmp (digest, hmac_sha_test_vectors[i], SHA_DIGESTSIZE) != 0) 328: return FALSE; 329: } 330: 331: return TRUE; 332: } 333: 334: BOOL 1.1.1.3 ! root 335: test_hmac_rmd160 () 1.1 root 336: { 337: int i; 1.1.1.3 ! root 338: for (i = 0; i < sizeof (hmac_rmd160_test_data) / sizeof(char *); i++) 1.1 root 339: { 1.1.1.3 ! root 340: char digest[RMD160_DIGESTSIZE]; ! 341: hmac_rmd160 (hmac_rmd160_test_keys[i], 20, hmac_rmd160_test_data[i], strlen (hmac_rmd160_test_data[i]), digest); ! 342: if (memcmp (digest, hmac_rmd160_test_vectors[i], RMD160_DIGESTSIZE) != 0) 1.1 root 343: return FALSE; 344: } 345: 346: return TRUE; 347: } 348: 349: BOOL 350: test_pkcs5 () 351: { 352: char dk[4]; 353: 354: /* First make sure the hmacs are ok */ 355: if (test_hmac_sha1 ()== FALSE) 356: return FALSE; 1.1.1.3 ! root 357: if (test_hmac_rmd160 ()== FALSE) 1.1 root 358: return FALSE; 359: 360: /* Next check the sha1 with pkcs5 */ 361: derive_sha_key ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4); 362: if (memcmp (dk, "\x5c\x75\xce\xf0", 4) != 0) 363: return FALSE; 364: 1.1.1.3 ! root 365: /* Next check ripemd160 with pkcs5 */ ! 366: derive_rmd160_key ("password", 8, "\x12\x34\x56\x78", 4, 2000, dk, 4); ! 367: if (memcmp (dk, "\xc5\x6b\x27\xdf", 4) != 0) 1.1 root 368: return FALSE; 369: 370: return TRUE; 371: 372: } 373:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.