meillo@0: /* meillo@211: hmac_md5 -- implements RFC 2104 meillo@211: meillo@211: Copyright 2010, markus schnalke meillo@211: meillo@211: Permission to use, copy, modify, and/or distribute this software for any meillo@211: purpose with or without fee is hereby granted, provided that the above meillo@211: copyright notice and this permission notice appear in all copies. meillo@211: meillo@211: THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES meillo@211: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF meillo@211: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR meillo@211: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES meillo@211: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN meillo@211: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF meillo@211: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. meillo@211: meillo@211: meillo@211: My motivation to write this code was the lack of a nicely licensed meillo@211: hmac_md5 function in C. I programmed it following the RFC's text. meillo@211: Obviously this code is highly similar to the sample code of the RFC. meillo@211: The code is tested against the test vectors of the RFC. Wikipedia's meillo@211: HMAC page helped me to understand the algorithm better. meillo@211: meillo@211: This hmac_md5 function requires an OpenSSL-compatible MD5 meillo@211: implementation. There are Public Domain MD5 implementations by Colin meillo@211: Plumb and by Solar Designer. You probably want to use one of these. meillo@0: */ meillo@0: meillo@0: #include meillo@0: #include "md5.h" meillo@0: meillo@211: meillo@211: const int blocksize = 64; meillo@211: const int hashsize = 16; meillo@211: meillo@211: meillo@211: /* meillo@211: The computed HMAC will be written to `digest'. meillo@211: Ensure digest points to hashsize bytes of allocated memory. meillo@211: */ meillo@10: void meillo@366: hmac_md5(unsigned char *text, int textlen, unsigned char *key, int keylen, unsigned char *digest) meillo@10: { meillo@211: int i; meillo@10: MD5_CTX context; meillo@211: unsigned char ipad[blocksize]; meillo@211: unsigned char opad[blocksize]; meillo@0: meillo@211: /* too long keys are replaced by their hash value */ meillo@211: if (keylen > blocksize) { meillo@211: MD5_Init(&context); meillo@211: MD5_Update(&context, key, keylen); meillo@211: MD5_Final(digest, &context); meillo@211: key = digest; meillo@211: keylen = hashsize; meillo@10: } meillo@0: meillo@211: /* copy the key into the pads */ meillo@211: memset(ipad, 0, sizeof(ipad)); meillo@211: memcpy(ipad, key, keylen); meillo@0: meillo@211: memset(opad, 0, sizeof(opad)); meillo@211: memcpy(opad, key, keylen); meillo@0: meillo@211: /* xor the pads with their ``basic'' value */ meillo@211: for (i=0; i