2N/A * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. 2N/A * Permission to use, copy modify, and distribute this software for any 2N/A * purpose with or without fee is hereby granted, provided that the above 2N/A * copyright notice and this permission notice appear in all copies. 2N/A * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS 2N/A * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 2N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 2N/A * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, 2N/A * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 2N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 2N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 2N/A * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. 2N/A * This file contains the interface between the DST API and the crypto API. 2N/A * This is the only file that needs to be changed if the crypto system is 2N/A * changed. Exported functions are: 2N/A * void dst_init() Initialize the toolkit 2N/A * int dst_check_algorithm() Function to determines if alg is suppored. 2N/A * int dst_compare_keys() Function to compare two keys for equality. 2N/A * int dst_sign_data() Incremental signing routine. 2N/A * int dst_verify_data() Incremental verify routine. 2N/A * int dst_generate_key() Function to generate new KEY 2N/A * void dst_write_key() Function to write out a key. 2N/A * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST 2N/A * int dst_key_to_dnskey() Function to return a public key in DNS 2N/A * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY 2N/A * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer 2N/A * void dst_free_key() Releases all memory referenced by key structure 2N/A/* static variables */ 2N/A/* internal I/O functions */ 2N/A/* internal function to set up data structure */ 2N/A * This function initializes the Digital Signature Toolkit. 2N/A * Right now, it just checks the DSTKEYPATH environment variable. 2N/A EREPORT((
"%s is longer than %d characters, ignoring\n",
2N/A /* first one is selected */ 2N/A * dst_check_algorithm 2N/A * This function determines if the crypto system for the specified 2N/A * algorithm is present. 2N/A * future algorithms TBD and registered with IANA. 2N/A * 1 - The algorithm is available. 2N/A * 0 - The algorithm is not available. 2N/A * dst_s_get_key_struct 2N/A * This function allocates key structure and fills in some of the 2N/A * fields of the structure. 2N/A * name: the name of the key 2N/A * alg: the algorithm number 2N/A * flags: the dns flags of the key 2N/A * protocol: the dns protocol of the key 2N/A * bits: the size of the key 2N/A * valid pointer otherwise 2N/A * Compares two keys for equality. 2N/A * key1, key2 Two keys to be compared. 2N/A * 0 The keys are equal. 2N/A * non-zero The keys are not equal. 2N/A * An incremental signing function. Data is signed in steps. 2N/A * First the context must be initialized (SIG_MODE_INIT). 2N/A * Then data is hashed (SIG_MODE_UPDATE). Finally the signature 2N/A * itself is created (SIG_MODE_FINAL). This function can be called 2N/A * once with INIT, UPDATE and FINAL modes all set, or it can be 2N/A * called separately with a different mode set for each step. The 2N/A * UPDATE step can be repeated. 2N/A * mode A bit mask used to specify operation(s) to be performed. 2N/A * SIG_MODE_INIT 1 Initialize digest 2N/A * SIG_MODE_UPDATE 2 Add data to digest 2N/A * SIG_MODE_FINAL 4 Generate signature 2N/A * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL 2N/A * data Data to be signed. 2N/A * len The length in bytes of data to be signed. 2N/A * in_key Contains a private key to sign with. 2N/A * KEY structures should be handled (created, converted, 2N/A * compared, stored, freed) by the DST. 2N/A * The location to which the signature will be written. 2N/A * sig_len Length of the signature field in bytes. 2N/A * 0 Successfull INIT or Update operation 2N/A * >0 success FINAL (sign) operation 2N/A * An incremental verify function. Data is verified in steps. 2N/A * First the context must be initialized (SIG_MODE_INIT). 2N/A * Then data is hashed (SIG_MODE_UPDATE). Finally the signature 2N/A * is verified (SIG_MODE_FINAL). This function can be called 2N/A * once with INIT, UPDATE and FINAL modes all set, or it can be 2N/A * called separately with a different mode set for each step. The 2N/A * UPDATE step can be repeated. 2N/A * mode Operations to perform this time. 2N/A * SIG_MODE_INIT 1 Initialize digest 2N/A * SIG_MODE_UPDATE 2 add data to digest 2N/A * SIG_MODE_FINAL 4 verify signature 2N/A * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) 2N/A * data Data to pass through the hash function. 2N/A * len Length of the data in bytes. 2N/A * in_key Key for verification. 2N/A * signature Location of signature. 2N/A * sig_len Length of the signature in bytes. 2N/A * Non-Zero Verify Failure 2N/A * dst_read_private_key 2N/A * Access a private key. First the list of private keys that have 2N/A * already been read in is searched, then the key accessed on disk. 2N/A * If the private key can be found, it is returned. If the key cannot 2N/A * be found, a null pointer is returned. The options specify required 2N/A * key characteristics. If the private key requested does not have 2N/A * these characteristics, it will not be read. 2N/A * in_keyname The private key name. 2N/A * in_id The id of the private key. 2N/A * options DST_FORCE_READ Read from disk - don't use a previously 2N/A * DST_CAN_SIGN The key must be useable for signing. 2N/A * DST_NO_AUTHEN The key must be useable for authentication. 2N/A * DST_STANDARD Return any key 2N/A * NULL If there is no key found in the current directory or 2N/A * this key has not been loaded before. 2N/A * !NULL Success - KEY structure returned. 2N/A EREPORT((
"dst_read_private_key(): Algorithm %d not suppored\n",
2N/A EREPORT((
"dst_read_private_key(): Null key name passed in\n"));
2N/A EREPORT((
"dst_read_private_key(): keyname too big\n"));
2N/A /* before I read in the public key, check if it is allowed to sign */ 2N/A /* Fill in private key and some fields in the general key structure */ 2N/A EREPORT((
"dst_write_key(): Algorithm %d not suppored\n",
2N/A * dst_write_private_key 2N/A * Write a private key to disk. The filename will be of the form: 2N/A * K<key->dk_name>+<key->dk_alg+><key-d>k_id.><private key suffix>. 2N/A * If there is already a file with this name, an error is returned. 2N/A * key A DST managed key structure that contains 2N/A * all information needed about a key. 2N/A * >= 0 Correct behavior. Returns length of encoded key value 2N/A /* First encode the key into the portable key format */ 2N/A return (0);
/*%< null key has no private key */ 2N/A EREPORT((
"dst_write_private_key(): Unsupported operation %d\n",
2N/A EREPORT((
"dst_write_private_key(): Failed encoding private RSA bsafe key %d\n",
len));
2N/A /* Now I can create the file I want to use */ 2N/A /* Do not overwrite an existing file */ 2N/A EREPORT((
"dst_write_private_key(): Write failure on %s %d != %d errno=%d\n",
2N/A EREPORT((
"dst_write_private_key(): Can not create file %s\n" 2N/A * dst_read_public_key 2N/A * Read a public key from disk and store in a DST key structure. 2N/A * in_name K<in_name><in_id>.<public key suffix> is the 2N/A * filename of the key file to be read. 2N/A * NULL If the key does not exist or no name is supplied. 2N/A * NON-NULL Initialized key structure if the key exists. 2N/A EREPORT((
"dst_read_public_key(): No key name given\n"));
2N/A EREPORT((
"dst_read_public_key(): Cannot make filename from %s, %d, and %s\n",
2N/A * Open the file and read it's formatted contents up to key 2N/A * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key> 2N/A * flags, proto, alg stored as decimal (or hex numbers FIXME). 2N/A * (FIXME: handle parentheses for line continuation.) 2N/A EREPORT((
"dst_read_public_key(): Public Key not found %s\n",
2N/A /* Skip domain name, which ends at first blank */ 2N/A /* Skip blank to get to next field */ 2N/A /* Skip optional TTL -- if initial digit, skip whole word. */ 2N/A /* Skip optional "IN" */ 2N/A if (c ==
'I' || c ==
'i') {
2N/A /* Locate and skip "KEY" */ 2N/A if (c !=
'K' && c !=
'k') {
2N/A ungetc(c,
fp);
/*%< return the charcter to the input field */ 2N/A /* Handle hex!! FIXME. */ 2N/A /* read in the key string */ 2N/A /* If we aren't at end-of-file, something is wrong. */ 2N/A /* remove leading spaces */ 2N/A EREPORT((
"dst_read_public_key: bad return from b64_pton = %d",
2N/A /* store key and info in a key structure that is returned */ 2N/A/* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, 2N/A * dst_write_public_key 2N/A * Write a key to disk in DNS format. 2N/A * key Pointer to a DST key structure. 2N/A EREPORT((
"dst_write_public_key(): No key specified \n"));
2N/A /* Make the filename */ 2N/A EREPORT((
"dst_write_public_key(): Cannot make filename from %s, %d, and %s\n",
2N/A /* XXX in general this should be a check for symmetric keys */ 2N/A /* create public key file */ 2N/A EREPORT((
"DST_write_public_key: open of file:%s failed (errno=%d)\n",
2N/A /*write out key first base64 the key data */ 2N/A * dst_dnskey_to_public_key 2N/A * This function converts the contents of a DNS KEY RR into a DST 2N/A * len Length of the RDATA of the KEY RR RDATA 2N/A * rdata A pointer to the the KEY RR RDATA. 2N/A * in_name Key name to be stored in key structure. 2N/A * NON-NULL Success. Pointer to key structure. 2N/A * Caller's responsibility to free() it. 2N/A EREPORT((
"dst_dnskey_to_key(): Algorithm %d not suppored\n",
2N/A * now point to the begining of the data representing the encoding 2N/A EREPORT((
"dst_dnskey_to_public_key(): unsuppored alg %d\n",
2N/A * dst_public_key_to_dnskey 2N/A * Function to encode a public key into DNS KEY wire format 2N/A * key Key structure to encode. 2N/A * out_storage Location to write the encoded key to. 2N/A * out_len Size of the output array. 2N/A * >=0 Number of bytes written to out_storage 2N/A EREPORT((
"dst_key_to_dnskey(): Algorithm %d not suppored\n",
2N/A EREPORT((
"dst_key_to_dnskey(): Unsupported ALG %d\n",
2N/A * Function to encode a string of raw data into a DST key 2N/A * alg The algorithm (HMAC only) 2N/A * key A pointer to the data 2N/A * keylen The length of the data 2N/A * NULL an error occurred 2N/A * NON-NULL the DST key 2N/A const int alg,
/*!< algorithm */ 2N/A EREPORT((
"dst_buffer_to_key(): Algorithm %d not suppored\n",
alg));
2N/A EREPORT((
"dst_buffer_to_key(): dst_buffer_to_hmac failed\n"));
2N/A /* this function will extrac the secret of HMAC into a buffer */ 2N/A * dst_s_read_private_key_file 2N/A * Function reads in private key from a file. 2N/A * Fills out the KEY structure. 2N/A * name Name of the key to be read. 2N/A * pk_key Structure that the key is returned in. 2N/A * in_id Key identifier (tag) 2N/A * 1 if everthing works 2N/A * 0 if there is any problem 2N/A EREPORT((
"dst_read_private_key_file(): No key name given\n"));
2N/A /* Make the filename */ 2N/A EREPORT((
"dst_read_private_key(): Cannot make filename from %s, %d, and %s\n",
2N/A /* first check if we can find the key file */ 2N/A EREPORT((
"dst_s_read_private_key_file: Could not open file %s in directory %s\n",
2N/A /* now read the header info from the file */ 2N/A EREPORT((
"dst_s_read_private_key_file: error reading file %s (empty file)\n",
2N/A "Private-key-format: v")) {
2N/A /* read in file format */ 2N/A EREPORT((
"dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n",
2N/A "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n",
2N/A while (*p++ !=
'\n') ;
/*%< skip to end of line */ 2N/A while (*p++ !=
'\n') ;
/*%< skip to end of line */ 2N/A /* allocate and fill in key structure */ 2N/A /* Make sure the actual key tag matches the input tag used in the filename 2N/A EREPORT((
"dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n",
id,
in_id));
2N/A * Keys will be stored in formatted files. 2N/A *\par name Name of the new key. Used to create key files 2N/A *\li K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private. 2N/A *\par bits Size of the new key in bits. 2N/A *\par exp What exponent to use: 2N/A *\li 0 use exponent 3 2N/A *\li non-zero use Fermant4 2N/A *\par flags The default value of the DNS Key flags. 2N/A *\li The DNS Key RR Flag field is defined in RFC2065, 2N/A * section 3.3. The field has 16 bits. 2N/A *\li Default value of the DNS Key protocol field. 2N/A *\li The DNS Key protocol field is defined in RFC2065, 2N/A * section 3.4. The field has 8 bits. 2N/A *\par alg What algorithm to use. Currently defined: 2N/A *\par out_id The key tag is returned. 2N/A *\li non-NULL the generated key pair 2N/A * Caller frees the result, and its dk_name pointer. 2N/A EREPORT((
"dst_generate_key(): Algorithm %d not suppored\n",
alg));
2N/A if (
bits == 0)
/*%< null key we are done */ 2N/A EREPORT((
"dst_generate_key_pair():Unsupported algorithm %d\n",
2N/A EREPORT((
"dst_generate_key_pair(): Key generation failure %s %d %d %d\n",
2N/A * Release all data structures pointed to by a key structure. 2N/A *\li f_key Key structure to be freed. 2N/A * Return the maximim size of signature from the key specified in bytes