|
|
1.1 ! root 1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org ! 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.