Branch data Line data Source code
1 : : /*
2 : : *****************************************************************************
3 : : *
4 : : * File: fko_hmac.c
5 : : *
6 : : * Purpose: Provide HMAC support to SPA communications
7 : : *
8 : : * Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
9 : : * Copyright (C) 2009-2014 fwknop developers and contributors. For a full
10 : : * list of contributors, see the file 'CREDITS'.
11 : : *
12 : : * License (GNU General Public License):
13 : : *
14 : : * This program is free software; you can redistribute it and/or
15 : : * modify it under the terms of the GNU General Public License
16 : : * as published by the Free Software Foundation; either version 2
17 : : * of the License, or (at your option) any later version.
18 : : *
19 : : * This program is distributed in the hope that it will be useful,
20 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 : : * GNU General Public License for more details.
23 : : *
24 : : * You should have received a copy of the GNU General Public License
25 : : * along with this program; if not, write to the Free Software
26 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 : : * USA
28 : : *
29 : : *****************************************************************************
30 : : */
31 : :
32 : : #include "hmac.h"
33 : :
34 : : typedef struct {
35 : : MD5Context ctx_inside;
36 : : MD5Context ctx_outside;
37 : :
38 : : unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
39 : : unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
40 : : } hmac_md5_ctx;
41 : :
42 : : typedef struct {
43 : : SHA1_INFO ctx_inside;
44 : : SHA1_INFO ctx_outside;
45 : :
46 : : unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
47 : : unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
48 : : } hmac_sha1_ctx;
49 : :
50 : : typedef struct {
51 : : SHA256_CTX ctx_inside;
52 : : SHA256_CTX ctx_outside;
53 : :
54 : : unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
55 : : unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
56 : : } hmac_sha256_ctx;
57 : :
58 : : typedef struct {
59 : : SHA384_CTX ctx_inside;
60 : : SHA384_CTX ctx_outside;
61 : :
62 : : unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
63 : : unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
64 : : } hmac_sha384_ctx;
65 : :
66 : : typedef struct {
67 : : SHA512_CTX ctx_inside;
68 : : SHA512_CTX ctx_outside;
69 : :
70 : : unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
71 : : unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
72 : : } hmac_sha512_ctx;
73 : :
74 : : static void
75 : 686 : pad_init(unsigned char *inner_pad, unsigned char *outer_pad,
76 : : const unsigned char * const key, const int key_len)
77 : : {
78 : 686 : int i = 0;
79 : :
80 [ + + ]: 33746 : for (i=0; i < MAX_DIGEST_BLOCK_LEN && i < key_len; i++) {
81 : 33060 : inner_pad[i] = key[i] ^ 0x36;
82 : 33060 : outer_pad[i] = key[i] ^ 0x5c;
83 : : }
84 : :
85 [ + + ]: 686 : if(i < MAX_DIGEST_BLOCK_LEN)
86 : : {
87 [ + + ]: 55396 : while(i < MAX_DIGEST_BLOCK_LEN)
88 : : {
89 : 54748 : inner_pad[i] = 0x36;
90 : 54748 : outer_pad[i] = 0x5c;
91 : 54748 : i++;
92 : : }
93 : : }
94 : 686 : return;
95 : : }
96 : :
97 : : /* Begin MD5 HMAC functions
98 : : */
99 : : static void
100 : 0 : hmac_md5_init(hmac_md5_ctx *ctx, const char *key, const int key_len)
101 : : {
102 : 0 : unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
103 : 0 : unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
104 : 0 : int final_len = key_len;
105 : :
106 [ # # ]: 0 : if(key_len > MAX_DIGEST_BLOCK_LEN)
107 : 0 : final_len = MAX_DIGEST_BLOCK_LEN;
108 : :
109 : 0 : memcpy(init_key, key, final_len);
110 : :
111 [ # # ]: 0 : if(MD5_BLOCK_LEN < key_len)
112 : : {
113 : : /* Calculate the digest of the key
114 : : */
115 : 0 : md5(final_key, init_key, final_len);
116 : : }
117 : : else
118 : : {
119 : 0 : memcpy(final_key, init_key, key_len);
120 : : }
121 : :
122 : 0 : pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
123 : :
124 : 0 : MD5Init(&ctx->ctx_inside);
125 : 0 : MD5Update(&ctx->ctx_inside, ctx->block_inner_pad, MD5_BLOCK_LEN);
126 : :
127 : 0 : MD5Init(&ctx->ctx_outside);
128 : 0 : MD5Update(&ctx->ctx_outside, ctx->block_outer_pad, MD5_BLOCK_LEN);
129 : :
130 : 0 : return;
131 : : }
132 : :
133 : : static void
134 : 0 : hmac_md5_update(hmac_md5_ctx *ctx, const char *msg,
135 : : unsigned int msg_len)
136 : : {
137 : 0 : MD5Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
138 : 0 : return;
139 : : }
140 : :
141 : : static void
142 : 0 : hmac_md5_final(hmac_md5_ctx *ctx, unsigned char *hmac)
143 : : {
144 : : unsigned char digest_inside[MD5_DIGEST_LEN];
145 : :
146 : 0 : MD5Final(digest_inside, &ctx->ctx_inside);
147 : 0 : MD5Update(&ctx->ctx_outside, digest_inside, MD5_DIGEST_LEN);
148 : 0 : MD5Final(hmac, &ctx->ctx_outside);
149 : :
150 : 0 : return;
151 : : }
152 : :
153 : : void
154 : 0 : hmac_md5(const char *msg, const unsigned int msg_len,
155 : : unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
156 : : {
157 : : hmac_md5_ctx ctx;
158 : :
159 : : memset(&ctx, 0, sizeof(ctx));
160 : :
161 : 0 : hmac_md5_init(&ctx, hmac_key, hmac_key_len);
162 : 0 : hmac_md5_update(&ctx, msg, msg_len);
163 : 0 : hmac_md5_final(&ctx, hmac);
164 : :
165 : 0 : return;
166 : : }
167 : :
168 : : /* Begin SHA1 HMAC functions
169 : : */
170 : : static void
171 : 146 : hmac_sha1_init(hmac_sha1_ctx *ctx, const char *key, const int key_len)
172 : : {
173 : 146 : unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
174 : 146 : unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
175 : 146 : int final_len = key_len;
176 : :
177 [ - + ]: 146 : if(key_len > MAX_DIGEST_BLOCK_LEN)
178 : 0 : final_len = MAX_DIGEST_BLOCK_LEN;
179 : :
180 : 146 : memcpy(init_key, key, final_len);
181 : :
182 [ + + ]: 146 : if(SHA1_BLOCK_LEN < key_len)
183 : : {
184 : : /* Calculate the digest of the key
185 : : */
186 : 108 : sha1(final_key, init_key, final_len);
187 : : }
188 : : else
189 : : {
190 : 38 : memcpy(final_key, init_key, key_len);
191 : : }
192 : :
193 : 146 : pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
194 : :
195 : 146 : sha1_init(&ctx->ctx_inside);
196 : 146 : sha1_update(&ctx->ctx_inside, ctx->block_inner_pad, SHA1_BLOCK_LEN);
197 : :
198 : 146 : sha1_init(&ctx->ctx_outside);
199 : 146 : sha1_update(&ctx->ctx_outside, ctx->block_outer_pad, SHA1_BLOCK_LEN);
200 : :
201 : 146 : return;
202 : : }
203 : :
204 : : static void
205 : 146 : hmac_sha1_update(hmac_sha1_ctx *ctx, const char *msg,
206 : : unsigned int msg_len)
207 : : {
208 : 146 : sha1_update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
209 : 146 : return;
210 : : }
211 : :
212 : : static void
213 : 146 : hmac_sha1_final(hmac_sha1_ctx *ctx, unsigned char *hmac)
214 : : {
215 : : unsigned char digest_inside[SHA1_DIGEST_LEN];
216 : :
217 : 146 : sha1_final(digest_inside, &ctx->ctx_inside);
218 : 146 : sha1_update(&ctx->ctx_outside, digest_inside, SHA1_DIGEST_LEN);
219 : 146 : sha1_final(hmac, &ctx->ctx_outside);
220 : :
221 : 146 : return;
222 : : }
223 : :
224 : : void
225 : 146 : hmac_sha1(const char *msg, const unsigned int msg_len,
226 : : unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
227 : : {
228 : : hmac_sha1_ctx ctx;
229 : :
230 : : memset(&ctx, 0, sizeof(ctx));
231 : :
232 : 146 : hmac_sha1_init(&ctx, hmac_key, hmac_key_len);
233 : 146 : hmac_sha1_update(&ctx, msg, msg_len);
234 : 146 : hmac_sha1_final(&ctx, hmac);
235 : :
236 : 146 : return;
237 : : }
238 : :
239 : : /* Begin SHA256 HMAC functions
240 : : */
241 : : static void
242 : 540 : hmac_sha256_init(hmac_sha256_ctx *ctx, const char *key, const int key_len)
243 : : {
244 : 540 : unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
245 : 540 : unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
246 : 540 : int final_len = key_len;
247 : :
248 [ - + ]: 540 : if(key_len > MAX_DIGEST_BLOCK_LEN)
249 : 0 : final_len = MAX_DIGEST_BLOCK_LEN;
250 : :
251 : 540 : memcpy(init_key, key, final_len);
252 : :
253 [ + + ]: 540 : if(SHA256_BLOCK_LEN < key_len)
254 : : {
255 : : /* Calculate the digest of the key
256 : : */
257 : 166 : sha256(final_key, init_key, final_len);
258 : : }
259 : : else
260 : : {
261 : 374 : memcpy(final_key, init_key, key_len);
262 : : }
263 : :
264 : 540 : pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
265 : :
266 : 540 : SHA256_Init(&ctx->ctx_inside);
267 : 540 : SHA256_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA256_BLOCK_LEN);
268 : :
269 : 540 : SHA256_Init(&ctx->ctx_outside);
270 : 540 : SHA256_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA256_BLOCK_LEN);
271 : :
272 : 540 : return;
273 : : }
274 : :
275 : : static void
276 : 540 : hmac_sha256_update(hmac_sha256_ctx *ctx, const char *msg,
277 : : unsigned int msg_len)
278 : : {
279 : 540 : SHA256_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
280 : 540 : return;
281 : : }
282 : :
283 : : static void
284 : 540 : hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *hmac)
285 : : {
286 : : unsigned char digest_inside[SHA256_DIGEST_LEN];
287 : :
288 : 540 : SHA256_Final(digest_inside, &ctx->ctx_inside);
289 : 540 : SHA256_Update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_LEN);
290 : 540 : SHA256_Final(hmac, &ctx->ctx_outside);
291 : :
292 : 540 : return;
293 : : }
294 : :
295 : : void
296 : 540 : hmac_sha256(const char *msg, const unsigned int msg_len,
297 : : unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
298 : : {
299 : : hmac_sha256_ctx ctx;
300 : :
301 : : memset(&ctx, 0, sizeof(ctx));
302 : :
303 : 540 : hmac_sha256_init(&ctx, hmac_key, hmac_key_len);
304 : 540 : hmac_sha256_update(&ctx, msg, msg_len);
305 : 540 : hmac_sha256_final(&ctx, hmac);
306 : :
307 : 540 : return;
308 : : }
309 : :
310 : : /* Begin SHA384 HMAC functions
311 : : */
312 : : static void
313 : 0 : hmac_sha384_init(hmac_sha384_ctx *ctx, const char *key, const int key_len)
314 : : {
315 : 0 : unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
316 : 0 : int final_len = key_len;
317 : :
318 [ # # ]: 0 : if(key_len > MAX_DIGEST_BLOCK_LEN)
319 : 0 : final_len = MAX_DIGEST_BLOCK_LEN;
320 : :
321 : : /* When we eventually support arbitrary key sizes, take the digest
322 : : * of the key with: sha384(final_key, init_key, final_len);
323 : : */
324 : 0 : memcpy(final_key, key, final_len);
325 : :
326 : 0 : pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
327 : :
328 : 0 : SHA384_Init(&ctx->ctx_inside);
329 : 0 : SHA384_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA384_BLOCK_LEN);
330 : :
331 : 0 : SHA384_Init(&ctx->ctx_outside);
332 : 0 : SHA384_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA384_BLOCK_LEN);
333 : :
334 : 0 : return;
335 : : }
336 : :
337 : : static void
338 : 0 : hmac_sha384_update(hmac_sha384_ctx *ctx, const char *msg,
339 : : unsigned int msg_len)
340 : : {
341 : 0 : SHA384_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
342 : 0 : return;
343 : : }
344 : :
345 : : static void
346 : 0 : hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *hmac)
347 : : {
348 : : unsigned char digest_inside[SHA384_DIGEST_LEN];
349 : :
350 : 0 : SHA384_Final(digest_inside, &ctx->ctx_inside);
351 : 0 : SHA384_Update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_LEN);
352 : 0 : SHA384_Final(hmac, &ctx->ctx_outside);
353 : :
354 : 0 : return;
355 : : }
356 : :
357 : : void
358 : 0 : hmac_sha384(const char *msg, const unsigned int msg_len,
359 : : unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
360 : : {
361 : : hmac_sha384_ctx ctx;
362 : :
363 : : memset(&ctx, 0, sizeof(ctx));
364 : :
365 : 0 : hmac_sha384_init(&ctx, hmac_key, hmac_key_len);
366 : 0 : hmac_sha384_update(&ctx, msg, msg_len);
367 : 0 : hmac_sha384_final(&ctx, hmac);
368 : :
369 : 0 : return;
370 : : }
371 : :
372 : : /* Begin SHA512 HMAC functions
373 : : */
374 : : static void
375 : 0 : hmac_sha512_init(hmac_sha512_ctx *ctx, const char *key, const int key_len)
376 : : {
377 : 0 : unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
378 : 0 : int final_len = key_len;
379 : :
380 [ # # ]: 0 : if(key_len > MAX_DIGEST_BLOCK_LEN)
381 : 0 : final_len = MAX_DIGEST_BLOCK_LEN;
382 : :
383 : : /* When we eventually support arbitrary key sizes, take the digest
384 : : * of the key with: sha512(final_key, init_key, final_len);
385 : : */
386 : 0 : memcpy(final_key, key, final_len);
387 : :
388 : 0 : pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
389 : :
390 : 0 : SHA512_Init(&ctx->ctx_inside);
391 : 0 : SHA512_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA512_BLOCK_LEN);
392 : :
393 : 0 : SHA512_Init(&ctx->ctx_outside);
394 : 0 : SHA512_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA512_BLOCK_LEN);
395 : :
396 : 0 : return;
397 : : }
398 : :
399 : : static void
400 : 0 : hmac_sha512_update(hmac_sha512_ctx *ctx, const char *msg,
401 : : unsigned int msg_len)
402 : : {
403 : 0 : SHA512_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
404 : 0 : return;
405 : : }
406 : :
407 : : static void
408 : 0 : hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *hmac)
409 : : {
410 : : unsigned char digest_inside[SHA512_DIGEST_LEN];
411 : :
412 : 0 : SHA512_Final(digest_inside, &ctx->ctx_inside);
413 : 0 : SHA512_Update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_LEN);
414 : 0 : SHA512_Final(hmac, &ctx->ctx_outside);
415 : :
416 : 0 : return;
417 : : }
418 : :
419 : : void
420 : 0 : hmac_sha512(const char *msg, const unsigned int msg_len,
421 : : unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
422 : : {
423 : : hmac_sha512_ctx ctx;
424 : :
425 : : memset(&ctx, 0, sizeof(ctx));
426 : :
427 : 0 : hmac_sha512_init(&ctx, hmac_key, hmac_key_len);
428 : 0 : hmac_sha512_update(&ctx, msg, msg_len);
429 : 0 : hmac_sha512_final(&ctx, hmac);
430 : :
431 : 0 : return;
432 : : }
|