Line data Source code
1 : /*
2 : * hmac.c
3 : *
4 : * implementation of hmac auth_type_t
5 : *
6 : * David A. McGrew
7 : * Cisco Systems, Inc.
8 : */
9 : /*
10 : *
11 : * Copyright(c) 2001-2006 Cisco Systems, Inc.
12 : * All rights reserved.
13 : *
14 : * Redistribution and use in source and binary forms, with or without
15 : * modification, are permitted provided that the following conditions
16 : * are met:
17 : *
18 : * Redistributions of source code must retain the above copyright
19 : * notice, this list of conditions and the following disclaimer.
20 : *
21 : * Redistributions in binary form must reproduce the above
22 : * copyright notice, this list of conditions and the following
23 : * disclaimer in the documentation and/or other materials provided
24 : * with the distribution.
25 : *
26 : * Neither the name of the Cisco Systems, Inc. nor the names of its
27 : * contributors may be used to endorse or promote products derived
28 : * from this software without specific prior written permission.
29 : *
30 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 : * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 : * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35 : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41 : * OF THE POSSIBILITY OF SUCH DAMAGE.
42 : *
43 : */
44 :
45 : #include "hmac.h"
46 : #include "alloc.h"
47 :
48 : /* the debug module for authentiation */
49 :
50 : debug_module_t mod_hmac = {
51 : 0, /* debugging is off by default */
52 : "hmac sha-1" /* printable name for module */
53 : };
54 :
55 :
56 : err_status_t
57 0 : hmac_alloc(auth_t **a, int key_len, int out_len) {
58 : extern auth_type_t hmac;
59 : uint8_t *pointer;
60 :
61 : debug_print(mod_hmac, "allocating auth func with key length %d", key_len);
62 : debug_print(mod_hmac, " tag length %d", out_len);
63 :
64 : /*
65 : * check key length - note that we don't support keys larger
66 : * than 20 bytes yet
67 : */
68 0 : if (key_len > 20)
69 0 : return err_status_bad_param;
70 :
71 : /* check output length - should be less than 20 bytes */
72 0 : if (out_len > 20)
73 0 : return err_status_bad_param;
74 :
75 : /* allocate memory for auth and hmac_ctx_t structures */
76 0 : pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t));
77 0 : if (pointer == NULL)
78 0 : return err_status_alloc_fail;
79 :
80 : /* set pointers */
81 0 : *a = (auth_t *)pointer;
82 0 : (*a)->type = &hmac;
83 0 : (*a)->state = pointer + sizeof(auth_t);
84 0 : (*a)->out_len = out_len;
85 0 : (*a)->key_len = key_len;
86 0 : (*a)->prefix_len = 0;
87 :
88 : /* increment global count of all hmac uses */
89 0 : hmac.ref_count++;
90 :
91 0 : return err_status_ok;
92 : }
93 :
94 : err_status_t
95 0 : hmac_dealloc(auth_t *a) {
96 : extern auth_type_t hmac;
97 :
98 : /* zeroize entire state*/
99 0 : octet_string_set_to_zero((uint8_t *)a,
100 : sizeof(hmac_ctx_t) + sizeof(auth_t));
101 :
102 : /* free memory */
103 0 : crypto_free(a);
104 :
105 : /* decrement global count of all hmac uses */
106 0 : hmac.ref_count--;
107 :
108 0 : return err_status_ok;
109 : }
110 :
111 : err_status_t
112 0 : hmac_init(hmac_ctx_t *state, const uint8_t *key, int key_len) {
113 : int i;
114 : uint8_t ipad[64];
115 :
116 : /*
117 : * check key length - note that we don't support keys larger
118 : * than 20 bytes yet
119 : */
120 0 : if (key_len > 20)
121 0 : return err_status_bad_param;
122 :
123 : /*
124 : * set values of ipad and opad by exoring the key into the
125 : * appropriate constant values
126 : */
127 0 : for (i=0; i < key_len; i++) {
128 0 : ipad[i] = key[i] ^ 0x36;
129 0 : state->opad[i] = key[i] ^ 0x5c;
130 : }
131 : /* set the rest of ipad, opad to constant values */
132 0 : for ( ; i < 64; i++) {
133 0 : ipad[i] = 0x36;
134 0 : ((uint8_t *)state->opad)[i] = 0x5c;
135 : }
136 :
137 : debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(ipad, 64));
138 :
139 : /* initialize sha1 context */
140 0 : sha1_init(&state->init_ctx);
141 :
142 : /* hash ipad ^ key */
143 0 : sha1_update(&state->init_ctx, ipad, 64);
144 0 : memcpy(&state->ctx, &state->init_ctx, sizeof(sha1_ctx_t));
145 :
146 0 : return err_status_ok;
147 : }
148 :
149 : err_status_t
150 0 : hmac_start(hmac_ctx_t *state) {
151 :
152 0 : memcpy(&state->ctx, &state->init_ctx, sizeof(sha1_ctx_t));
153 :
154 0 : return err_status_ok;
155 : }
156 :
157 : err_status_t
158 0 : hmac_update(hmac_ctx_t *state, const uint8_t *message, int msg_octets) {
159 :
160 : debug_print(mod_hmac, "input: %s",
161 : octet_string_hex_string(message, msg_octets));
162 :
163 : /* hash message into sha1 context */
164 0 : sha1_update(&state->ctx, message, msg_octets);
165 :
166 0 : return err_status_ok;
167 : }
168 :
169 : err_status_t
170 0 : hmac_compute(hmac_ctx_t *state, const void *message,
171 : int msg_octets, int tag_len, uint8_t *result) {
172 : uint32_t hash_value[5];
173 : uint32_t H[5];
174 : int i;
175 :
176 : /* check tag length, return error if we can't provide the value expected */
177 0 : if (tag_len > 20)
178 0 : return err_status_bad_param;
179 :
180 : /* hash message, copy output into H */
181 0 : hmac_update(state, (const uint8_t*)message, msg_octets);
182 0 : sha1_final(&state->ctx, H);
183 :
184 : /*
185 : * note that we don't need to debug_print() the input, since the
186 : * function hmac_update() already did that for us
187 : */
188 : debug_print(mod_hmac, "intermediate state: %s",
189 : octet_string_hex_string((uint8_t *)H, 20));
190 :
191 : /* re-initialize hash context */
192 0 : sha1_init(&state->ctx);
193 :
194 : /* hash opad ^ key */
195 0 : sha1_update(&state->ctx, (uint8_t *)state->opad, 64);
196 :
197 : /* hash the result of the inner hash */
198 0 : sha1_update(&state->ctx, (uint8_t *)H, 20);
199 :
200 : /* the result is returned in the array hash_value[] */
201 0 : sha1_final(&state->ctx, hash_value);
202 :
203 : /* copy hash_value to *result */
204 0 : for (i=0; i < tag_len; i++)
205 0 : result[i] = ((uint8_t *)hash_value)[i];
206 :
207 : debug_print(mod_hmac, "output: %s",
208 : octet_string_hex_string((uint8_t *)hash_value, tag_len));
209 :
210 0 : return err_status_ok;
211 : }
212 :
213 :
214 : /* begin test case 0 */
215 :
216 : uint8_t
217 : hmac_test_case_0_key[20] = {
218 : 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
219 : 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
220 : 0x0b, 0x0b, 0x0b, 0x0b
221 : };
222 :
223 : uint8_t
224 : hmac_test_case_0_data[8] = {
225 : 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */
226 : };
227 :
228 : uint8_t
229 : hmac_test_case_0_tag[20] = {
230 : 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
231 : 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
232 : 0xf1, 0x46, 0xbe, 0x00
233 : };
234 :
235 : auth_test_case_t
236 : hmac_test_case_0 = {
237 : 20, /* octets in key */
238 : hmac_test_case_0_key, /* key */
239 : 8, /* octets in data */
240 : hmac_test_case_0_data, /* data */
241 : 20, /* octets in tag */
242 : hmac_test_case_0_tag, /* tag */
243 : NULL /* pointer to next testcase */
244 : };
245 :
246 : /* end test case 0 */
247 :
248 : char hmac_description[] = "hmac sha-1 authentication function";
249 :
250 : /*
251 : * auth_type_t hmac is the hmac metaobject
252 : */
253 :
254 : auth_type_t
255 : hmac = {
256 : (auth_alloc_func) hmac_alloc,
257 : (auth_dealloc_func) hmac_dealloc,
258 : (auth_init_func) hmac_init,
259 : (auth_compute_func) hmac_compute,
260 : (auth_update_func) hmac_update,
261 : (auth_start_func) hmac_start,
262 : (char *) hmac_description,
263 : (int) 0, /* instance count */
264 : (auth_test_case_t *) &hmac_test_case_0,
265 : (debug_module_t *) &mod_hmac,
266 : (auth_type_id_t) HMAC_SHA1
267 : };
268 :
|