meillo@0: /* meillo@367: ** hmac_md5 -- implements RFC 2104 meillo@367: ** meillo@367: ** Copyright 2010, markus schnalke meillo@367: ** meillo@367: ** Permission to use, copy, modify, and/or distribute this software for any meillo@367: ** purpose with or without fee is hereby granted, provided that the above meillo@367: ** copyright notice and this permission notice appear in all copies. meillo@367: ** meillo@367: ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES meillo@367: ** WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF meillo@367: ** MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR meillo@367: ** ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES meillo@367: ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN meillo@367: ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF meillo@367: ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. meillo@367: ** meillo@367: ** meillo@367: ** My motivation to write this code was the lack of a nicely licensed meillo@367: ** hmac_md5 function in C. I programmed it following the RFC's text. meillo@367: ** Obviously this code is highly similar to the sample code of the RFC. meillo@367: ** The code is tested against the test vectors of the RFC. Wikipedia's meillo@367: ** HMAC page helped me to understand the algorithm better. meillo@367: ** meillo@367: ** This hmac_md5 function requires an OpenSSL-compatible MD5 meillo@367: ** implementation. There are Public Domain MD5 implementations by Colin meillo@367: ** 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@367: ** The computed HMAC will be written to `digest'. meillo@367: ** Ensure digest points to hashsize bytes of allocated memory. meillo@211: */ meillo@10: void meillo@367: hmac_md5(unsigned char *text, int textlen, unsigned char *key, int keylen, meillo@367: 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