|
|
1.1.1.6 ! root 1: /* Legal Notice: The source code contained in this file has been derived from ! 2: the source code of Encryption for the Masses 2.02a, which is Copyright (c) ! 3: 1998-99 Paul Le Roux and which is covered by the 'License Agreement for ! 4: Encryption for the Masses'. Modifications and additions to that source code ! 5: contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and ! 6: Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0 ! 7: the full text of which is contained in the file License.txt included in ! 8: TrueCrypt binary and source code distribution archives. */ 1.1 root 9: 1.1.1.6 ! root 10: #include "Tcdefs.h" 1.1 root 11: 12: #include <memory.h> 1.1.1.6 ! root 13: #include "Sha1.h" ! 14: #include "Rmd160.h" ! 15: #include "Whirlpool.h" ! 16: #include "Pkcs5.h" ! 17: #include "Crypto.h" 1.1 root 18: 19: void truncate 20: ( 21: char *d1, /* data to be truncated */ 22: char *d2, /* truncated data */ 23: int len /* length in bytes to keep */ 24: ) 25: { 26: int i; 27: for (i = 0; i < len; i++) 28: d2[i] = d1[i]; 29: } 30: 1.1.1.6 ! root 31: void hmac_sha1 ! 32: ( 1.1 root 33: char *k, /* secret key */ 34: int lk, /* length of the key in bytes */ 35: char *d, /* data */ 36: int ld, /* length of data in bytes */ 37: char *out, /* output buffer, at least "t" bytes */ 38: int t 39: ) 40: { 1.1.1.6 ! root 41: sha1_ctx ictx, octx; ! 42: char isha[SHA1_DIGESTSIZE], osha[SHA1_DIGESTSIZE]; ! 43: char key[SHA1_DIGESTSIZE]; ! 44: char buf[SHA1_BLOCKSIZE]; 1.1 root 45: int i; 46: 1.1.1.6 ! root 47: /* If the key is longer than the hash algorithm block size, ! 48: let key = sha1(key), as per HMAC specifications. */ ! 49: if (lk > SHA1_BLOCKSIZE) ! 50: { ! 51: sha1_ctx tctx; ! 52: ! 53: sha1_begin (&tctx); ! 54: sha1_hash ((unsigned char *) k, lk, &tctx); ! 55: sha1_end ((unsigned char *) key, &tctx); 1.1 root 56: 57: k = key; 1.1.1.6 ! root 58: lk = SHA1_DIGESTSIZE; ! 59: ! 60: memset (&tctx, 0, sizeof(tctx)); // Prevent leaks 1.1 root 61: } 62: 63: /**** Inner Digest ****/ 64: 1.1.1.6 ! root 65: sha1_begin (&ictx); 1.1 root 66: 67: /* Pad the key for inner digest */ 68: for (i = 0; i < lk; ++i) 69: buf[i] = (char) (k[i] ^ 0x36); 1.1.1.6 ! root 70: for (i = lk; i < SHA1_BLOCKSIZE; ++i) 1.1 root 71: buf[i] = 0x36; 72: 1.1.1.6 ! root 73: sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &ictx); ! 74: sha1_hash ((unsigned char *) d, ld, &ictx); 1.1 root 75: 1.1.1.6 ! root 76: sha1_end ((unsigned char *) isha, &ictx); 1.1 root 77: 78: /**** Outter Digest ****/ 79: 1.1.1.6 ! root 80: sha1_begin (&octx); 1.1 root 81: 82: for (i = 0; i < lk; ++i) 83: buf[i] = (char) (k[i] ^ 0x5C); 1.1.1.6 ! root 84: for (i = lk; i < SHA1_BLOCKSIZE; ++i) 1.1 root 85: buf[i] = 0x5C; 86: 1.1.1.6 ! root 87: sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &octx); ! 88: sha1_hash ((unsigned char *) isha, SHA1_DIGESTSIZE, &octx); 1.1 root 89: 1.1.1.6 ! root 90: sha1_end ((unsigned char *) osha, &octx); 1.1 root 91: 92: /* truncate and print the results */ 1.1.1.6 ! root 93: t = t > SHA1_DIGESTSIZE ? SHA1_DIGESTSIZE : t; 1.1 root 94: truncate (osha, out, t); 1.1.1.6 ! root 95: ! 96: /* Prevent leaks */ ! 97: memset (&ictx, 0, sizeof(ictx)); ! 98: memset (&octx, 0, sizeof(octx)); ! 99: memset (isha, 0, sizeof(isha)); ! 100: memset (osha, 0, sizeof(osha)); ! 101: memset (buf, 0, sizeof(buf)); ! 102: memset (key, 0, sizeof(key)); 1.1 root 103: } 104: 105: 1.1.1.6 ! root 106: void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) 1.1 root 107: { 1.1.1.6 ! root 108: char j[SHA1_DIGESTSIZE], k[SHA1_DIGESTSIZE]; 1.1 root 109: char init[128]; 110: char counter[4]; 111: int c, i; 112: 113: /* iteration 1 */ 114: memset (counter, 0, 4); 115: counter[3] = (char) b; 116: memcpy (init, salt, salt_len); /* salt */ 117: memcpy (&init[salt_len], counter, 4); /* big-endian block number */ 1.1.1.6 ! root 118: hmac_sha1 (pwd, pwd_len, init, salt_len + 4, j, SHA1_DIGESTSIZE); ! 119: memcpy (u, j, SHA1_DIGESTSIZE); 1.1 root 120: 121: /* remaining iterations */ 122: for (c = 1; c < iterations; c++) 123: { 1.1.1.6 ! root 124: hmac_sha1 (pwd, pwd_len, j, SHA1_DIGESTSIZE, k, SHA1_DIGESTSIZE); ! 125: for (i = 0; i < SHA1_DIGESTSIZE; i++) 1.1 root 126: { 127: u[i] ^= k[i]; 128: j[i] = k[i]; 129: } 130: } 1.1.1.6 ! root 131: ! 132: /* Prevent possible leaks. */ ! 133: memset (j, 0, sizeof(j)); ! 134: memset (k, 0, sizeof(k)); 1.1 root 135: } 136: 1.1.1.6 ! root 137: void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) 1.1 root 138: { 1.1.1.6 ! root 139: char u[SHA1_DIGESTSIZE]; 1.1 root 140: int b, l, r; 141: 1.1.1.6 ! root 142: if (dklen % SHA1_DIGESTSIZE) 1.1 root 143: { 1.1.1.6 ! root 144: l = 1 + dklen / SHA1_DIGESTSIZE; 1.1 root 145: } 146: else 147: { 1.1.1.6 ! root 148: l = dklen / SHA1_DIGESTSIZE; 1.1 root 149: } 150: 1.1.1.6 ! root 151: r = dklen - (l - 1) * SHA1_DIGESTSIZE; 1.1 root 152: 153: /* first l - 1 blocks */ 154: for (b = 1; b < l; b++) 155: { 1.1.1.6 ! root 156: derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); ! 157: memcpy (dk, u, SHA1_DIGESTSIZE); ! 158: dk += SHA1_DIGESTSIZE; 1.1 root 159: } 160: 161: /* last block */ 1.1.1.6 ! root 162: derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); 1.1 root 163: memcpy (dk, u, r); 164: 165: 1.1.1.6 ! root 166: /* Prevent possible leaks. */ ! 167: memset (u, 0, sizeof(u)); ! 168: } 1.1 root 169: 1.1.1.6 ! root 170: void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest) 1.1.1.3 root 171: { 172: RMD160_CTX context; 173: unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ 174: unsigned char k_opad[65]; /* outer padding - key XORd with opad */ 1.1.1.6 ! root 175: unsigned char tk[RIPEMD160_DIGESTSIZE]; 1.1.1.3 root 176: int i; 177: 1.1.1.6 ! root 178: /* If the key is longer than the hash algorithm block size, ! 179: let key = ripemd160(key), as per HMAC specifications. */ ! 180: if (keylen > RIPEMD160_BLOCKSIZE) ! 181: { 1.1.1.3 root 182: RMD160_CTX tctx; 183: 184: RMD160Init(&tctx); 185: RMD160Update(&tctx, key, keylen); 186: RMD160Final(tk, &tctx); 187: 188: key = tk; 1.1.1.6 ! root 189: keylen = RIPEMD160_DIGESTSIZE; ! 190: ! 191: memset (&tctx, 0, sizeof(tctx)); // Prevent leaks 1.1.1.3 root 192: } 193: 1.1.1.6 ! root 194: /* ! 195: ! 196: RMD160(K XOR opad, RMD160(K XOR ipad, text)) 1.1.1.3 root 197: 1.1.1.6 ! root 198: where K is an n byte key ! 199: ipad is the byte 0x36 repeated RIPEMD160_BLOCKSIZE times ! 200: opad is the byte 0x5c repeated RIPEMD160_BLOCKSIZE times ! 201: and text is the data being protected */ 1.1.1.3 root 202: 203: 1.1.1.6 ! root 204: /* start out by storing key in pads */ ! 205: memset(k_ipad, 0x36, sizeof(k_ipad)); 1.1.1.3 root 206: memset(k_opad, 0x5c, sizeof(k_opad)); 207: 1.1.1.6 ! root 208: /* XOR key with ipad and opad values */ ! 209: for (i=0; i<keylen; i++) ! 210: { 1.1.1.3 root 211: k_ipad[i] ^= key[i]; 212: k_opad[i] ^= key[i]; 213: } 214: 1.1.1.6 ! root 215: /* perform inner RIPEMD-160 */ 1.1.1.3 root 216: 217: RMD160Init(&context); /* init context for 1st pass */ 1.1.1.6 ! root 218: RMD160Update(&context, k_ipad, RIPEMD160_BLOCKSIZE); /* start with inner pad */ 1.1.1.3 root 219: RMD160Update(&context, input, len); /* then text of datagram */ 220: RMD160Final(digest, &context); /* finish up 1st pass */ 221: 1.1.1.6 ! root 222: /* perform outer RIPEMD-160 */ 1.1.1.3 root 223: RMD160Init(&context); /* init context for 2nd pass */ 1.1.1.6 ! root 224: RMD160Update(&context, k_opad, RIPEMD160_BLOCKSIZE); /* start with outer pad */ ! 225: /* results of 1st hash */ ! 226: RMD160Update(&context, digest, RIPEMD160_DIGESTSIZE); 1.1.1.3 root 227: RMD160Final(digest, &context); /* finish up 2nd pass */ 1.1 root 228: 1.1.1.6 ! root 229: /* Prevent possible leaks. */ ! 230: memset(k_ipad, 0, sizeof(k_ipad)); ! 231: memset(k_opad, 0, sizeof(k_opad)); ! 232: memset (tk, 0, sizeof(tk)); ! 233: memset (&context, 0, sizeof(context)); 1.1 root 234: } 235: 1.1.1.6 ! root 236: void derive_u_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) 1.1 root 237: { 1.1.1.6 ! root 238: char j[RIPEMD160_DIGESTSIZE], k[RIPEMD160_DIGESTSIZE]; 1.1 root 239: char init[128]; 240: char counter[4]; 241: int c, i; 242: 243: /* iteration 1 */ 244: memset (counter, 0, 4); 245: counter[3] = (char) b; 246: memcpy (init, salt, salt_len); /* salt */ 247: memcpy (&init[salt_len], counter, 4); /* big-endian block number */ 1.1.1.6 ! root 248: hmac_ripemd160 (pwd, pwd_len, init, salt_len + 4, j); ! 249: memcpy (u, j, RIPEMD160_DIGESTSIZE); 1.1 root 250: 251: /* remaining iterations */ 252: for (c = 1; c < iterations; c++) 253: { 1.1.1.6 ! root 254: hmac_ripemd160 (pwd, pwd_len, j, RIPEMD160_DIGESTSIZE, k); ! 255: for (i = 0; i < RIPEMD160_DIGESTSIZE; i++) 1.1 root 256: { 257: u[i] ^= k[i]; 258: j[i] = k[i]; 259: } 260: } 1.1.1.6 ! root 261: ! 262: /* Prevent possible leaks. */ ! 263: memset (j, 0, sizeof(j)); ! 264: memset (k, 0, sizeof(k)); 1.1 root 265: } 266: 1.1.1.6 ! root 267: void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) 1.1 root 268: { 1.1.1.6 ! root 269: char u[RIPEMD160_DIGESTSIZE]; 1.1 root 270: int b, l, r; 271: 1.1.1.6 ! root 272: if (dklen % RIPEMD160_DIGESTSIZE) 1.1 root 273: { 1.1.1.6 ! root 274: l = 1 + dklen / RIPEMD160_DIGESTSIZE; 1.1 root 275: } 276: else 277: { 1.1.1.6 ! root 278: l = dklen / RIPEMD160_DIGESTSIZE; 1.1 root 279: } 280: 1.1.1.6 ! root 281: r = dklen - (l - 1) * RIPEMD160_DIGESTSIZE; 1.1 root 282: 283: /* first l - 1 blocks */ 284: for (b = 1; b < l; b++) 285: { 1.1.1.6 ! root 286: derive_u_ripemd160 (pwd, pwd_len, salt, salt_len, iterations, u, b); ! 287: memcpy (dk, u, RIPEMD160_DIGESTSIZE); ! 288: dk += RIPEMD160_DIGESTSIZE; 1.1 root 289: } 290: 291: /* last block */ 1.1.1.6 ! root 292: derive_u_ripemd160 (pwd, pwd_len, salt, salt_len, iterations, u, b); 1.1 root 293: memcpy (dk, u, r); 1.1.1.6 ! root 294: ! 295: ! 296: /* Prevent possible leaks. */ ! 297: memset (u, 0, sizeof(u)); 1.1 root 298: } 299: 1.1.1.6 ! root 300: void hmac_whirlpool ! 301: ( ! 302: char *k, /* secret key */ ! 303: int lk, /* length of the key in bytes */ ! 304: char *d, /* data */ ! 305: int ld, /* length of data in bytes */ ! 306: char *out, /* output buffer, at least "t" bytes */ ! 307: int t ! 308: ) ! 309: { ! 310: WHIRLPOOL_CTX ictx, octx; ! 311: char iwhi[WHIRLPOOL_DIGESTSIZE], owhi[WHIRLPOOL_DIGESTSIZE]; ! 312: char key[WHIRLPOOL_DIGESTSIZE]; ! 313: char buf[WHIRLPOOL_BLOCKSIZE]; ! 314: int i; ! 315: ! 316: /* If the key is longer than the hash algorithm block size, ! 317: let key = whirlpool(key), as per HMAC specifications. */ ! 318: if (lk > WHIRLPOOL_BLOCKSIZE) ! 319: { ! 320: WHIRLPOOL_CTX tctx; ! 321: ! 322: WHIRLPOOL_init (&tctx); ! 323: WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); ! 324: WHIRLPOOL_finalize (&tctx, (unsigned char *) key); 1.1 root 325: 1.1.1.6 ! root 326: k = key; ! 327: lk = WHIRLPOOL_DIGESTSIZE; 1.1 root 328: 1.1.1.6 ! root 329: memset (&tctx, 0, sizeof(tctx)); // Prevent leaks ! 330: } 1.1 root 331: 1.1.1.6 ! root 332: /**** Inner Digest ****/ 1.1 root 333: 1.1.1.6 ! root 334: WHIRLPOOL_init (&ictx); 1.1 root 335: 1.1.1.6 ! root 336: /* Pad the key for inner digest */ ! 337: for (i = 0; i < lk; ++i) ! 338: buf[i] = (char) (k[i] ^ 0x36); ! 339: for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) ! 340: buf[i] = 0x36; 1.1 root 341: 1.1.1.6 ! root 342: WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &ictx); ! 343: WHIRLPOOL_add ((unsigned char *) d, ld * 8, &ictx); 1.1 root 344: 1.1.1.6 ! root 345: WHIRLPOOL_finalize (&ictx, (unsigned char *) iwhi); 1.1 root 346: 1.1.1.6 ! root 347: /**** Outter Digest ****/ 1.1.1.3 root 348: 1.1.1.6 ! root 349: WHIRLPOOL_init (&octx); 1.1.1.3 root 350: 1.1.1.6 ! root 351: for (i = 0; i < lk; ++i) ! 352: buf[i] = (char) (k[i] ^ 0x5C); ! 353: for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) ! 354: buf[i] = 0x5C; ! 355: ! 356: WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &octx); ! 357: WHIRLPOOL_add ((unsigned char *) iwhi, WHIRLPOOL_DIGESTSIZE * 8, &octx); 1.1.1.3 root 358: 1.1.1.6 ! root 359: WHIRLPOOL_finalize (&octx, (unsigned char *) owhi); ! 360: ! 361: /* truncate and print the results */ ! 362: t = t > WHIRLPOOL_DIGESTSIZE ? WHIRLPOOL_DIGESTSIZE : t; ! 363: truncate (owhi, out, t); ! 364: ! 365: /* Prevent possible leaks. */ ! 366: memset (&ictx, 0, sizeof(ictx)); ! 367: memset (&octx, 0, sizeof(octx)); ! 368: memset (owhi, 0, sizeof(owhi)); ! 369: memset (iwhi, 0, sizeof(iwhi)); ! 370: memset (buf, 0, sizeof(buf)); ! 371: memset (key, 0, sizeof(key)); ! 372: } ! 373: ! 374: void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) 1.1 root 375: { 1.1.1.6 ! root 376: char j[WHIRLPOOL_DIGESTSIZE], k[WHIRLPOOL_DIGESTSIZE]; ! 377: char init[128]; ! 378: char counter[4]; ! 379: int c, i; ! 380: ! 381: /* iteration 1 */ ! 382: memset (counter, 0, 4); ! 383: counter[3] = (char) b; ! 384: memcpy (init, salt, salt_len); /* salt */ ! 385: memcpy (&init[salt_len], counter, 4); /* big-endian block number */ ! 386: hmac_whirlpool (pwd, pwd_len, init, salt_len + 4, j, WHIRLPOOL_DIGESTSIZE); ! 387: memcpy (u, j, WHIRLPOOL_DIGESTSIZE); 1.1 root 388: 1.1.1.6 ! root 389: /* remaining iterations */ ! 390: for (c = 1; c < iterations; c++) 1.1 root 391: { 1.1.1.6 ! root 392: hmac_whirlpool (pwd, pwd_len, j, WHIRLPOOL_DIGESTSIZE, k, WHIRLPOOL_DIGESTSIZE); ! 393: for (i = 0; i < WHIRLPOOL_DIGESTSIZE; i++) ! 394: { ! 395: u[i] ^= k[i]; ! 396: j[i] = k[i]; ! 397: } 1.1 root 398: } 399: 1.1.1.6 ! root 400: /* Prevent possible leaks. */ ! 401: memset (j, 0, sizeof(j)); ! 402: memset (k, 0, sizeof(k)); 1.1 root 403: } 404: 1.1.1.6 ! root 405: void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) 1.1 root 406: { 1.1.1.6 ! root 407: char u[WHIRLPOOL_DIGESTSIZE]; ! 408: int b, l, r; ! 409: ! 410: if (dklen % WHIRLPOOL_DIGESTSIZE) ! 411: { ! 412: l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; ! 413: } ! 414: else 1.1 root 415: { 1.1.1.6 ! root 416: l = dklen / WHIRLPOOL_DIGESTSIZE; 1.1 root 417: } 418: 1.1.1.6 ! root 419: r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; 1.1 root 420: 1.1.1.6 ! root 421: /* first l - 1 blocks */ ! 422: for (b = 1; b < l; b++) ! 423: { ! 424: derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); ! 425: memcpy (dk, u, WHIRLPOOL_DIGESTSIZE); ! 426: dk += WHIRLPOOL_DIGESTSIZE; ! 427: } 1.1 root 428: 1.1.1.6 ! root 429: /* last block */ ! 430: derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); ! 431: memcpy (dk, u, r); 1.1 root 432: 433: 1.1.1.6 ! root 434: /* Prevent possible leaks. */ ! 435: memset (u, 0, sizeof(u)); ! 436: } 1.1 root 437: 438: 1.1.1.6 ! root 439: int get_pkcs5_iteration_count (int pkcs5_prf_id) ! 440: { ! 441: switch (pkcs5_prf_id) ! 442: { ! 443: case SHA1: return 2000; ! 444: case RIPEMD160: return 2000; ! 445: case WHIRLPOOL: return 1000; ! 446: default: return 0; ! 447: } 1.1 root 448: } 449: 1.1.1.6 ! root 450: char *get_pkcs5_prf_name (int pkcs5_prf_id) ! 451: { ! 452: switch (pkcs5_prf_id) ! 453: { ! 454: case SHA1: return "HMAC-SHA-1"; ! 455: case RIPEMD160: return "HMAC-RIPEMD-160"; ! 456: case WHIRLPOOL: return "HMAC-Whirlpool"; ! 457: default: return "Unknown"; ! 458: } ! 459: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.