rev |
line source |
meillo@0
|
1 /*
|
meillo@367
|
2 ** hmac_md5 -- implements RFC 2104
|
meillo@367
|
3 **
|
meillo@367
|
4 ** Copyright 2010, markus schnalke <meillo@marmaro.de>
|
meillo@367
|
5 **
|
meillo@367
|
6 ** Permission to use, copy, modify, and/or distribute this software for any
|
meillo@367
|
7 ** purpose with or without fee is hereby granted, provided that the above
|
meillo@367
|
8 ** copyright notice and this permission notice appear in all copies.
|
meillo@367
|
9 **
|
meillo@367
|
10 ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
meillo@367
|
11 ** WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
meillo@367
|
12 ** MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
meillo@367
|
13 ** ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
meillo@367
|
14 ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
meillo@367
|
15 ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
meillo@367
|
16 ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
meillo@367
|
17 **
|
meillo@367
|
18 **
|
meillo@367
|
19 ** My motivation to write this code was the lack of a nicely licensed
|
meillo@367
|
20 ** hmac_md5 function in C. I programmed it following the RFC's text.
|
meillo@367
|
21 ** Obviously this code is highly similar to the sample code of the RFC.
|
meillo@367
|
22 ** The code is tested against the test vectors of the RFC. Wikipedia's
|
meillo@367
|
23 ** HMAC page helped me to understand the algorithm better.
|
meillo@367
|
24 **
|
meillo@367
|
25 ** This hmac_md5 function requires an OpenSSL-compatible MD5
|
meillo@367
|
26 ** implementation. There are Public Domain MD5 implementations by Colin
|
meillo@367
|
27 ** Plumb and by Solar Designer. You probably want to use one of these.
|
meillo@0
|
28 */
|
meillo@0
|
29
|
meillo@0
|
30 #include <string.h>
|
meillo@0
|
31 #include "md5.h"
|
meillo@0
|
32
|
meillo@211
|
33
|
meillo@211
|
34 const int blocksize = 64;
|
meillo@211
|
35 const int hashsize = 16;
|
meillo@211
|
36
|
meillo@211
|
37
|
meillo@211
|
38 /*
|
meillo@367
|
39 ** The computed HMAC will be written to `digest'.
|
meillo@367
|
40 ** Ensure digest points to hashsize bytes of allocated memory.
|
meillo@211
|
41 */
|
meillo@10
|
42 void
|
meillo@367
|
43 hmac_md5(unsigned char *text, int textlen, unsigned char *key, int keylen,
|
meillo@367
|
44 unsigned char *digest)
|
meillo@10
|
45 {
|
meillo@211
|
46 int i;
|
meillo@10
|
47 MD5_CTX context;
|
meillo@211
|
48 unsigned char ipad[blocksize];
|
meillo@211
|
49 unsigned char opad[blocksize];
|
meillo@0
|
50
|
meillo@211
|
51 /* too long keys are replaced by their hash value */
|
meillo@211
|
52 if (keylen > blocksize) {
|
meillo@211
|
53 MD5_Init(&context);
|
meillo@211
|
54 MD5_Update(&context, key, keylen);
|
meillo@211
|
55 MD5_Final(digest, &context);
|
meillo@211
|
56 key = digest;
|
meillo@211
|
57 keylen = hashsize;
|
meillo@10
|
58 }
|
meillo@0
|
59
|
meillo@211
|
60 /* copy the key into the pads */
|
meillo@211
|
61 memset(ipad, 0, sizeof(ipad));
|
meillo@211
|
62 memcpy(ipad, key, keylen);
|
meillo@0
|
63
|
meillo@211
|
64 memset(opad, 0, sizeof(opad));
|
meillo@211
|
65 memcpy(opad, key, keylen);
|
meillo@0
|
66
|
meillo@211
|
67 /* xor the pads with their ``basic'' value */
|
meillo@211
|
68 for (i=0; i<blocksize; i++) {
|
meillo@211
|
69 ipad[i] ^= 0x36;
|
meillo@211
|
70 opad[i] ^= 0x5c;
|
meillo@10
|
71 }
|
meillo@211
|
72
|
meillo@211
|
73 /* inner pass (ipad ++ message) */
|
meillo@211
|
74 MD5_Init(&context);
|
meillo@211
|
75 MD5_Update(&context, ipad, sizeof(ipad));
|
meillo@211
|
76 MD5_Update(&context, text, textlen);
|
meillo@211
|
77 MD5_Final(digest, &context);
|
meillo@211
|
78
|
meillo@211
|
79 /* outer pass (opad ++ result of inner pass) */
|
meillo@211
|
80 MD5_Init(&context);
|
meillo@211
|
81 MD5_Update(&context, opad, sizeof(opad));
|
meillo@211
|
82 MD5_Update(&context, digest, hashsize);
|
meillo@211
|
83 MD5_Final(digest, &context);
|
meillo@0
|
84 }
|