]> git.ipfire.org Git - people/ms/mstpd.git/blame - hmac_md5.c
driver hooks for creating/deleting new MSTI
[people/ms/mstpd.git] / hmac_md5.c
CommitLineData
1e6d2d09
VD
1/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
2rights reserved.
3
4License to copy and use this software is granted provided that it
5is identified as the "RSA Data Security, Inc. MD5 Message-Digest
6Algorithm" in all material mentioning or referencing this software
7or this function.
8
9License is also granted to make and use derivative works provided
10that such works are identified as "derived from the RSA Data
11Security, Inc. MD5 Message-Digest Algorithm" in all material
12mentioning or referencing the derived work.
13
14RSA Data Security, Inc. makes no representations concerning either
15the merchantability of this software or the suitability of this
16software for any particular purpose. It is provided "as is"
17without express or implied warranty of any kind.
18
19These notices must be retained in any copies of any part of this
20documentation and/or software.
21 */
22
23#include <string.h>
24#include <sys/types.h>
25#include <asm/types.h>
26
27#include "mstp.h"
28
29/* POINTER defines a generic pointer type */
30typedef unsigned char *POINTER;
31
32/* UINT2 defines a two byte word */
33typedef __u16 UINT2;
34
35/* UINT4 defines a four byte word */
36typedef __u32 UINT4;
37
38/* MD5 context. */
39typedef struct
40{
41 UINT4 state[4]; /* state (ABCD) */
42 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
43 unsigned char buffer[64]; /* input buffer */
44} MD5_CTX;
45
46#define MD5_memcpy(output, input, len) memcpy((output), (input), (len))
47#define MD5_memset(output, value, len) memset((output), (value), (len))
48
49/* Constants for MD5Transform routine.
50 */
51#define S11 7
52#define S12 12
53#define S13 17
54#define S14 22
55#define S21 5
56#define S22 9
57#define S23 14
58#define S24 20
59#define S31 4
60#define S32 11
61#define S33 16
62#define S34 23
63#define S41 6
64#define S42 10
65#define S43 15
66#define S44 21
67
68static const unsigned char PADDING[64] = {
69 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
72};
73
74/* F, G, H and I are basic MD5 functions.
75 */
76#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
77#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
78#define H(x, y, z) ((x) ^ (y) ^ (z))
79#define I(x, y, z) ((y) ^ ((x) | (~z)))
80
81/* ROTATE_LEFT rotates x left n bits.
82 */
83#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
84
85/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
86Rotation is separate from addition to prevent recomputation.
87 */
88#define FF(a, b, c, d, x, s, ac) { \
89 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
90 (a) = ROTATE_LEFT ((a), (s)); \
91 (a) += (b); \
92 }
93#define GG(a, b, c, d, x, s, ac) { \
94 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
95 (a) = ROTATE_LEFT ((a), (s)); \
96 (a) += (b); \
97 }
98#define HH(a, b, c, d, x, s, ac) { \
99 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
100 (a) = ROTATE_LEFT ((a), (s)); \
101 (a) += (b); \
102 }
103#define II(a, b, c, d, x, s, ac) { \
104 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
105 (a) = ROTATE_LEFT ((a), (s)); \
106 (a) += (b); \
107 }
108
109/* Encodes input (UINT4) into output (unsigned char). Assumes len is
110 a multiple of 4.
111 */
112static void Encode(output, input, len)
113unsigned char *output;
114UINT4 *input;
115unsigned int len;
116{
117 unsigned int i, j;
118
119 for(i = 0, j = 0; j < len; i++, j += 4)
120 {
121 output[j] = (unsigned char)(input[i] & 0xff);
122 output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
123 output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
124 output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
125 }
126}
127
128/* Decodes input (unsigned char) into output (UINT4). Assumes len is
129 a multiple of 4.
130 */
131static void Decode(output, input, len)
132UINT4 *output;
133unsigned char *input;
134unsigned int len;
135{
136 unsigned int i, j;
137
138 for(i = 0, j = 0; j < len; i++, j += 4)
139 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
140 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
141}
142
143/* MD5 basic transformation. Transforms state based on block.
144 */
145static void MD5Transform(state, block)
146UINT4 state[4];
147unsigned char block[64];
148{
149 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
150
151 Decode(x, block, 64);
152
153 /* Round 1 */
154 FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
155 FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
156 FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
157 FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
158 FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
159 FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
160 FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
161 FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
162 FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
163 FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
164 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
165 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
166 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
167 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
168 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
169 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
170
171 /* Round 2 */
172 GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
173 GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
174 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
175 GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
176 GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
177 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
178 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
179 GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
180 GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
181 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
182 GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
183 GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
184 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
185 GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
186 GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
187 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
188
189 /* Round 3 */
190 HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
191 HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
192 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
193 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
194 HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
195 HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
196 HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
197 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
198 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
199 HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
200 HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
201 HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
202 HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
203 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
204 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
205 HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
206
207 /* Round 4 */
208 II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
209 II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
210 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
211 II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
212 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
213 II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
214 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
215 II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
216 II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
217 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
218 II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
219 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
220 II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
221 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
222 II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
223 II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
224
225 state[0] += a;
226 state[1] += b;
227 state[2] += c;
228 state[3] += d;
229
230 /* Zeroize sensitive information. */
231 /* No need in MSTP ;) */
232 /* MD5_memset((POINTER)x, 0, sizeof (x)); */
233}
234
235/* MD5 initialization. Begins an MD5 operation, writing a new context.
236 */
237static void MD5Init(context)
238MD5_CTX *context; /* context */
239{
240 context->count[0] = context->count[1] = 0;
241 /* Load magic initialization constants. */
242 context->state[0] = 0x67452301;
243 context->state[1] = 0xefcdab89;
244 context->state[2] = 0x98badcfe;
245 context->state[3] = 0x10325476;
246}
247
248/* MD5 block update operation. Continues an MD5 message-digest
249 operation, processing another message block, and updating the
250 context.
251 */
252static void MD5Update(context, input, inputLen)
253MD5_CTX *context; /* context */
254unsigned char *input; /* input block */
255unsigned int inputLen; /* length of input block */
256{
257 unsigned int i, index, partLen;
258
259 /* Compute number of bytes mod 64 */
260 index = (unsigned int)((context->count[0] >> 3) & 0x3F);
261
262 /* Update number of bits */
263 if((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
264 context->count[1]++;
265 context->count[1] += ((UINT4)inputLen >> 29);
266
267 partLen = 64 - index;
268
269 /* Transform as many times as possible. */
270 if(inputLen >= partLen)
271 {
272 MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
273 MD5Transform(context->state, context->buffer);
274 for(i = partLen; i + 63 < inputLen; i += 64)
275 MD5Transform(context->state, &input[i]);
276 index = 0;
277 }
278 else
279 i = 0;
280
281 /* Buffer remaining input */
282 MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],
283 inputLen - i);
284}
285
286/* MD5 finalization. Ends an MD5 message-digest operation, writing the
287 the message digest and zeroizing the context.
288 */
289static void MD5Final(digest, context)
290unsigned char digest[16]; /* message digest */
291MD5_CTX *context; /* context */
292{
293 unsigned char bits[8];
294 unsigned int index, padLen;
295
296 /* Save number of bits */
297 Encode(bits, context->count, 8);
298
299 /* Pad out to 56 mod 64. */
300 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
301 padLen = (index < 56) ? (56 - index) : (120 - index);
302 MD5Update(context, PADDING, padLen);
303
304 /* Append length (before padding) */
305 MD5Update(context, bits, 8);
306
307 /* Store state in digest */
308 Encode(digest, context->state, 16);
309
310 /* Zeroize sensitive information. */
311 /* No need in MSTP ;) */
312 /* MD5_memset((POINTER)context, 0, sizeof(*context)); */
313}
314
315/*
316** Function: hmac_md5 from RFC-2104
317*/
318void hmac_md5(text, text_len, key, key_len, digest)
319unsigned char* text; /* pointer to data stream */
320int text_len; /* length of data stream */
321unsigned char* key; /* pointer to authentication key */
322int key_len; /* length of authentication key */
323caddr_t digest; /* caller digest to be filled in */
324{
325 MD5_CTX context;
326 unsigned char k_ipad[65]; /* inner padding -
327 * key XORd with ipad
328 */
329 unsigned char k_opad[65]; /* outer padding -
330 * key XORd with opad
331 */
332 unsigned char tk[16];
333 int i;
334 /* if key is longer than 64 bytes reset it to key=MD5(key) */
335 if(key_len > 64)
336 {
337 MD5_CTX tctx;
338
339 MD5Init(&tctx);
340 MD5Update(&tctx, key, key_len);
341 MD5Final(tk, &tctx);
342
343 key = tk;
344 key_len = 16;
345 }
346
347 /*
348 * the HMAC_MD5 transform looks like:
349 *
350 * MD5(K XOR opad, MD5(K XOR ipad, text))
351 *
352 * where K is an n byte key
353 * ipad is the byte 0x36 repeated 64 times
354 * opad is the byte 0x5c repeated 64 times
355 * and text is the data being protected
356 */
357
358 /* start out by storing key in pads */
359 bzero(k_ipad, sizeof k_ipad);
360 bzero(k_opad, sizeof k_opad);
361 bcopy(key, k_ipad, key_len);
362 bcopy( key, k_opad, key_len);
363
364 /* XOR key with ipad and opad values */
365 for(i = 0; i < 64; ++i)
366 {
367 k_ipad[i] ^= 0x36;
368 k_opad[i] ^= 0x5c;
369 }
370 /*
371 * perform inner MD5
372 */
373 MD5Init(&context); /* init context for 1st
374 * pass */
375 MD5Update(&context, k_ipad, 64); /* start with inner pad */
376 MD5Update(&context, text, text_len); /* then text of datagram */
377 MD5Final(digest, &context); /* finish up 1st pass */
378 /*
379 * perform outer MD5
380 */
381 MD5Init(&context); /* init context for 2nd
382 * pass */
383 MD5Update(&context, k_opad, 64); /* start with outer pad */
384 MD5Update(&context, digest, 16); /* then results of 1st
385 * hash */
386 MD5Final(digest, &context); /* finish up 2nd pass */
387}
388
389#ifdef HMAC_MDS_TEST_FUNCTIONS
390/* Digests a string */
391static void MD5String(string, digest)
392char *string;
393caddr_t digest; /* caller digest to be filled in */
394{
395 MD5_CTX context;
396 unsigned int len = strlen(string);
397
398 MD5Init(&context);
399 MD5Update(&context, string, len);
400 MD5Final(digest, &context);
401}
402
403/* Digests a reference suite of strings */
404bool MD5TestSuite(void)
405{
406 unsigned char digest[16];
407 unsigned char key[16];
408 unsigned char mstp_key[16] = HMAC_KEY;
409 unsigned char data[4096 * 2];
410 int i;
411
412 /* Tests from RFC-1231 */
413 MD5String("", digest);
414 {
415 unsigned char expected_result[16] = {
416 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
417 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e};
418 if(memcmp(expected_result, digest, 16))
419 return false;
420 }
421 MD5String("a", digest);
422 {
423 unsigned char expected_result[16] = {
424 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
425 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61};
426 if(memcmp(expected_result, digest, 16))
427 return false;
428 }
429 MD5String("abc", digest);
430 {
431 unsigned char expected_result[16] = {
432 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
433 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72};
434 if(memcmp(expected_result, digest, 16))
435 return false;
436 }
437 MD5String("message digest", digest);
438 {
439 unsigned char expected_result[16] = {
440 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
441 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0};
442 if(memcmp(expected_result, digest, 16))
443 return false;
444 }
445 MD5String("abcdefghijklmnopqrstuvwxyz", digest);
446 {
447 unsigned char expected_result[16] = {
448 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
449 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b};
450 if(memcmp(expected_result, digest, 16))
451 return false;
452 }
453 MD5String("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
454 digest);
455 {
456 unsigned char expected_result[16] = {
457 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
458 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f};
459 if(memcmp(expected_result, digest, 16))
460 return false;
461 }
462 MD5String("1234567890123456789012345678901234567890"
463 "1234567890123456789012345678901234567890", digest);
464 {
465 unsigned char expected_result[16] = {
466 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
467 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a};
468 if(memcmp(expected_result, digest, 16))
469 return false;
470 }
471
472 /* Tests from RFC-2104 */
473 memset(key, 0x0B, 16);
474 hmac_md5("Hi There", 8, key, 16, digest);
475 {
476 unsigned char expected_result[16] = {
477 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
478 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d};
479 if(memcmp(expected_result, digest, 16))
480 return false;
481 }
482 hmac_md5("what do ya want for nothing?", 28, "Jefe", 4, digest);
483 {
484 unsigned char expected_result[16] = {
485 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
486 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38};
487 if(memcmp(expected_result, digest, 16))
488 return false;
489 }
490 memset(key, 0xAA, 16);
491 memset(data, 0xDD, 50);
492 hmac_md5(data, 50, key, 16, digest);
493 {
494 unsigned char expected_result[16] = {
495 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
496 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6};
497 if(memcmp(expected_result, digest, 16))
498 return false;
499 }
500
501 /* Tests from IEEE 802.1Q-2005 13.7 Table 13-2 */
502 memset(data, 0, 4096 * 2);
503 hmac_md5(data, 4096 * 2, mstp_key, 16, digest);
504 {
505 unsigned char expected_result[16] = {
506 0xac, 0x36, 0x17, 0x7f, 0x50, 0x28, 0x3c, 0xd4,
507 0xb8, 0x38, 0x21, 0xd8, 0xab, 0x26, 0xde, 0x62};
508 if(memcmp(expected_result, digest, 16))
509 return false;
510 }
511 for(i = 3; i < 4095 * 2; i+= 2)
512 data[i] = 1;
513 hmac_md5(data, 4096 * 2, mstp_key, 16, digest);
514 {
515 unsigned char expected_result[16] = {
516 0xe1, 0x3a, 0x80, 0xf1, 0x1e, 0xd0, 0x85, 0x6a,
517 0xcd, 0x4e, 0xe3, 0x47, 0x69, 0x41, 0xc7, 0x3b};
518 if(memcmp(expected_result, digest, 16))
519 return false;
520 }
521 for(i = 3; i < 4095 * 2; i+= 2)
522 data[i] = (i / 2) % 32 + 1;
523 hmac_md5(data, 4096 * 2, mstp_key, 16, digest);
524 {
525 unsigned char expected_result[16] = {
526 0x9d, 0x14, 0x5c, 0x26, 0x7d, 0xbe, 0x9f, 0xb5,
527 0xd8, 0x93, 0x44, 0x1b, 0xe3, 0xba, 0x08, 0xce};
528 if(memcmp(expected_result, digest, 16))
529 return false;
530 }
531
532 return true;
533}
534#endif /* HMAC_MDS_TEST_FUNCTIONS */