Mercurial > masqmail
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 } |