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