masqmail

annotate src/md5/hmac_md5.c @ 281:ea5f86e0a81c

modes are now enforced exclusive Other MTAs (exim, postfix) are more relaxing, but as combinations of exclusive modes are senseless we behave more obvious if we fail early. This makes understanding the behavior easier too.
author markus schnalke <meillo@marmaro.de>
date Tue, 07 Dec 2010 14:04:56 -0300
parents 10da50168dab
children 41958685480d
rev   line source
meillo@0 1 /*
meillo@211 2 hmac_md5 -- implements RFC 2104
meillo@211 3
meillo@211 4 Copyright 2010, markus schnalke <meillo@marmaro.de>
meillo@211 5
meillo@211 6 Permission to use, copy, modify, and/or distribute this software for any
meillo@211 7 purpose with or without fee is hereby granted, provided that the above
meillo@211 8 copyright notice and this permission notice appear in all copies.
meillo@211 9
meillo@211 10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
meillo@211 11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
meillo@211 12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
meillo@211 13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
meillo@211 14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
meillo@211 15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
meillo@211 16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
meillo@211 17
meillo@211 18
meillo@211 19 My motivation to write this code was the lack of a nicely licensed
meillo@211 20 hmac_md5 function in C. I programmed it following the RFC's text.
meillo@211 21 Obviously this code is highly similar to the sample code of the RFC.
meillo@211 22 The code is tested against the test vectors of the RFC. Wikipedia's
meillo@211 23 HMAC page helped me to understand the algorithm better.
meillo@211 24
meillo@211 25 This hmac_md5 function requires an OpenSSL-compatible MD5
meillo@211 26 implementation. There are Public Domain MD5 implementations by Colin
meillo@211 27 Plumb and by Solar Designer. You probably want to use one of these.
meillo@0 28 */
meillo@0 29
meillo@0 30 #include <string.h>
meillo@0 31 #include "md5.h"
meillo@0 32
meillo@211 33
meillo@211 34 const int blocksize = 64;
meillo@211 35 const int hashsize = 16;
meillo@211 36
meillo@211 37
meillo@211 38 /*
meillo@211 39 The computed HMAC will be written to `digest'.
meillo@211 40 Ensure digest points to hashsize bytes of allocated memory.
meillo@211 41 */
meillo@10 42 void
meillo@211 43 hmac_md5(unsigned char* text, int textlen, unsigned char* key, int keylen, unsigned char* digest)
meillo@10 44 {
meillo@211 45 int i;
meillo@10 46 MD5_CTX context;
meillo@211 47 unsigned char ipad[blocksize];
meillo@211 48 unsigned char opad[blocksize];
meillo@0 49
meillo@211 50 /* too long keys are replaced by their hash value */
meillo@211 51 if (keylen > blocksize) {
meillo@211 52 MD5_Init(&context);
meillo@211 53 MD5_Update(&context, key, keylen);
meillo@211 54 MD5_Final(digest, &context);
meillo@211 55 key = digest;
meillo@211 56 keylen = hashsize;
meillo@10 57 }
meillo@0 58
meillo@211 59 /* copy the key into the pads */
meillo@211 60 memset(ipad, 0, sizeof(ipad));
meillo@211 61 memcpy(ipad, key, keylen);
meillo@0 62
meillo@211 63 memset(opad, 0, sizeof(opad));
meillo@211 64 memcpy(opad, key, keylen);
meillo@0 65
meillo@211 66 /* xor the pads with their ``basic'' value */
meillo@211 67 for (i=0; i<blocksize; i++) {
meillo@211 68 ipad[i] ^= 0x36;
meillo@211 69 opad[i] ^= 0x5c;
meillo@10 70 }
meillo@211 71
meillo@211 72 /* inner pass (ipad ++ message) */
meillo@211 73 MD5_Init(&context);
meillo@211 74 MD5_Update(&context, ipad, sizeof(ipad));
meillo@211 75 MD5_Update(&context, text, textlen);
meillo@211 76 MD5_Final(digest, &context);
meillo@211 77
meillo@211 78 /* outer pass (opad ++ result of inner pass) */
meillo@211 79 MD5_Init(&context);
meillo@211 80 MD5_Update(&context, opad, sizeof(opad));
meillo@211 81 MD5_Update(&context, digest, hashsize);
meillo@211 82 MD5_Final(digest, &context);
meillo@0 83 }