File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / dst / hmac_link.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    1: #ifdef HMAC_MD5
    2: #ifndef LINT
    3: static const char rcsid[] = "$Header: /usr/local/www/users/anoncvs/cvs/embedaddon/dhcp/dst/hmac_link.c,v 1.1.1.1 2012/10/09 09:06:54 misho 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>