masqmail
diff 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 |
line diff
1.1 --- a/src/md5/hmac_md5.c Sun Jul 18 22:02:54 2010 +0200 1.2 +++ b/src/md5/hmac_md5.c Sun Jul 18 22:20:36 2010 +0200 1.3 @@ -1,71 +1,83 @@ 1.4 /* 1.5 -** Function: hmac_md5 1.6 +hmac_md5 -- implements RFC 2104 1.7 + 1.8 +Copyright 2010, markus schnalke <meillo@marmaro.de> 1.9 + 1.10 +Permission to use, copy, modify, and/or distribute this software for any 1.11 +purpose with or without fee is hereby granted, provided that the above 1.12 +copyright notice and this permission notice appear in all copies. 1.13 + 1.14 +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1.15 +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1.16 +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1.17 +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.18 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1.19 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1.20 +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.21 + 1.22 + 1.23 +My motivation to write this code was the lack of a nicely licensed 1.24 +hmac_md5 function in C. I programmed it following the RFC's text. 1.25 +Obviously this code is highly similar to the sample code of the RFC. 1.26 +The code is tested against the test vectors of the RFC. Wikipedia's 1.27 +HMAC page helped me to understand the algorithm better. 1.28 + 1.29 +This hmac_md5 function requires an OpenSSL-compatible MD5 1.30 +implementation. There are Public Domain MD5 implementations by Colin 1.31 +Plumb and by Solar Designer. You probably want to use one of these. 1.32 */ 1.33 1.34 #include <string.h> 1.35 #include "md5.h" 1.36 -#include "hmac_md5.h" 1.37 1.38 + 1.39 +const int blocksize = 64; 1.40 +const int hashsize = 16; 1.41 + 1.42 + 1.43 +/* 1.44 +The computed HMAC will be written to `digest'. 1.45 +Ensure digest points to hashsize bytes of allocated memory. 1.46 +*/ 1.47 void 1.48 -hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest) 1.49 - /* text; pointer to data stream */ 1.50 - /* text_len; length of data stream */ 1.51 - /* key; pointer to authentication key */ 1.52 - /* key_len; length of authentication key */ 1.53 - /* digest; caller digest to be filled in */ 1.54 +hmac_md5(unsigned char* text, int textlen, unsigned char* key, int keylen, unsigned char* digest) 1.55 { 1.56 + int i; 1.57 MD5_CTX context; 1.58 - unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ 1.59 - unsigned char k_opad[65]; /* outer padding - key XORd with opad */ 1.60 - unsigned char tk[16]; 1.61 - int i; 1.62 - /* if key is longer than 64 bytes reset it to key=MD5(key) */ 1.63 - if (key_len > 64) { 1.64 + unsigned char ipad[blocksize]; 1.65 + unsigned char opad[blocksize]; 1.66 1.67 - MD5_CTX tctx; 1.68 - 1.69 - MD5_Init(&tctx); 1.70 - MD5_Update(&tctx, key, key_len); 1.71 - MD5_Final(tk, &tctx); 1.72 - 1.73 - key = tk; 1.74 - key_len = 16; 1.75 + /* too long keys are replaced by their hash value */ 1.76 + if (keylen > blocksize) { 1.77 + MD5_Init(&context); 1.78 + MD5_Update(&context, key, keylen); 1.79 + MD5_Final(digest, &context); 1.80 + key = digest; 1.81 + keylen = hashsize; 1.82 } 1.83 1.84 - /* 1.85 - * the HMAC_MD5 transform looks like: 1.86 - * 1.87 - * MD5(K XOR opad, MD5(K XOR ipad, text)) 1.88 - * 1.89 - * where K is an n byte key 1.90 - * ipad is the byte 0x36 repeated 64 times 1.91 - * opad is the byte 0x5c repeated 64 times 1.92 - * and text is the data being protected 1.93 - */ 1.94 + /* copy the key into the pads */ 1.95 + memset(ipad, 0, sizeof(ipad)); 1.96 + memcpy(ipad, key, keylen); 1.97 1.98 - /* start out by storing key in pads */ 1.99 - bzero(k_ipad, sizeof k_ipad); 1.100 - bzero(k_opad, sizeof k_opad); 1.101 - bcopy(key, k_ipad, key_len); 1.102 - bcopy(key, k_opad, key_len); 1.103 + memset(opad, 0, sizeof(opad)); 1.104 + memcpy(opad, key, keylen); 1.105 1.106 - /* XOR key with ipad and opad values */ 1.107 - for (i = 0; i < 64; i++) { 1.108 - k_ipad[i] ^= 0x36; 1.109 - k_opad[i] ^= 0x5c; 1.110 + /* xor the pads with their ``basic'' value */ 1.111 + for (i=0; i<blocksize; i++) { 1.112 + ipad[i] ^= 0x36; 1.113 + opad[i] ^= 0x5c; 1.114 } 1.115 - /* 1.116 - * perform inner MD5 1.117 - */ 1.118 - MD5_Init(&context); /* init context for 1st pass */ 1.119 - MD5_Update(&context, k_ipad, 64); /* start with inner pad */ 1.120 - MD5_Update(&context, text, text_len); /* then text of datagram */ 1.121 - MD5_Final(digest, &context); /* finish up 1st pass */ 1.122 - /* 1.123 - * perform outer MD5 1.124 - */ 1.125 - MD5_Init(&context); /* init context for 2nd pass */ 1.126 - MD5_Update(&context, k_opad, 64); /* start with outer pad */ 1.127 - MD5_Update(&context, digest, 16); /* then results of 1st hash */ 1.128 - MD5_Final(digest, &context); /* finish up 2nd pass */ 1.129 + 1.130 + /* inner pass (ipad ++ message) */ 1.131 + MD5_Init(&context); 1.132 + MD5_Update(&context, ipad, sizeof(ipad)); 1.133 + MD5_Update(&context, text, textlen); 1.134 + MD5_Final(digest, &context); 1.135 + 1.136 + /* outer pass (opad ++ result of inner pass) */ 1.137 + MD5_Init(&context); 1.138 + MD5_Update(&context, opad, sizeof(opad)); 1.139 + MD5_Update(&context, digest, hashsize); 1.140 + MD5_Final(digest, &context); 1.141 }