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