|
|
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.