2 * hmac.c For the sake of illustration we provide the following
3 * sample code for the implementation of HMAC-MD5 as well
4 * as some corresponding test vectors (the code is based
5 * on MD5 code as described in [MD5]).
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
21 * Copyright 2000 The FreeRADIUS server project
30 #include "libradius.h"
33 unsigned char* text; pointer to data stream
34 int text_len; length of data stream
35 unsigned char* key; pointer to authentication key
36 int key_len; length of authentication key
37 unsigned char* digest; caller digest to be filled in
41 lrad_hmac_md5(const unsigned char *text, int text_len,
42 const unsigned char *key, int key_len,
43 unsigned char *digest)
46 unsigned char k_ipad[65]; /* inner padding -
49 unsigned char k_opad[65]; /* outer padding -
54 /* if key is longer than 64 bytes reset it to key=MD5(key) */
60 MD5Update(&tctx, key, key_len);
68 * the HMAC_MD5 transform looks like:
70 * MD5(K XOR opad, MD5(K XOR ipad, text))
72 * where K is an n byte key
73 * ipad is the byte 0x36 repeated 64 times
75 * opad is the byte 0x5c repeated 64 times
76 * and text is the data being protected
79 /* start out by storing key in pads */
80 memset( k_ipad, 0, sizeof(k_ipad));
81 memset( k_opad, 0, sizeof(k_opad));
82 memcpy( k_ipad, key, key_len);
83 memcpy( k_opad, key, key_len);
85 /* XOR key with ipad and opad values */
86 for (i = 0; i < 64; i++) {
93 MD5Init(&context); /* init context for 1st
95 MD5Update(&context, k_ipad, 64); /* start with inner pad */
96 MD5Update(&context, text, text_len); /* then text of datagram */
97 MD5Final(digest, &context); /* finish up 1st pass */
101 MD5Init(&context); /* init context for 2nd
103 MD5Update(&context, k_opad, 64); /* start with outer pad */
104 MD5Update(&context, digest, 16); /* then results of 1st
106 MD5Final(digest, &context); /* finish up 2nd pass */
110 Test Vectors (Trailing '\0' of a character string not included in test):
112 key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
116 digest = 0x9294727a3638bb1c13f48ef8158bfc9d
119 data = "what do ya want for nothing?"
121 digest = 0x750c783e6ab0b503eaa86e310a5db738
123 key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
126 data = 0xDDDDDDDDDDDDDDDDDDDD...
127 ..DDDDDDDDDDDDDDDDDDDD...
128 ..DDDDDDDDDDDDDDDDDDDD...
129 ..DDDDDDDDDDDDDDDDDDDD...
130 ..DDDDDDDDDDDDDDDDDDDD
132 digest = 0x56be34521d144c88dbb8c733f0e8b3f6
137 * cc -DTESTING -I ../include/ hmac.c md5.c -o hmac
139 * ./hmac Jefe "what do ya want for nothing?"
145 int main(int argc, char **argv)
147 unsigned char digest[16];
155 key_len = strlen(key);
158 text_len = strlen(text);
160 lrad_hmac_md5(text, text_len, key, key_len, digest);
162 for (i = 0; i < 16; i++) {
163 printf("%02x", digest[i]);