Annotation of embedaddon/dhcp/dst/hmac_link.c, revision 1.1.1.1.2.1
1.1 misho 1: #ifdef HMAC_MD5
2: #ifndef LINT
1.1.1.1.2.1! misho 3: static const char rcsid[] = "$Header: /home/cvs/embedaddon/dhcp/dst/hmac_link.c,v 1.1.1.1 2012/10/09 09:06:54 misho Exp $";
1.1 misho 4: #endif
5: /*
6: * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
7: * Portions Copyright (c) 2007 by Internet Systems Consortium, Inc. ("ISC")
8: *
9: * Permission to use, copy modify, and distribute this software for any
10: * purpose with or without fee is hereby granted, provided that the above
11: * copyright notice and this permission notice appear in all copies.
12: *
13: * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
14: * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
16: * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
17: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
18: * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
19: * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
20: * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
21: */
22:
23: /*
24: * This file contains an implementation of the HMAC-MD5 algorithm.
25: */
26:
27: #include <stdio.h>
28: #include <unistd.h>
29: #include <stdlib.h>
30: #include <string.h>
31: #include <memory.h>
32: #include <sys/param.h>
33: #include <sys/time.h>
34: #include <netinet/in.h>
35: #include <sys/socket.h>
36:
37: #include "minires/minires.h"
38: #include "arpa/nameser.h"
39:
40: #include "dst_internal.h"
41:
42: #ifdef USE_MD5
43: # include "md5.h"
44: # ifndef _MD5_H_
45: # define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */
46: # endif
47: #endif
48:
49: #define HMAC_LEN 64
50: #define HMAC_IPAD 0x36
51: #define HMAC_OPAD 0x5c
52: #define MD5_LEN 16
53:
54:
55: typedef struct hmackey {
56: u_char hk_ipad[64], hk_opad[64];
57: } HMAC_Key;
58:
59:
60: /**************************************************************************
61: * dst_hmac_md5_sign
62: * Call HMAC signing functions to sign a block of data.
63: * There are three steps to signing, INIT (initialize structures),
64: * UPDATE (hash (more) data), FINAL (generate a signature). This
65: * routine performs one or more of these steps.
66: * Parameters
67: * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
68: * priv_key key to use for signing.
69: * context the context to be used in this digest
70: * data data to be signed.
71: * len length in bytes of data.
72: * signature location to store signature.
73: * sig_len size of the signature location
74: * returns
75: * N Success on SIG_MODE_FINAL = returns signature length in bytes
76: * 0 Success on SIG_MODE_INIT and UPDATE
77: * <0 Failure
78: */
79:
80: static int
81: dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context,
82: const u_char *data, const unsigned len,
83: u_char *signature, const unsigned sig_len)
84: {
85: HMAC_Key *key;
86: int sign_len = 0;
87: MD5_CTX *ctx = NULL;
88:
89: if (mode & SIG_MODE_INIT)
90: ctx = (MD5_CTX *) malloc(sizeof(*ctx));
91: else if (context)
92: ctx = (MD5_CTX *) *context;
93: if (ctx == NULL)
94: return (-1);
95:
96: if (d_key == NULL || d_key->dk_KEY_struct == NULL)
97: return (-1);
98: key = (HMAC_Key *) d_key->dk_KEY_struct;
99:
100: if (mode & SIG_MODE_INIT) {
101: MD5Init(ctx);
102: MD5Update(ctx, key->hk_ipad, HMAC_LEN);
103: }
104:
105: if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
106: MD5Update(ctx, (const unsigned char *)data, len);
107:
108: if (mode & SIG_MODE_FINAL) {
109: if (signature == NULL || sig_len < MD5_LEN)
110: return (SIGN_FINAL_FAILURE);
111: MD5Final(signature, ctx);
112:
113: /* perform outer MD5 */
114: MD5Init(ctx);
115: MD5Update(ctx, key->hk_opad, HMAC_LEN);
116: MD5Update(ctx, signature, MD5_LEN);
117: MD5Final(signature, ctx);
118: sign_len = MD5_LEN;
119: SAFE_FREE(ctx);
120: }
121: else {
122: if (context == NULL)
123: return (-1);
124: *context = (void *) ctx;
125: }
126: return (sign_len);
127: }
128:
129:
130: /**************************************************************************
131: * dst_hmac_md5_verify()
132: * Calls HMAC verification routines. There are three steps to
133: * verification, INIT (initialize structures), UPDATE (hash (more) data),
134: * FINAL (generate a signature). This routine performs one or more of
135: * these steps.
136: * Parameters
137: * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
138: * dkey key to use for verify.
139: * data data signed.
140: * len length in bytes of data.
141: * signature signature.
142: * sig_len length in bytes of signature.
143: * returns
144: * 0 Success
145: * <0 Failure
146: */
147:
148: static int
149: dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
150: const u_char *data, const unsigned len,
151: const u_char *signature, const unsigned sig_len)
152: {
153: HMAC_Key *key;
154: MD5_CTX *ctx = NULL;
155:
156: if (mode & SIG_MODE_INIT)
157: ctx = (MD5_CTX *) malloc(sizeof(*ctx));
158: else if (context)
159: ctx = (MD5_CTX *) *context;
160: if (ctx == NULL)
161: return (-1);
162:
163: if (d_key == NULL || d_key->dk_KEY_struct == NULL)
164: return (-1);
165:
166: key = (HMAC_Key *) d_key->dk_KEY_struct;
167: if (mode & SIG_MODE_INIT) {
168: MD5Init(ctx);
169: MD5Update(ctx, key->hk_ipad, HMAC_LEN);
170: }
171: if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
172: MD5Update(ctx, (const unsigned char *)data, len);
173:
174: if (mode & SIG_MODE_FINAL) {
175: u_char digest[MD5_LEN];
176: if (signature == NULL || key == NULL || sig_len != MD5_LEN)
177: return (VERIFY_FINAL_FAILURE);
178: MD5Final(digest, ctx);
179:
180: /* perform outer MD5 */
181: MD5Init(ctx);
182: MD5Update(ctx, key->hk_opad, HMAC_LEN);
183: MD5Update(ctx, digest, MD5_LEN);
184: MD5Final(digest, ctx);
185:
186: SAFE_FREE(ctx);
187: if (memcmp(digest, signature, MD5_LEN) != 0)
188: return (VERIFY_FINAL_FAILURE);
189: }
190: else {
191: if (context == NULL)
192: return (-1);
193: *context = (void *) ctx;
194: }
195: return (0);
196: }
197:
198:
199: /**************************************************************************
200: * dst_buffer_to_hmac_md5
201: * Converts key from raw data to an HMAC Key
202: * This function gets in a pointer to the data
203: * Parameters
204: * hkey the HMAC key to be filled in
205: * key the key in raw format
206: * keylen the length of the key
207: * Return
208: * 0 Success
209: * <0 Failure
210: */
211: static int
212: dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const unsigned keylen)
213: {
214: int i;
215: HMAC_Key *hkey = NULL;
216: MD5_CTX ctx;
217: unsigned local_keylen = keylen;
218:
1.1.1.1.2.1! misho 219: if (dkey == NULL || key == NULL)
1.1 misho 220: return (-1);
221:
222: if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
223: return (-2);
224:
225: memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
226: memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
227:
228: /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
229: if (keylen > HMAC_LEN) {
230: u_char tk[MD5_LEN];
231: MD5Init(&ctx);
232: MD5Update(&ctx, (const unsigned char *)key, keylen);
233: MD5Final(tk, &ctx);
234: memset((void *) &ctx, 0, sizeof(ctx));
235: key = tk;
236: local_keylen = MD5_LEN;
237: }
238: /* start out by storing key in pads */
239: memcpy(hkey->hk_ipad, key, local_keylen);
240: memcpy(hkey->hk_opad, key, local_keylen);
241:
242: /* XOR key with hk_ipad and opad values */
243: for (i = 0; i < HMAC_LEN; i++) {
244: hkey->hk_ipad[i] ^= HMAC_IPAD;
245: hkey->hk_opad[i] ^= HMAC_OPAD;
246: }
247: dkey->dk_key_size = local_keylen;
248: dkey->dk_KEY_struct = (void *) hkey;
249: return (1);
250: }
251:
252:
253: /**************************************************************************
254: * dst_hmac_md5_key_to_file_format
255: * Encodes an HMAC Key into the portable file format.
256: * Parameters
257: * hkey HMAC KEY structure
258: * buff output buffer
259: * buff_len size of output buffer
260: * Return
261: * 0 Failure - null input hkey
262: * -1 Failure - not enough space in output area
263: * N Success - Length of data returned in buff
264: */
265:
266: static int
267: dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
268: const unsigned buff_len)
269: {
270: char *bp;
271: int i;
272: unsigned len, b_len, key_len;
273: u_char key[HMAC_LEN];
274: HMAC_Key *hkey;
275:
276: if (dkey == NULL || dkey->dk_KEY_struct == NULL)
277: return (0);
278: if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
279: return (-1); /* no OR not enough space in output area */
280:
281: hkey = (HMAC_Key *) dkey->dk_KEY_struct;
282: memset(buff, 0, buff_len); /* just in case */
283: /* write file header */
284: sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
285:
286: bp = (char *) strchr(buff, '\0');
287: b_len = buff_len - (bp - buff);
288:
289: memset(key, 0, HMAC_LEN);
290: for (i = 0; i < HMAC_LEN; i++)
291: key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
292: for (i = HMAC_LEN - 1; i >= 0; i--)
293: if (key[i] != 0)
294: break;
295: key_len = i + 1;
296:
297: strcat(bp, "Key: ");
298: bp += strlen("Key: ");
299: b_len = buff_len - (bp - buff);
300:
301: len = b64_ntop(key, key_len, bp, b_len);
1.1.1.1.2.1! misho 302: if ((int) len < 0)
1.1 misho 303: return (-1);
304: bp += len;
305: *(bp++) = '\n';
306: *bp = '\0';
307: b_len = buff_len - (bp - buff);
308:
309: return (buff_len - b_len);
310: }
311:
312:
313: /**************************************************************************
314: * dst_hmac_md5_key_from_file_format
315: * Converts contents of a key file into an HMAC key.
316: * Parameters
317: * hkey structure to put key into
318: * buff buffer containing the encoded key
319: * buff_len the length of the buffer
320: * Return
321: * n >= 0 Foot print of the key converted
322: * n < 0 Error in conversion
323: */
324:
325: static int
326: dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
327: const unsigned buff_len)
328: {
329: const char *p = buff, *eol;
330: u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode
331: * it should probably be fixed rather than doing
332: * this
333: */
334: u_char *tmp;
335: unsigned key_len, len;
336:
337: if (dkey == NULL)
338: return (-2);
339: if (buff == NULL)
340: return (-1);
341:
342: memset(key, 0, sizeof(key));
343:
344: if (!dst_s_verify_str(&p, "Key: "))
345: return (-3);
346:
347: eol = strchr(p, '\n');
348: if (eol == NULL)
349: return (-4);
350: len = eol - p;
351: tmp = malloc(len + 2);
352: memcpy(tmp, p, len);
353: *(tmp + len) = 0x0;
354: key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */
355: SAFE_FREE2(tmp, len + 2);
356:
357: if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
358: return (-6);
359: }
360: return (0);
361: }
362:
363: /*
364: * dst_hmac_md5_to_dns_key()
365: * function to extract hmac key from DST_KEY structure
366: * input:
367: * in_key: HMAC-MD5 key
368: * output:
369: * out_str: buffer to write ot
370: * out_len: size of output buffer
371: * returns:
372: * number of bytes written to output buffer
373: */
374: static int
375: dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
376: const unsigned out_len)
377: {
378:
379: HMAC_Key *hkey;
380: int i;
381:
382: if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
383: out_len <= in_key->dk_key_size || out_str == NULL)
384: return (-1);
385:
386: hkey = (HMAC_Key *) in_key->dk_KEY_struct;
387: for (i = 0; i < in_key->dk_key_size; i++)
388: out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
389: return (i);
390: }
391:
392: /**************************************************************************
393: * dst_hmac_md5_compare_keys
394: * Compare two keys for equality.
395: * Return
396: * 0 The keys are equal
397: * NON-ZERO The keys are not equal
398: */
399:
400: static int
401: dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
402: {
403: HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct;
404: HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct;
405: return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN);
406: }
407:
408: /**************************************************************************
409: * dst_hmac_md5_free_key_structure
410: * Frees all (none) dynamically allocated structures in hkey
411: */
412:
413: static void *
414: dst_hmac_md5_free_key_structure(void *key)
415: {
416: HMAC_Key *hkey = key;
417: SAFE_FREE(hkey);
418: return (NULL);
419: }
420:
421:
422: /***************************************************************************
423: * dst_hmac_md5_generate_key
424: * Creates a HMAC key of size size with a maximum size of 63 bytes
425: * generating a HMAC key larger than 63 bytes makes no sense as that key
426: * is digested before use.
427: */
428:
429: static int
430: dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
431: {
432: u_char *buff;
433: int n;
434: unsigned size, len;
435:
436: if (key == NULL || key->dk_alg != KEY_HMAC_MD5)
437: return (0);
438: size = (key->dk_key_size + 7) / 8; /* convert to bytes */
439: if (size <= 0)
440: return(0);
441:
442: len = size > 64 ? 64 : size;
443: buff = malloc(len+8);
444:
445: n = dst_random(DST_RAND_SEMI, len, buff);
446: n += dst_random(DST_RAND_KEY, len, buff);
447: if (n <= len) { /* failed getting anything */
448: SAFE_FREE2(buff, len);
449: return (-1);
450: }
451: n = dst_buffer_to_hmac_md5(key, buff, len);
452: SAFE_FREE2(buff, len);
453: if (n <= 0)
454: return (n);
455: return (1);
456: }
457:
458: /*
459: * dst_hmac_md5_init() Function to answer set up function pointers for HMAC
460: * related functions
461: */
462: int
463: dst_hmac_md5_init()
464: {
465: if (dst_t_func[KEY_HMAC_MD5] != NULL)
466: return (1);
467: dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
468: if (dst_t_func[KEY_HMAC_MD5] == NULL)
469: return (0);
470: memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
471: dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
472: dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
473: dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
474: dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
475: dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
476: dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
477: dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
478: dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
479: dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
480: return (1);
481: }
482:
483: #else
484: int
485: dst_hmac_md5_init(){
486: return (0);
487: }
488: #endif
489:
490:
491:
492:
493:
494:
495:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>