File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / dst / dst_api.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: #ifndef LINT
    2: static const char rcsid[] = "$Header: /usr/local/www/users/anoncvs/cvs/embedaddon/dhcp/dst/dst_api.c,v 1.1.1.1 2012/10/09 09:06:54 misho Exp $";
    3: #endif
    4: 
    5: /*
    6:  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
    7:  * Portions Copyright (c) 2007,2009 by Internet Systems Consortium, Inc. ("ISC")
    8:  * Portions Copyright (c) 2012 by Internet Systems Consortium, Inc. ("ISC")
    9:  *
   10:  * Permission to use, copy modify, and distribute this software for any
   11:  * purpose with or without fee is hereby granted, provided that the above
   12:  * copyright notice and this permission notice appear in all copies.
   13:  *
   14:  * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
   15:  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
   17:  * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
   18:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
   19:  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
   20:  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
   21:  * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
   22:  */
   23: /*
   24:  * This file contains the interface between the DST API and the crypto API.
   25:  * This is the only file that needs to be changed if the crypto system is
   26:  * changed.  Exported functions are:
   27:  * void dst_init()	 Initialize the toolkit
   28:  * int  dst_check_algorithm()   Function to determines if alg is supported.
   29:  * int  dst_compare_keys()      Function to compare two keys for equality.
   30:  * int  dst_sign_data()         Incremental signing routine.
   31:  * int  dst_verify_data()       Incremental verify routine.
   32:  * int  dst_generate_key()      Function to generate new KEY
   33:  * DST_KEY *dst_read_key()      Function to retrieve private/public KEY.
   34:  * void dst_write_key()         Function to write out a key.
   35:  * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST
   36:  *				KEY structure.
   37:  * int dst_key_to_dnskey() 	Function to return a public key in DNS 
   38:  *				format binary
   39:  * DST_KEY *dst_buffer_to_key() Convert a data in buffer to KEY
   40:  * int *dst_key_to_buffer()	Writes out DST_KEY key material in buffer
   41:  * void dst_free_key()       	Releases all memory referenced by key structure
   42:  */
   43: 
   44: #include <stdio.h>
   45: #include <errno.h>
   46: #include <fcntl.h>
   47: #include <stdlib.h>
   48: #include <unistd.h>
   49: #include <string.h>
   50: #include <memory.h>
   51: #include <ctype.h>
   52: #include <time.h>
   53: #include <sys/param.h>
   54: #include <sys/stat.h>
   55: #include <sys/socket.h>
   56: #include <netinet/in.h>
   57: 
   58: #include "minires/minires.h"
   59: #include "arpa/nameser.h"
   60: 
   61: #include "dst_internal.h"
   62: 
   63: /* static variables */
   64: static int done_init = 0;
   65: dst_func *dst_t_func[DST_MAX_ALGS];
   66: const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n";
   67: const char *dst_path = "";
   68: 
   69: /* internal I/O functions */
   70: static DST_KEY *dst_s_read_public_key(const char *in_name, 
   71: 				      const unsigned in_id, int in_alg);
   72: static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key,
   73: 				       unsigned in_id, int in_alg);
   74: static int dst_s_write_public_key(const DST_KEY *key);
   75: static int dst_s_write_private_key(const DST_KEY *key);
   76: 
   77: /* internal function to set up data structure */
   78: static DST_KEY *dst_s_get_key_struct(const char *name, const int alg,
   79: 				     const u_int32_t flags, const int protocol,
   80: 				     const int bits);
   81: 
   82: /*
   83:  *  dst_init
   84:  *	This function initializes the Digital Signature Toolkit.
   85:  *	Right now, it just checks the DSTKEYPATH environment variable.
   86:  *  Parameters
   87:  *	none
   88:  *  Returns
   89:  *	none
   90:  */
   91: void
   92: dst_init()
   93: {
   94: 	char *s;
   95: 	unsigned len;
   96: 
   97: 	if (done_init != 0)
   98: 		return;
   99: 	done_init = 1;
  100: 
  101: 	s = getenv("DSTKEYPATH");
  102: 	len = 0;
  103: 	if (s) {
  104: 		struct stat statbuf;
  105: 
  106: 		len = strlen(s);
  107: 		if (len > PATH_MAX) {
  108: 			EREPORT(("%s is longer than %d characters, ignoring\n",
  109: 				 s, PATH_MAX));
  110: 		} else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
  111: 			EREPORT(("%s is not a valid directory\n", s));
  112: 		} else {
  113: 			char *dp = (char *) malloc(len + 2);
  114: 			int l;
  115: 			memcpy(dp, s, len + 1);
  116: 			l = strlen (dp);
  117: 			if (dp[l - 1] != '/') {
  118: 				dp[l + 1] = 0;
  119: 				dp[l] = '/';
  120: 			}
  121: 			dst_path = dp;
  122: 		}
  123: 	}
  124: 	memset(dst_t_func, 0, sizeof(dst_t_func));
  125: 	/* first one is selected */
  126: #if 0
  127: 	dst_bsafe_init();
  128: 	dst_rsaref_init(); 
  129: #endif
  130: 	dst_hmac_md5_init();
  131: #if 0
  132: 	dst_eay_dss_init();
  133: 	dst_cylink_init();
  134: #endif
  135: }
  136: 
  137: /*
  138:  *  dst_check_algorithm
  139:  *	This function determines if the crypto system for the specified
  140:  *	algorithm is present.
  141:  *  Parameters
  142:  *	alg     1       KEY_RSA
  143:  *		3       KEY_DSA
  144:  *	      157     KEY_HMAC_MD5
  145:  *		      future algorithms TBD and registered with IANA.
  146:  *  Returns
  147:  *	1 - The algorithm is available.
  148:  *	0 - The algorithm is not available.
  149:  */
  150: int
  151: dst_check_algorithm(const int alg)
  152: {
  153: 	return (dst_t_func[alg] != NULL);
  154: }
  155: 
  156: /* 
  157:  * dst_s_get_key_struct 
  158:  *	This function allocates key structure and fills in some of the 
  159:  *	fields of the structure. 
  160:  * Parameters: 
  161:  *	name:     the name of the key 
  162:  *	alg:      the algorithm number 
  163:  *	flags:    the dns flags of the key
  164:  *	protocol: the dns protocol of the key
  165:  *	bits:     the size of the key
  166:  * Returns:
  167:  *       NULL if error
  168:  *       valid pointer otherwise
  169:  */
  170: static DST_KEY *
  171: dst_s_get_key_struct(const char *name, const int alg, const u_int32_t flags,
  172: 		     const int protocol, const int bits)
  173: {
  174: 	DST_KEY *new_key = NULL; 
  175: 
  176: 	if (dst_check_algorithm(alg)) /* make sure alg is available */
  177: 		new_key = (DST_KEY *) malloc(sizeof(*new_key));
  178: 	if (new_key == NULL)
  179: 		return (NULL);
  180: 
  181: 	memset(new_key, 0, sizeof(*new_key));
  182: 	new_key->dk_key_name = strdup(name);
  183: 	new_key->dk_alg = alg;
  184: 	new_key->dk_flags = flags;
  185: 	new_key->dk_proto = protocol;
  186: 	new_key->dk_KEY_struct = NULL;
  187: 	new_key->dk_key_size = bits;
  188: 	new_key->dk_func = dst_t_func[alg];
  189: 	return (new_key);
  190: }
  191: 
  192: /*
  193:  *  dst_compare_keys
  194:  *	Compares two keys for equality.
  195:  *  Parameters
  196:  *	key1, key2      Two keys to be compared.
  197:  *  Returns
  198:  *	0	       The keys are equal.
  199:  *	non-zero	The keys are not equal.
  200:  */
  201: 
  202: int
  203: dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
  204: {
  205: 	if (key1 == key2)
  206: 		return (0);
  207: 	if (key1 == NULL || key2 == NULL)
  208: 		return (4);
  209: 	if (key1->dk_alg != key2->dk_alg)
  210: 		return (1);
  211: 	if (key1->dk_key_size != key2->dk_key_size)
  212: 		return (2);
  213: 	if (key1->dk_id != key2->dk_id)
  214: 		return (3);
  215: 	return (key1->dk_func->compare(key1, key2));
  216: }
  217: 
  218: 
  219: /*
  220:  * dst_sign_data
  221:  *	An incremental signing function.  Data is signed in steps.
  222:  *	First the context must be initialized (SIG_MODE_INIT).
  223:  *	Then data is hashed (SIG_MODE_UPDATE).  Finally the signature
  224:  *	itself is created (SIG_MODE_FINAL).  This function can be called
  225:  *	once with INIT, UPDATE and FINAL modes all set, or it can be
  226: 
  227:  *	called separately with a different mode set for each step.  The
  228:  *	UPDATE step can be repeated.
  229:  * Parameters
  230:  *	mode    A bit mask used to specify operation(s) to be performed.
  231:  *		  SIG_MODE_INIT	   1   Initialize digest
  232:  *		  SIG_MODE_UPDATE	 2   Add data to digest
  233:  *		  SIG_MODE_FINAL	  4   Generate signature
  234:  *					      from signature
  235:  *		  SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL
  236:  *	data    Data to be signed.
  237:  *	len     The length in bytes of data to be signed.
  238:  *	in_key  Contains a private key to sign with.
  239:  *		  KEY structures should be handled (created, converted,
  240:  *		  compared, stored, freed) by the DST.
  241:  *	signature
  242:  *	      The location to which the signature will be written.
  243:  *	sig_len Length of the signature field in bytes.
  244:  * Return
  245:  *	 0      Successful INIT or Update operation
  246:  *	>0      success FINAL (sign) operation
  247:  *	<0      failure
  248:  */
  249: 
  250: int
  251: dst_sign_data(const int mode, DST_KEY *in_key, void **context, 
  252: 	      const u_char *data, const unsigned len,
  253: 	      u_char *signature, const unsigned sig_len)
  254: {
  255: 	DUMP(data, mode, len, "dst_sign_data()");
  256: 
  257: 	if (mode & SIG_MODE_FINAL &&
  258: 	    (in_key->dk_KEY_struct == NULL || signature == NULL))
  259: 		return (MISSING_KEY_OR_SIGNATURE);
  260: 
  261: 	if (in_key->dk_func && in_key->dk_func->sign)
  262: 		return (in_key->dk_func->sign(mode, in_key, context, data, len,
  263: 					      signature, sig_len));
  264: 	return (UNKNOWN_KEYALG);
  265: }
  266: 
  267: 
  268: /*
  269:  *  dst_verify_data
  270:  *	An incremental verify function.  Data is verified in steps.
  271:  *	First the context must be initialized (SIG_MODE_INIT).
  272:  *	Then data is hashed (SIG_MODE_UPDATE).  Finally the signature
  273:  *	is verified (SIG_MODE_FINAL).  This function can be called
  274:  *	once with INIT, UPDATE and FINAL modes all set, or it can be
  275:  *	called separately with a different mode set for each step.  The
  276:  *	UPDATE step can be repeated.
  277:  *  Parameters
  278:  *	mode	Operations to perform this time.
  279:  *		      SIG_MODE_INIT       1   Initialize digest
  280:  *		      SIG_MODE_UPDATE     2   add data to digest
  281:  *		      SIG_MODE_FINAL      4   verify signature
  282:  *		      SIG_MODE_ALL
  283:  *			  (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL)
  284:  *	data	Data to pass through the hash function.
  285:  *	len	 Length of the data in bytes.
  286:  *	in_key      Key for verification.
  287:  *	signature   Location of signature.
  288:  *	sig_len     Length of the signature in bytes.
  289:  *  Returns
  290:  *	0	   Verify success
  291:  *	Non-Zero    Verify Failure
  292:  */
  293: 
  294: int
  295: dst_verify_data(const int mode, DST_KEY *in_key, void **context, 
  296: 		const u_char *data, const unsigned len,
  297: 		const u_char *signature, const unsigned sig_len)
  298: {
  299: 	DUMP(data, mode, len, "dst_verify_data()");
  300: 	if (mode & SIG_MODE_FINAL &&
  301: 	    (in_key->dk_KEY_struct == NULL || signature == NULL))
  302: 		return (MISSING_KEY_OR_SIGNATURE);
  303: 
  304: 	if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL)
  305: 		return (UNSUPPORTED_KEYALG);
  306: 	return (in_key->dk_func->verify(mode, in_key, context, data, len,
  307: 					signature, sig_len));
  308: }
  309: 
  310: 
  311: /*
  312:  *  dst_read_private_key
  313:  *	Access a private key.  First the list of private keys that have
  314:  *	already been read in is searched, then the key accessed on disk.
  315:  *	If the private key can be found, it is returned.  If the key cannot
  316:  *	be found, a null pointer is returned.  The options specify required
  317:  *	key characteristics.  If the private key requested does not have
  318:  *	these characteristics, it will not be read.
  319:  *  Parameters
  320:  *	in_keyname  The private key name.
  321:  *	in_id	    The id of the private key.
  322:  *	options     DST_FORCE_READ  Read from disk - don't use a previously
  323:  *				      read key.
  324:  *		  DST_CAN_SIGN    The key must be usable for signing.
  325:  *		  DST_NO_AUTHEN   The key must be usable for authentication.
  326:  *		  DST_STANDARD    Return any key 
  327:  *  Returns
  328:  *	NULL	If there is no key found in the current directory or
  329:  *		      this key has not been loaded before.
  330:  *	!NULL       Success - KEY structure returned.
  331:  */
  332: 
  333: DST_KEY *
  334: dst_read_key(const char *in_keyname, const unsigned in_id, 
  335: 	     const int in_alg, const int type)
  336: {
  337: 	char keyname[PATH_MAX];
  338: 	DST_KEY *dg_key = NULL, *pubkey = NULL;
  339: 
  340: 	if (!dst_check_algorithm(in_alg)) { /* make sure alg is available */
  341: 		EREPORT(("dst_read_private_key(): Algorithm %d not supported\n",
  342: 			 in_alg));
  343: 		return (NULL);
  344: 	}
  345: 	if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) 
  346: 		return (NULL);
  347: 	if (in_keyname == NULL) {
  348: 		EREPORT(("dst_read_private_key(): Null key name passed in\n"));
  349: 		return (NULL);
  350: 	} else
  351: 		strcpy(keyname, in_keyname);
  352: 
  353: 	/* before I read in the public key, check if it is allowed to sign */
  354: 	if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL)
  355: 		return (NULL);
  356: 
  357: 	if (type == DST_PUBLIC) 
  358: 		return pubkey; 
  359: 
  360: 	if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg,
  361: 					    pubkey->dk_flags, pubkey->dk_proto,
  362: 					    0)))
  363: 		return (dg_key);
  364: 	/* Fill in private key and some fields in the general key structure */
  365: 	if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id,
  366: 					pubkey->dk_alg) == 0)
  367: 		dg_key = dst_free_key(dg_key);
  368: 
  369: 	pubkey = dst_free_key(pubkey);
  370: 	return (dg_key);
  371: }
  372: 
  373: int 
  374: dst_write_key(const DST_KEY *key, const int type)
  375: {
  376: 	int pub = 0, priv = 0;
  377: 
  378: 	if (key == NULL) 
  379: 		return (0);
  380: 	if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */
  381: 		EREPORT(("dst_write_key(): Algorithm %d not supported\n", 
  382: 			 key->dk_alg));
  383: 		return (UNSUPPORTED_KEYALG);
  384: 	}
  385: 	if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0)
  386: 		return (0);
  387: 
  388: 	if (type & DST_PUBLIC) 
  389: 		if ((pub = dst_s_write_public_key(key)) < 0)
  390: 			return (pub);
  391: 	if (type & DST_PRIVATE)
  392: 		if ((priv = dst_s_write_private_key(key)) < 0)
  393: 			return (priv);
  394: 	return (priv+pub);
  395: }
  396: 
  397: /*
  398:  *  dst_write_private_key
  399:  *	Write a private key to disk.  The filename will be of the form:
  400:  *	K<key->dk_name>+<key->dk_alg>+<key->dk_id>.<private key suffix>.
  401:  *	If there is already a file with this name, an error is returned.
  402:  *
  403:  *  Parameters
  404:  *	key     A DST managed key structure that contains
  405:  *	      all information needed about a key.
  406:  *  Return
  407:  *	>= 0    Correct behavior.  Returns length of encoded key value
  408:  *		  written to disk.
  409:  *	<  0    error.
  410:  */
  411: 
  412: static int
  413: dst_s_write_private_key(const DST_KEY *key)
  414: {
  415: 	u_char encoded_block[RAW_KEY_SIZE];
  416: 	char file[PATH_MAX];
  417: 	unsigned len;
  418: 	FILE *fp;
  419: 
  420: 	/* First encode the key into the portable key format */
  421: 	if (key == NULL)
  422: 		return (-1);
  423: 	if (key->dk_KEY_struct == NULL)
  424: 		return (0);	/* null key has no private key */
  425: 
  426: 	if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) {
  427: 		EREPORT(("dst_write_private_key(): Unsupported operation %d\n",
  428: 			 key->dk_alg));
  429: 		return (-5);
  430: 	} else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block,
  431: 					     sizeof(encoded_block))) <= 0) {
  432: 		EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len));
  433: 		return (-8);
  434: 	}
  435: 	/* Now I can create the file I want to use */
  436: 	dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg,
  437: 			     PRIVATE_KEY, PATH_MAX);
  438: 
  439: 	/* Do not overwrite an existing file */
  440: 	if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) {
  441: 		int nn;
  442: 		if ((nn = fwrite(encoded_block, 1, len, fp)) != len) {
  443: 			EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n",
  444: 				 file, out_len, nn, errno));
  445: 			return (-5);
  446: 		}
  447: 		fclose(fp);
  448: 	} else {
  449: 		EREPORT(("dst_write_private_key(): Can not create file %s\n"
  450: 			 ,file));
  451: 		return (-6);
  452: 	}
  453: 	memset(encoded_block, 0, len);
  454: 	return (len);
  455: }
  456: 
  457: /*
  458: *
  459:  *  dst_read_public_key
  460:  *	Read a public key from disk and store in a DST key structure.
  461:  *  Parameters
  462:  *	in_name	 K<in_name><in_id>.<public key suffix> is the
  463:  *		      filename of the key file to be read.
  464:  *  Returns
  465:  *	NULL	    If the key does not exist or no name is supplied.
  466:  *	NON-NULL	Initialized key structure if the key exists.
  467:  */
  468: 
  469: static DST_KEY *
  470: dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
  471: {
  472: 	unsigned flags, len;
  473: 	int proto, alg, dlen;
  474: 	int c;
  475: 	char name[PATH_MAX], enckey[RAW_KEY_SIZE];
  476:         unsigned char *notspace;
  477: 	u_char deckey[RAW_KEY_SIZE];
  478: 	FILE *fp;
  479: 
  480: 	if (in_name == NULL) {
  481: 		EREPORT(("dst_read_public_key(): No key name given\n"));
  482: 		return (NULL);
  483: 	}
  484: 	if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY,
  485: 				 PATH_MAX) == -1) {
  486: 		EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n",
  487: 			 in_name, in_id, PUBLIC_KEY));
  488: 		return (NULL);
  489: 	}
  490: 	/*
  491: 	 * Open the file and read it's formatted contents up to key
  492: 	 * File format:
  493: 	 *    domain.name [ttl] [IN] KEY  <flags> <protocol> <algorithm> <key>
  494: 	 * flags, proto, alg stored as decimal (or hex numbers FIXME).
  495: 	 * (FIXME: handle parentheses for line continuation.)
  496: 	 */
  497: 	if ((fp = dst_s_fopen(name, "r", 0)) == NULL) {
  498: 		EREPORT(("dst_read_public_key(): Public Key not found %s\n",
  499: 			 name));
  500: 		return (NULL);
  501: 	}
  502: 	/* Skip domain name, which ends at first blank */
  503: 	while ((c = getc(fp)) != EOF)
  504: 		if (isspace(c))
  505: 			break;
  506: 	/* Skip blank to get to next field */
  507: 	while ((c = getc(fp)) != EOF)
  508: 		if (!isspace(c))
  509: 			break;
  510: 
  511: 	/* Skip optional TTL -- if initial digit, skip whole word. */
  512: 	if (isdigit(c)) {
  513: 		while ((c = getc(fp)) != EOF)
  514: 			if (isspace(c))
  515: 				break;
  516: 		while ((c = getc(fp)) != EOF)
  517: 			if (!isspace(c))
  518: 				break;
  519: 	}
  520: 	/* Skip optional "IN" */
  521: 	if (c == 'I' || c == 'i') {
  522: 		while ((c = getc(fp)) != EOF)
  523: 			if (isspace(c))
  524: 				break;
  525: 		while ((c = getc(fp)) != EOF)
  526: 			if (!isspace(c))
  527: 				break;
  528: 	}
  529: 	/* Locate and skip "KEY" */
  530: 	if (c != 'K' && c != 'k') {
  531: 		EREPORT(("\"KEY\" doesn't appear in file: %s", name));
  532: 		return NULL;
  533: 	}
  534: 	while ((c = getc(fp)) != EOF)
  535: 		if (isspace(c))
  536: 			break;
  537: 	while ((c = getc(fp)) != EOF)
  538: 		if (!isspace(c))
  539: 			break;
  540: 	ungetc(c, fp);		/* return the character to the input field */
  541: 	/* Handle hex!! FIXME.  */
  542: 
  543: 	if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) {
  544: 		EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n"
  545: 			 ,name));
  546: 		return (NULL);
  547: 	}
  548: 	/* read in the key string */
  549: 	if ((fgets(enckey, sizeof(enckey), fp) == NULL) &&
  550: 	    (ferror(fp) != 0)) {
  551: 		EREPORT(("dst_read_public_kety(): Error reading key\n"));
  552: 		return (NULL);
  553: 	}
  554: 
  555: 	/* If we aren't at end-of-file, something is wrong.  */
  556: 	while ((c = getc(fp)) != EOF)
  557: 		if (!isspace(c))
  558: 			break;
  559: 	if (!feof(fp)) {
  560: 		EREPORT(("Key too long in file: %s", name));
  561: 		return NULL;
  562: 	}
  563: 	fclose(fp);
  564: 
  565: 	if ((len = strlen(enckey)) <= 0)
  566: 		return (NULL);
  567: 
  568: 	/* discard \n */
  569: 	enckey[--len] = '\0';
  570: 
  571: 	/* remove leading spaces */
  572: 	for (notspace = (unsigned char *)enckey; isspace(*notspace); len--)
  573: 		notspace++;
  574: 
  575: 	dlen = b64_pton((char *)notspace, deckey, sizeof(deckey));
  576: 	if (dlen < 0) {
  577: 		EREPORT(("dst_read_public_key: bad return from b64_pton = %d",
  578: 			 dlen));
  579: 		return (NULL);
  580: 	}
  581: 	/* store key and info in a key structure that is returned */
  582: /*	return dst_store_public_key(in_name, alg, proto, 666, flags, deckey,
  583: 				    dlen);*/
  584: 	return dst_buffer_to_key(in_name, alg,
  585: 				 flags, proto, deckey, (unsigned)dlen);
  586: }
  587: 
  588: 
  589: /*
  590:  *  dst_write_public_key
  591:  *	Write a key to disk in DNS format.
  592:  *  Parameters
  593:  *	key     Pointer to a DST key structure.
  594:  *  Returns
  595:  *	0       Failure
  596:  *	1       Success
  597:  */
  598: 
  599: static int
  600: dst_s_write_public_key(const DST_KEY *key)
  601: {
  602: 	FILE *fp;
  603: 	char filename[PATH_MAX];
  604: 	u_char out_key[RAW_KEY_SIZE];
  605: 	char enc_key[RAW_KEY_SIZE];
  606: 	int len = 0;
  607: 
  608: 	memset(out_key, 0, sizeof(out_key));
  609: 	if (key == NULL) {
  610: 		EREPORT(("dst_write_public_key(): No key specified \n"));
  611: 		return (0);
  612: 	} else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0)
  613: 		return (0);
  614: 
  615: 	/* Make the filename */
  616: 	if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id,
  617: 				 key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) {
  618: 		EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n",
  619: 			 key->dk_key_name, key->dk_id, PUBLIC_KEY));
  620: 		return (0);
  621: 	}
  622: 	/* create public key file */
  623: 	if ((fp = dst_s_fopen(filename, "w+", 0644)) == NULL) {
  624: 		EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n",
  625: 			 filename, errno));
  626: 		return (0);
  627: 	}
  628: 	/*write out key first base64 the key data */
  629: 	if (key->dk_flags & DST_EXTEND_FLAG)
  630: 		b64_ntop(&out_key[6],
  631: 			 (unsigned)(len - 6), enc_key, sizeof(enc_key));
  632: 	else
  633: 		b64_ntop(&out_key[4],
  634: 			 (unsigned)(len - 4), enc_key, sizeof(enc_key));
  635: 	fprintf(fp, "%s IN KEY %d %d %d %s\n",
  636: 		key->dk_key_name,
  637: 		key->dk_flags, key->dk_proto, key->dk_alg, enc_key);
  638: 	fclose(fp);
  639: 	return (1);
  640: }
  641: 
  642: 
  643: /*
  644:  *  dst_dnskey_to_public_key
  645:  *	This function converts the contents of a DNS KEY RR into a DST
  646:  *	key structure.
  647:  *  Parameters
  648:  *	len	 Length of the RDATA of the KEY RR RDATA
  649:  *	rdata	 A pointer to the the KEY RR RDATA.
  650:  *	in_name     Key name to be stored in key structure.
  651:  *  Returns
  652:  *	NULL	    Failure
  653:  *	NON-NULL	Success.  Pointer to key structure.
  654:  *			Caller's responsibility to free() it.
  655:  */
  656: 
  657: DST_KEY *
  658: dst_dnskey_to_key(const char *in_name,
  659: 		  const u_char *rdata, const unsigned len)
  660: {
  661: 	DST_KEY *key_st;
  662: 	int alg ;
  663: 	int start = DST_KEY_START;
  664: 
  665: 	if (rdata == NULL || len <= DST_KEY_ALG) /* no data */
  666: 		return (NULL);
  667: 	alg = (u_int8_t) rdata[DST_KEY_ALG];
  668: 	if (!dst_check_algorithm(alg)) { /* make sure alg is available */
  669: 		EREPORT(("dst_dnskey_to_key(): Algorithm %d not supported\n",
  670: 			 alg));
  671: 		return (NULL);
  672: 	}
  673: 	if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL)
  674: 		return (NULL);
  675: 
  676: 	if (in_name == NULL)
  677: 		return (NULL);
  678: 	key_st->dk_flags = dst_s_get_int16(rdata);
  679: 	key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT];
  680: 	if (key_st->dk_flags & DST_EXTEND_FLAG) {
  681: 		u_int32_t ext_flags;
  682: 		ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]);
  683: 		key_st->dk_flags = key_st->dk_flags | (ext_flags << 16);
  684: 		start += 2;
  685: 	}
  686: 	/*
  687: 	 * now point to the beginning of the data representing the encoding
  688: 	 * of the key
  689: 	 */
  690: 	if (key_st->dk_func && key_st->dk_func->from_dns_key) {
  691: 		if (key_st->dk_func->from_dns_key(key_st, &rdata[start],
  692: 						  len - start) > 0)
  693: 			return (key_st);
  694: 	} else
  695: 		EREPORT(("dst_dnskey_to_public_key(): unsupported alg %d\n",
  696: 			 alg));
  697: 
  698: 	SAFE_FREE(key_st);
  699: 	return (key_st);
  700: }
  701: 
  702: 
  703: /*
  704:  *  dst_public_key_to_dnskey
  705:  *	Function to encode a public key into DNS KEY wire format 
  706:  *  Parameters
  707:  *	key	     Key structure to encode.
  708:  *	out_storage     Location to write the encoded key to.
  709:  *	out_len	 Size of the output array.
  710:  *  Returns
  711:  *	<0      Failure
  712:  *	>=0     Number of bytes written to out_storage
  713:  */
  714: 
  715: int
  716: dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage,
  717: 			 const unsigned out_len)
  718: {
  719: 	u_int16_t val;
  720: 	int loc = 0;
  721: 	int enc_len = 0;
  722: 	if (key == NULL)
  723: 		return (-1);
  724: 
  725: 	if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */
  726: 		EREPORT(("dst_key_to_dnskey(): Algorithm %d not supported\n",
  727: 			 key->dk_alg));
  728: 		return (UNSUPPORTED_KEYALG);
  729: 	}
  730: 	memset(out_storage, 0, out_len);
  731: 	val = (u_int16_t)(key->dk_flags & 0xffff);
  732: 	out_storage[0] = (val >> 8) & 0xff;
  733: 	out_storage[1] = val        & 0xff;
  734: 	loc += 2;
  735: 
  736: 	out_storage[loc++] = (u_char) key->dk_proto;
  737: 	out_storage[loc++] = (u_char) key->dk_alg;
  738: 
  739: 	if (key->dk_flags > 0xffff) {	/* Extended flags */
  740: 		val = (u_int16_t)((key->dk_flags >> 16) & 0xffff);
  741: 		out_storage[loc]   = (val >> 8) & 0xff;
  742: 		out_storage[loc+1] = val        & 0xff;
  743: 		loc += 2;
  744: 	}
  745: 	if (key->dk_KEY_struct == NULL)
  746: 		return (loc);
  747: 	if (key->dk_func && key->dk_func->to_dns_key) {
  748: 		enc_len = key->dk_func->to_dns_key(key,
  749: 						 (u_char *) &out_storage[loc],
  750: 						   out_len - loc);
  751: 		if (enc_len > 0)
  752: 			return (enc_len + loc);
  753: 		else
  754: 			return (-1);
  755: 	} else
  756: 		EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n",
  757: 			 key->dk_alg));
  758: 	return (-1);
  759: }
  760: 
  761: 
  762: /*
  763:  *  dst_buffer_to_key
  764:  *	Function to encode a string of raw data into a DST key
  765:  *  Parameters
  766:  *	alg		The algorithm (HMAC only)
  767:  *	key		A pointer to the data
  768:  *	keylen		The length of the data
  769:  *  Returns
  770:  *	NULL	    an error occurred
  771:  *	NON-NULL	the DST key
  772:  */
  773: DST_KEY *
  774: dst_buffer_to_key(const char *key_name,		/* name of the key */
  775: 		  const int alg,		/* algorithm */
  776: 		  const unsigned flags,		/* dns flags */
  777: 		  const int protocol,		/* dns protocol */
  778: 		  const u_char *key_buf,	/* key in dns wire fmt */
  779: 		  const unsigned key_len)		/* size of key */
  780: {
  781: 	
  782: 	DST_KEY *dkey = NULL; 
  783: 
  784: 	if (!dst_check_algorithm(alg)) { /* make sure alg is available */
  785: 		EREPORT(("dst_buffer_to_key(): Algorithm %d not supported\n", alg));
  786: 		return (NULL);
  787: 	}
  788: 
  789: 	dkey = dst_s_get_key_struct(key_name, alg, flags,  protocol, -1);
  790: 
  791: 	if (dkey == NULL)
  792: 		return (NULL);
  793: 	if (dkey->dk_func != NULL &&
  794: 	    dkey->dk_func->from_dns_key != NULL) {
  795: 		if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) {
  796: 			EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n"));
  797: 			return (dst_free_key(dkey));
  798: 		}
  799: 		return (dkey);
  800: 	}
  801: 	return (NULL);
  802: }
  803: 
  804: int 
  805: dst_key_to_buffer(DST_KEY *key, u_char *out_buff, unsigned buf_len)
  806: {
  807: 	int len;
  808:   /* this function will extract the secret of HMAC into a buffer */
  809: 	if(key == NULL) 
  810: 		return (0);
  811: 	if(key->dk_func != NULL && key->dk_func != NULL) {
  812: 		len = key->dk_func->to_dns_key(key, out_buff, buf_len);
  813: 		if (len < 0)
  814: 			return (0);
  815: 		return (len);
  816: 	}
  817: 	return (0);
  818: }
  819: 
  820: 
  821: /*
  822:  * dst_s_read_private_key_file
  823:  *     Function reads in private key from a file.
  824:  *     Fills out the KEY structure.
  825:  * Parameters
  826:  *     name    Name of the key to be read.
  827:  *     pk_key  Structure that the key is returned in.
  828:  *     in_id   Key identifier (tag)
  829:  * Return
  830:  *     1 if everything works
  831:  *     0 if there is any problem
  832:  */
  833: 
  834: static int
  835: dst_s_read_private_key_file(char *name, DST_KEY *pk_key, unsigned in_id,
  836: 			    int in_alg)
  837: {
  838: 	int cnt, alg, len, major, minor, file_major, file_minor;
  839: 	int id;
  840: 	char filename[PATH_MAX];
  841: 	u_char in_buff[RAW_KEY_SIZE];
  842: 	char *p;
  843: 	FILE *fp;
  844: 
  845: 	if (name == NULL || pk_key == NULL) {
  846: 		EREPORT(("dst_read_private_key_file(): No key name given\n"));
  847: 		return (0);
  848: 	}
  849: 	/* Make the filename */
  850: 	if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY,
  851: 				 PATH_MAX) == -1) {
  852: 		EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n",
  853: 			 name, in_id, PRIVATE_KEY));
  854: 		return (0);
  855: 	}
  856: 	/* first check if we can find the key file */
  857: 	if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) {
  858: 		EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n",
  859: 			 filename, dst_path[0] ? dst_path :
  860: 			 (char *) getcwd(NULL, PATH_MAX - 1)));
  861: 		return (0);
  862: 	}
  863: 	/* now read the header info from the file */
  864: 	if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) {
  865: 		fclose(fp);
  866: 		EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n",
  867: 			 filename));
  868: 		return (0);
  869: 	}
  870: 	/* decrypt key */
  871: 	fclose(fp);
  872: 	if (memcmp(in_buff, "Private-key-format: v", 20) != 0)
  873: 		goto fail;
  874: 	len = cnt;
  875: 	p = (char *)in_buff;
  876: 
  877: 	if (!dst_s_verify_str((const char **) &p, "Private-key-format: v")) {
  878: 		EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name));
  879: 		goto fail;
  880: 	}
  881: 	/* read in file format */
  882: 	sscanf(p, "%d.%d", &file_major, &file_minor);
  883: 	sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor);
  884: 	if (file_major < 1) {
  885: 		EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n",
  886: 			 file_major, file_minor, name));
  887: 		goto fail;
  888: 	} else if (file_major > major || file_minor > minor)
  889: 		EREPORT((
  890: 				"dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n",
  891: 				name, file_major, file_minor));
  892: 
  893: 	while (*p++ != '\n') ;	/* skip to end of line */
  894: 
  895: 	if (!dst_s_verify_str((const char **) &p, "Algorithm: "))
  896: 		goto fail;
  897: 
  898: 	if (sscanf(p, "%d", &alg) != 1)
  899: 		goto fail;
  900: 	while (*p++ != '\n') ;	/* skip to end of line */
  901: 
  902: 	if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name))
  903: 		SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name));
  904: 	pk_key->dk_key_name = (char *) strdup(name);
  905: 
  906: 	/* allocate and fill in key structure */
  907: 	if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL)
  908: 		goto fail;
  909: 
  910: 	id = pk_key->dk_func->from_file_fmt(pk_key, (char *)p,
  911: 					    (unsigned)(&in_buff[len] - (u_char *)p));
  912: 	if (id < 0)
  913: 		goto fail;
  914: 
  915: 	/* Make sure the actual key tag matches the input tag used in the filename
  916: 	 */
  917: 	if (id != in_id) {
  918: 		EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id));
  919: 		goto fail;
  920: 	}
  921: 	pk_key->dk_id = (u_int16_t) id;
  922: 	pk_key->dk_alg = alg;
  923: 	memset(in_buff, 0, (unsigned)cnt);
  924: 	return (1);
  925: 
  926:  fail:
  927: 	memset(in_buff, 0, (unsigned)cnt);
  928: 	return (0);
  929: }
  930: 
  931: 
  932: /*
  933:  *  dst_generate_key
  934:  *	Generate and store a public/private keypair.
  935:  *	Keys will be stored in formatted files.
  936:  *  Parameters
  937:  *	name    Name of the new key.  Used to create key files
  938:  *		  K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private.
  939:  *	bits    Size of the new key in bits.
  940:  *	exp     What exponent to use:
  941:  *		  0	   use exponent 3
  942:  *		  non-zero    use Fermant4
  943:  *	flags   The default value of the DNS Key flags.
  944:  *		  The DNS Key RR Flag field is defined in RFC 2065,
  945:  *		  section 3.3.  The field has 16 bits.
  946:  *	protocol
  947:  *	      Default value of the DNS Key protocol field.
  948:  *		  The DNS Key protocol field is defined in RFC 2065,
  949:  *		  section 3.4.  The field has 8 bits.
  950:  *	alg     What algorithm to use.  Currently defined:
  951:  *		  KEY_RSA       1
  952:  *		  KEY_DSA       3
  953:  *		  KEY_HMAC    157
  954:  *	out_id The key tag is returned.
  955:  *
  956:  *  Return
  957:  *	NULL		Failure
  958:  *	non-NULL 	the generated key pair
  959:  *			Caller frees the result, and its dk_name pointer.
  960:  */
  961: DST_KEY *
  962: dst_generate_key(const char *name, const int bits, const int exp,
  963: 		 const unsigned flags, const int protocol, const int alg)
  964: {
  965: 	DST_KEY *new_key = NULL;
  966: 	int res;
  967: 	if (name == NULL)
  968: 		return (NULL);
  969: 
  970: 	if (!dst_check_algorithm(alg)) { /* make sure alg is available */
  971: 		EREPORT(("dst_generate_key(): Algorithm %d not supported\n", alg));
  972: 		return (NULL);
  973: 	}
  974: 
  975: 	new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits);
  976: 	if (new_key == NULL)
  977: 		return (NULL);
  978: 	if (bits == 0) /* null key we are done */
  979: 		return (new_key);
  980: 	if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) {
  981: 		EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n",
  982: 			 alg));
  983: 		return (dst_free_key(new_key));
  984: 	}
  985: 	if ((res = new_key->dk_func->generate(new_key, exp)) <= 0) {
  986: 		EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n",
  987: 			 new_key->dk_key_name, new_key->dk_alg,
  988: 			 new_key->dk_key_size, exp));
  989: 		return (dst_free_key(new_key));
  990: 	}
  991: 	return (new_key);
  992: }
  993: 
  994: 
  995: /*
  996:  *  dst_free_key
  997:  *	Release all data structures pointed to by a key structure.
  998:  *  Parameters
  999:  *	f_key   Key structure to be freed.
 1000:  */
 1001: 
 1002: DST_KEY *
 1003: dst_free_key(DST_KEY *f_key)
 1004: {
 1005: 
 1006: 	if (f_key == NULL)
 1007: 		return (f_key);
 1008: 	if (f_key->dk_func && f_key->dk_func->destroy)
 1009: 		f_key->dk_KEY_struct =
 1010: 			f_key->dk_func->destroy(f_key->dk_KEY_struct);
 1011: 	else {
 1012: 		EREPORT(("dst_free_key(): Unknown key alg %d\n",
 1013: 			 f_key->dk_alg));
 1014: 		free(f_key->dk_KEY_struct);	/* SHOULD NOT happen */
 1015: 	}
 1016: 	if (f_key->dk_KEY_struct) {
 1017: 		free(f_key->dk_KEY_struct);
 1018: 		f_key->dk_KEY_struct = NULL;
 1019: 	}
 1020: 	if (f_key->dk_key_name)
 1021: 		SAFE_FREE(f_key->dk_key_name);
 1022: 	SAFE_FREE(f_key);
 1023: 	return (NULL);
 1024: }
 1025: 
 1026: /*
 1027:  * dst_sig_size
 1028:  *	Return the maximum size of signature from the key specified in bytes
 1029:  * Parameters
 1030:  *      key 
 1031:  * Returns
 1032:  *     bytes
 1033:  */
 1034: int
 1035: dst_sig_size(DST_KEY *key) {
 1036: 	switch (key->dk_alg) {
 1037: 	    case KEY_HMAC_MD5:
 1038: 		return (16);
 1039: 	    case KEY_HMAC_SHA1:
 1040: 		return (20);
 1041: 	    case KEY_RSA:
 1042: 		return (key->dk_key_size + 7) / 8;
 1043: 	    case KEY_DSA:
 1044: 		return (40);
 1045: 	    default:
 1046: 		EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg));
 1047: 		return -1;
 1048: 	}
 1049: }
 1050: 
 1051: /* 
 1052:  * dst_random 
 1053:  *  function that multiplexes number of random number generators
 1054:  * Parameters  
 1055:  *   mode: select the random number generator
 1056:  *   wanted is how many bytes of random data are requested 
 1057:  *   outran is a buffer of size at least wanted for the output data
 1058:  *
 1059:  * Returns
 1060:  *    number of bytes written to outran
 1061:  */
 1062: int 
 1063: dst_random(const int mode, unsigned wanted, u_char *outran)
 1064: {
 1065: 	u_int32_t *buff = NULL, *bp = NULL;
 1066: 	int i;
 1067: 	if (wanted <= 0 || outran == NULL) 
 1068: 		return (0);
 1069: 
 1070: 	switch (mode) {
 1071: 	case DST_RAND_SEMI: 
 1072: 		bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t));
 1073: 		for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) {
 1074: 			*bp = dst_s_quick_random(i);
 1075: 		}
 1076: 		memcpy(outran, buff, (unsigned)wanted);
 1077: 		SAFE_FREE(buff);
 1078: 		return (wanted);
 1079: 	case DST_RAND_STD:
 1080: 		return (dst_s_semi_random(outran, wanted));
 1081: 	case DST_RAND_KEY:
 1082: 		return (dst_s_random(outran, wanted));
 1083: 	case DST_RAND_DSS:
 1084: 	default:
 1085: 		/* need error case here XXX OG */
 1086: 		return (0);
 1087: 	}
 1088: }
 1089: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>