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