4 * MD5 implementation for PuTTY. Written directly from the spec by
\r
8 /* ----------------------------------------------------------------------
\r
9 * Core MD5 algorithm: processes 16-word blocks into a message digest.
\r
12 #define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) )
\r
13 #define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) )
\r
14 #define H(x,y,z) ( (x) ^ (y) ^ (z) )
\r
15 #define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) )
\r
17 #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
\r
19 #define subround(f,w,x,y,z,k,s,ti) \
\r
20 w = x + rol(w + f(x,y,z) + block[k] + ti, s)
\r
22 static void MD5_Core_Init(MD5_Core_State * s)
\r
24 s->h[0] = 0x67452301;
\r
25 s->h[1] = 0xefcdab89;
\r
26 s->h[2] = 0x98badcfe;
\r
27 s->h[3] = 0x10325476;
\r
30 static void MD5_Block(MD5_Core_State * s, uint32 * block)
\r
39 subround(F, a, b, c, d, 0, 7, 0xd76aa478);
\r
40 subround(F, d, a, b, c, 1, 12, 0xe8c7b756);
\r
41 subround(F, c, d, a, b, 2, 17, 0x242070db);
\r
42 subround(F, b, c, d, a, 3, 22, 0xc1bdceee);
\r
43 subround(F, a, b, c, d, 4, 7, 0xf57c0faf);
\r
44 subround(F, d, a, b, c, 5, 12, 0x4787c62a);
\r
45 subround(F, c, d, a, b, 6, 17, 0xa8304613);
\r
46 subround(F, b, c, d, a, 7, 22, 0xfd469501);
\r
47 subround(F, a, b, c, d, 8, 7, 0x698098d8);
\r
48 subround(F, d, a, b, c, 9, 12, 0x8b44f7af);
\r
49 subround(F, c, d, a, b, 10, 17, 0xffff5bb1);
\r
50 subround(F, b, c, d, a, 11, 22, 0x895cd7be);
\r
51 subround(F, a, b, c, d, 12, 7, 0x6b901122);
\r
52 subround(F, d, a, b, c, 13, 12, 0xfd987193);
\r
53 subround(F, c, d, a, b, 14, 17, 0xa679438e);
\r
54 subround(F, b, c, d, a, 15, 22, 0x49b40821);
\r
55 subround(G, a, b, c, d, 1, 5, 0xf61e2562);
\r
56 subround(G, d, a, b, c, 6, 9, 0xc040b340);
\r
57 subround(G, c, d, a, b, 11, 14, 0x265e5a51);
\r
58 subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
\r
59 subround(G, a, b, c, d, 5, 5, 0xd62f105d);
\r
60 subround(G, d, a, b, c, 10, 9, 0x02441453);
\r
61 subround(G, c, d, a, b, 15, 14, 0xd8a1e681);
\r
62 subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
\r
63 subround(G, a, b, c, d, 9, 5, 0x21e1cde6);
\r
64 subround(G, d, a, b, c, 14, 9, 0xc33707d6);
\r
65 subround(G, c, d, a, b, 3, 14, 0xf4d50d87);
\r
66 subround(G, b, c, d, a, 8, 20, 0x455a14ed);
\r
67 subround(G, a, b, c, d, 13, 5, 0xa9e3e905);
\r
68 subround(G, d, a, b, c, 2, 9, 0xfcefa3f8);
\r
69 subround(G, c, d, a, b, 7, 14, 0x676f02d9);
\r
70 subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
\r
71 subround(H, a, b, c, d, 5, 4, 0xfffa3942);
\r
72 subround(H, d, a, b, c, 8, 11, 0x8771f681);
\r
73 subround(H, c, d, a, b, 11, 16, 0x6d9d6122);
\r
74 subround(H, b, c, d, a, 14, 23, 0xfde5380c);
\r
75 subround(H, a, b, c, d, 1, 4, 0xa4beea44);
\r
76 subround(H, d, a, b, c, 4, 11, 0x4bdecfa9);
\r
77 subround(H, c, d, a, b, 7, 16, 0xf6bb4b60);
\r
78 subround(H, b, c, d, a, 10, 23, 0xbebfbc70);
\r
79 subround(H, a, b, c, d, 13, 4, 0x289b7ec6);
\r
80 subround(H, d, a, b, c, 0, 11, 0xeaa127fa);
\r
81 subround(H, c, d, a, b, 3, 16, 0xd4ef3085);
\r
82 subround(H, b, c, d, a, 6, 23, 0x04881d05);
\r
83 subround(H, a, b, c, d, 9, 4, 0xd9d4d039);
\r
84 subround(H, d, a, b, c, 12, 11, 0xe6db99e5);
\r
85 subround(H, c, d, a, b, 15, 16, 0x1fa27cf8);
\r
86 subround(H, b, c, d, a, 2, 23, 0xc4ac5665);
\r
87 subround(I, a, b, c, d, 0, 6, 0xf4292244);
\r
88 subround(I, d, a, b, c, 7, 10, 0x432aff97);
\r
89 subround(I, c, d, a, b, 14, 15, 0xab9423a7);
\r
90 subround(I, b, c, d, a, 5, 21, 0xfc93a039);
\r
91 subround(I, a, b, c, d, 12, 6, 0x655b59c3);
\r
92 subround(I, d, a, b, c, 3, 10, 0x8f0ccc92);
\r
93 subround(I, c, d, a, b, 10, 15, 0xffeff47d);
\r
94 subround(I, b, c, d, a, 1, 21, 0x85845dd1);
\r
95 subround(I, a, b, c, d, 8, 6, 0x6fa87e4f);
\r
96 subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
\r
97 subround(I, c, d, a, b, 6, 15, 0xa3014314);
\r
98 subround(I, b, c, d, a, 13, 21, 0x4e0811a1);
\r
99 subround(I, a, b, c, d, 4, 6, 0xf7537e82);
\r
100 subround(I, d, a, b, c, 11, 10, 0xbd3af235);
\r
101 subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
\r
102 subround(I, b, c, d, a, 9, 21, 0xeb86d391);
\r
110 /* ----------------------------------------------------------------------
\r
111 * Outer MD5 algorithm: take an arbitrary length byte string,
\r
112 * convert it into 16-word blocks with the prescribed padding at
\r
113 * the end, and pass those blocks to the core MD5 algorithm.
\r
118 void MD5Init(struct MD5Context *s)
\r
120 MD5_Core_Init(&s->core);
\r
122 s->lenhi = s->lenlo = 0;
\r
125 void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len)
\r
127 unsigned char *q = (unsigned char *) p;
\r
128 uint32 wordblock[16];
\r
133 * Update the length field.
\r
136 s->lenhi += (s->lenlo < lenw);
\r
138 if (s->blkused + len < BLKSIZE) {
\r
140 * Trivial case: just add to the block.
\r
142 memcpy(s->block + s->blkused, q, len);
\r
146 * We must complete and process at least one block.
\r
148 while (s->blkused + len >= BLKSIZE) {
\r
149 memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
\r
150 q += BLKSIZE - s->blkused;
\r
151 len -= BLKSIZE - s->blkused;
\r
152 /* Now process the block. Gather bytes little-endian into words */
\r
153 for (i = 0; i < 16; i++) {
\r
155 (((uint32) s->block[i * 4 + 3]) << 24) |
\r
156 (((uint32) s->block[i * 4 + 2]) << 16) |
\r
157 (((uint32) s->block[i * 4 + 1]) << 8) |
\r
158 (((uint32) s->block[i * 4 + 0]) << 0);
\r
160 MD5_Block(&s->core, wordblock);
\r
163 memcpy(s->block, q, len);
\r
168 void MD5Final(unsigned char output[16], struct MD5Context *s)
\r
172 unsigned char c[64];
\r
173 uint32 lenhi, lenlo;
\r
175 if (s->blkused >= 56)
\r
176 pad = 56 + 64 - s->blkused;
\r
178 pad = 56 - s->blkused;
\r
180 lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
\r
181 lenlo = (s->lenlo << 3);
\r
185 MD5Update(s, c, pad);
\r
187 c[7] = (lenhi >> 24) & 0xFF;
\r
188 c[6] = (lenhi >> 16) & 0xFF;
\r
189 c[5] = (lenhi >> 8) & 0xFF;
\r
190 c[4] = (lenhi >> 0) & 0xFF;
\r
191 c[3] = (lenlo >> 24) & 0xFF;
\r
192 c[2] = (lenlo >> 16) & 0xFF;
\r
193 c[1] = (lenlo >> 8) & 0xFF;
\r
194 c[0] = (lenlo >> 0) & 0xFF;
\r
196 MD5Update(s, c, 8);
\r
198 for (i = 0; i < 4; i++) {
\r
199 output[4 * i + 3] = (s->core.h[i] >> 24) & 0xFF;
\r
200 output[4 * i + 2] = (s->core.h[i] >> 16) & 0xFF;
\r
201 output[4 * i + 1] = (s->core.h[i] >> 8) & 0xFF;
\r
202 output[4 * i + 0] = (s->core.h[i] >> 0) & 0xFF;
\r
206 void MD5Simple(void const *p, unsigned len, unsigned char output[16])
\r
208 struct MD5Context s;
\r
211 MD5Update(&s, (unsigned char const *)p, len);
\r
212 MD5Final(output, &s);
\r
215 /* ----------------------------------------------------------------------
\r
216 * The above is the MD5 algorithm itself. Now we implement the
\r
217 * HMAC wrapper on it.
\r
219 * Some of these functions are exported directly, because they are
\r
220 * useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5).
\r
223 void *hmacmd5_make_context(void)
\r
225 return snewn(3, struct MD5Context);
\r
228 void hmacmd5_free_context(void *handle)
\r
233 void hmacmd5_key(void *handle, void const *keyv, int len)
\r
235 struct MD5Context *keys = (struct MD5Context *)handle;
\r
236 unsigned char foo[64];
\r
237 unsigned char const *key = (unsigned char const *)keyv;
\r
240 memset(foo, 0x36, 64);
\r
241 for (i = 0; i < len && i < 64; i++)
\r
244 MD5Update(&keys[0], foo, 64);
\r
246 memset(foo, 0x5C, 64);
\r
247 for (i = 0; i < len && i < 64; i++)
\r
250 MD5Update(&keys[1], foo, 64);
\r
252 memset(foo, 0, 64); /* burn the evidence */
\r
255 static void hmacmd5_key_16(void *handle, unsigned char *key)
\r
257 hmacmd5_key(handle, key, 16);
\r
260 static void hmacmd5_start(void *handle)
\r
262 struct MD5Context *keys = (struct MD5Context *)handle;
\r
264 keys[2] = keys[0]; /* structure copy */
\r
267 static void hmacmd5_bytes(void *handle, unsigned char const *blk, int len)
\r
269 struct MD5Context *keys = (struct MD5Context *)handle;
\r
270 MD5Update(&keys[2], blk, len);
\r
273 static void hmacmd5_genresult(void *handle, unsigned char *hmac)
\r
275 struct MD5Context *keys = (struct MD5Context *)handle;
\r
276 struct MD5Context s;
\r
277 unsigned char intermediate[16];
\r
279 s = keys[2]; /* structure copy */
\r
280 MD5Final(intermediate, &s);
\r
281 s = keys[1]; /* structure copy */
\r
282 MD5Update(&s, intermediate, 16);
\r
283 MD5Final(hmac, &s);
\r
286 static int hmacmd5_verresult(void *handle, unsigned char const *hmac)
\r
288 unsigned char correct[16];
\r
289 hmacmd5_genresult(handle, correct);
\r
290 return !memcmp(correct, hmac, 16);
\r
293 static void hmacmd5_do_hmac_internal(void *handle,
\r
294 unsigned char const *blk, int len,
\r
295 unsigned char const *blk2, int len2,
\r
296 unsigned char *hmac)
\r
298 hmacmd5_start(handle);
\r
299 hmacmd5_bytes(handle, blk, len);
\r
300 if (blk2) hmacmd5_bytes(handle, blk2, len2);
\r
301 hmacmd5_genresult(handle, hmac);
\r
304 void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
\r
305 unsigned char *hmac)
\r
307 hmacmd5_do_hmac_internal(handle, blk, len, NULL, 0, hmac);
\r
310 static void hmacmd5_do_hmac_ssh(void *handle, unsigned char const *blk, int len,
\r
311 unsigned long seq, unsigned char *hmac)
\r
313 unsigned char seqbuf[16];
\r
315 seqbuf[0] = (unsigned char) ((seq >> 24) & 0xFF);
\r
316 seqbuf[1] = (unsigned char) ((seq >> 16) & 0xFF);
\r
317 seqbuf[2] = (unsigned char) ((seq >> 8) & 0xFF);
\r
318 seqbuf[3] = (unsigned char) ((seq) & 0xFF);
\r
320 hmacmd5_do_hmac_internal(handle, seqbuf, 4, blk, len, hmac);
\r
323 static void hmacmd5_generate(void *handle, unsigned char *blk, int len,
\r
326 hmacmd5_do_hmac_ssh(handle, blk, len, seq, blk + len);
\r
329 static int hmacmd5_verify(void *handle, unsigned char *blk, int len,
\r
332 unsigned char correct[16];
\r
333 hmacmd5_do_hmac_ssh(handle, blk, len, seq, correct);
\r
334 return !memcmp(correct, blk + len, 16);
\r
337 const struct ssh_mac ssh_hmac_md5 = {
\r
338 hmacmd5_make_context, hmacmd5_free_context, hmacmd5_key_16,
\r
339 hmacmd5_generate, hmacmd5_verify,
\r
340 hmacmd5_start, hmacmd5_bytes, hmacmd5_genresult, hmacmd5_verresult,
\r