|
|
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
1.1.1.5 ! root 3: additions to that source code contained in this file are Copyright (c) 2004-2005
1.1.1.4 root 4: TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
1.1.1.3 root 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 */
1.1.1.4 root 366: derive_rmd160_key ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
367: if (memcmp (dk, "\x7a\x3d\x7c\x03", 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.