Annotation of embedaddon/dhcp/dst/hmac_link.c, revision 1.1
1.1 ! misho 1: #ifdef HMAC_MD5
! 2: #ifndef LINT
! 3: static const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/hmac_link.c,v 1.3 2007-12-06 00:50:22 dhankins Exp $";
! 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:
! 219: if (dkey == NULL || key == NULL || keylen < 0)
! 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);
! 302: if (len < 0)
! 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>