comparison src/md5/hmac_md5.c @ 211:0f36c0a46f82

replaced hmac_md5.c with an own implementation of RFC 2104 Until now the sample code of the RFC itself was used, but it lacked a license or copyright notice. See the comment in hmac_md5.c for details.
author meillo@marmaro.de
date Sun, 18 Jul 2010 22:20:36 +0200
parents 10da50168dab
children 41958685480d
comparison
equal deleted inserted replaced
210:e0938c511243 211:0f36c0a46f82
1 /* 1 /*
2 ** Function: hmac_md5 2 hmac_md5 -- implements RFC 2104
3
4 Copyright 2010, markus schnalke <meillo@marmaro.de>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18
19 My motivation to write this code was the lack of a nicely licensed
20 hmac_md5 function in C. I programmed it following the RFC's text.
21 Obviously this code is highly similar to the sample code of the RFC.
22 The code is tested against the test vectors of the RFC. Wikipedia's
23 HMAC page helped me to understand the algorithm better.
24
25 This hmac_md5 function requires an OpenSSL-compatible MD5
26 implementation. There are Public Domain MD5 implementations by Colin
27 Plumb and by Solar Designer. You probably want to use one of these.
3 */ 28 */
4 29
5 #include <string.h> 30 #include <string.h>
6 #include "md5.h" 31 #include "md5.h"
7 #include "hmac_md5.h"
8 32
33
34 const int blocksize = 64;
35 const int hashsize = 16;
36
37
38 /*
39 The computed HMAC will be written to `digest'.
40 Ensure digest points to hashsize bytes of allocated memory.
41 */
9 void 42 void
10 hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest) 43 hmac_md5(unsigned char* text, int textlen, unsigned char* key, int keylen, unsigned char* digest)
11 /* text; pointer to data stream */
12 /* text_len; length of data stream */
13 /* key; pointer to authentication key */
14 /* key_len; length of authentication key */
15 /* digest; caller digest to be filled in */
16 { 44 {
45 int i;
17 MD5_CTX context; 46 MD5_CTX context;
18 unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ 47 unsigned char ipad[blocksize];
19 unsigned char k_opad[65]; /* outer padding - key XORd with opad */ 48 unsigned char opad[blocksize];
20 unsigned char tk[16];
21 int i;
22 /* if key is longer than 64 bytes reset it to key=MD5(key) */
23 if (key_len > 64) {
24 49
25 MD5_CTX tctx; 50 /* too long keys are replaced by their hash value */
26 51 if (keylen > blocksize) {
27 MD5_Init(&tctx); 52 MD5_Init(&context);
28 MD5_Update(&tctx, key, key_len); 53 MD5_Update(&context, key, keylen);
29 MD5_Final(tk, &tctx); 54 MD5_Final(digest, &context);
30 55 key = digest;
31 key = tk; 56 keylen = hashsize;
32 key_len = 16;
33 } 57 }
34 58
35 /* 59 /* copy the key into the pads */
36 * the HMAC_MD5 transform looks like: 60 memset(ipad, 0, sizeof(ipad));
37 * 61 memcpy(ipad, key, keylen);
38 * MD5(K XOR opad, MD5(K XOR ipad, text))
39 *
40 * where K is an n byte key
41 * ipad is the byte 0x36 repeated 64 times
42 * opad is the byte 0x5c repeated 64 times
43 * and text is the data being protected
44 */
45 62
46 /* start out by storing key in pads */ 63 memset(opad, 0, sizeof(opad));
47 bzero(k_ipad, sizeof k_ipad); 64 memcpy(opad, key, keylen);
48 bzero(k_opad, sizeof k_opad);
49 bcopy(key, k_ipad, key_len);
50 bcopy(key, k_opad, key_len);
51 65
52 /* XOR key with ipad and opad values */ 66 /* xor the pads with their ``basic'' value */
53 for (i = 0; i < 64; i++) { 67 for (i=0; i<blocksize; i++) {
54 k_ipad[i] ^= 0x36; 68 ipad[i] ^= 0x36;
55 k_opad[i] ^= 0x5c; 69 opad[i] ^= 0x5c;
56 } 70 }
57 /* 71
58 * perform inner MD5 72 /* inner pass (ipad ++ message) */
59 */ 73 MD5_Init(&context);
60 MD5_Init(&context); /* init context for 1st pass */ 74 MD5_Update(&context, ipad, sizeof(ipad));
61 MD5_Update(&context, k_ipad, 64); /* start with inner pad */ 75 MD5_Update(&context, text, textlen);
62 MD5_Update(&context, text, text_len); /* then text of datagram */ 76 MD5_Final(digest, &context);
63 MD5_Final(digest, &context); /* finish up 1st pass */ 77
64 /* 78 /* outer pass (opad ++ result of inner pass) */
65 * perform outer MD5 79 MD5_Init(&context);
66 */ 80 MD5_Update(&context, opad, sizeof(opad));
67 MD5_Init(&context); /* init context for 2nd pass */ 81 MD5_Update(&context, digest, hashsize);
68 MD5_Update(&context, k_opad, 64); /* start with outer pad */ 82 MD5_Final(digest, &context);
69 MD5_Update(&context, digest, 16); /* then results of 1st hash */
70 MD5_Final(digest, &context); /* finish up 2nd pass */
71 } 83 }