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  }