17c478bd9Sstevel@tonic-gate #ifndef LINT 2*9525b14bSRao Shoaib static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/dst_api.c,v 1.17 2007/09/24 17:18:25 each Exp $"; 37c478bd9Sstevel@tonic-gate #endif 47c478bd9Sstevel@tonic-gate 57c478bd9Sstevel@tonic-gate /* 67c478bd9Sstevel@tonic-gate * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * Permission to use, copy modify, and distribute this software for any 97c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 107c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS 137c478bd9Sstevel@tonic-gate * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 147c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 157c478bd9Sstevel@tonic-gate * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, 167c478bd9Sstevel@tonic-gate * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 177c478bd9Sstevel@tonic-gate * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 187c478bd9Sstevel@tonic-gate * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 197c478bd9Sstevel@tonic-gate * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * This file contains the interface between the DST API and the crypto API. 237c478bd9Sstevel@tonic-gate * This is the only file that needs to be changed if the crypto system is 247c478bd9Sstevel@tonic-gate * changed. Exported functions are: 257c478bd9Sstevel@tonic-gate * void dst_init() Initialize the toolkit 267c478bd9Sstevel@tonic-gate * int dst_check_algorithm() Function to determines if alg is suppored. 277c478bd9Sstevel@tonic-gate * int dst_compare_keys() Function to compare two keys for equality. 287c478bd9Sstevel@tonic-gate * int dst_sign_data() Incremental signing routine. 297c478bd9Sstevel@tonic-gate * int dst_verify_data() Incremental verify routine. 307c478bd9Sstevel@tonic-gate * int dst_generate_key() Function to generate new KEY 317c478bd9Sstevel@tonic-gate * DST_KEY *dst_read_key() Function to retrieve private/public KEY. 327c478bd9Sstevel@tonic-gate * void dst_write_key() Function to write out a key. 337c478bd9Sstevel@tonic-gate * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST 347c478bd9Sstevel@tonic-gate * KEY structure. 357c478bd9Sstevel@tonic-gate * int dst_key_to_dnskey() Function to return a public key in DNS 367c478bd9Sstevel@tonic-gate * format binary 377c478bd9Sstevel@tonic-gate * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY 387c478bd9Sstevel@tonic-gate * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer 397c478bd9Sstevel@tonic-gate * void dst_free_key() Releases all memory referenced by key structure 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include "port_before.h" 437c478bd9Sstevel@tonic-gate #include <stdio.h> 447c478bd9Sstevel@tonic-gate #include <errno.h> 457c478bd9Sstevel@tonic-gate #include <fcntl.h> 467c478bd9Sstevel@tonic-gate #include <stdlib.h> 477c478bd9Sstevel@tonic-gate #include <unistd.h> 487c478bd9Sstevel@tonic-gate #include <string.h> 497c478bd9Sstevel@tonic-gate #include <memory.h> 507c478bd9Sstevel@tonic-gate #include <ctype.h> 517c478bd9Sstevel@tonic-gate #include <time.h> 527c478bd9Sstevel@tonic-gate #include <sys/param.h> 537c478bd9Sstevel@tonic-gate #include <sys/stat.h> 547c478bd9Sstevel@tonic-gate #include <sys/socket.h> 557c478bd9Sstevel@tonic-gate #include <netinet/in.h> 567c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 577c478bd9Sstevel@tonic-gate #include <resolv.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #include "dst_internal.h" 607c478bd9Sstevel@tonic-gate #include "port_after.h" 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* static variables */ 637c478bd9Sstevel@tonic-gate static int done_init = 0; 647c478bd9Sstevel@tonic-gate dst_func *dst_t_func[DST_MAX_ALGS]; 657c478bd9Sstevel@tonic-gate const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; 667c478bd9Sstevel@tonic-gate const char *dst_path = ""; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* internal I/O functions */ 697c478bd9Sstevel@tonic-gate static DST_KEY *dst_s_read_public_key(const char *in_name, 707c478bd9Sstevel@tonic-gate const u_int16_t in_id, int in_alg); 717c478bd9Sstevel@tonic-gate static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, 727c478bd9Sstevel@tonic-gate u_int16_t in_id, int in_alg); 737c478bd9Sstevel@tonic-gate static int dst_s_write_public_key(const DST_KEY *key); 747c478bd9Sstevel@tonic-gate static int dst_s_write_private_key(const DST_KEY *key); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* internal function to set up data structure */ 777c478bd9Sstevel@tonic-gate static DST_KEY *dst_s_get_key_struct(const char *name, const int alg, 787c478bd9Sstevel@tonic-gate const int flags, const int protocol, 797c478bd9Sstevel@tonic-gate const int bits); 807c478bd9Sstevel@tonic-gate 81*9525b14bSRao Shoaib /*% 827c478bd9Sstevel@tonic-gate * dst_init 837c478bd9Sstevel@tonic-gate * This function initializes the Digital Signature Toolkit. 847c478bd9Sstevel@tonic-gate * Right now, it just checks the DSTKEYPATH environment variable. 857c478bd9Sstevel@tonic-gate * Parameters 867c478bd9Sstevel@tonic-gate * none 877c478bd9Sstevel@tonic-gate * Returns 887c478bd9Sstevel@tonic-gate * none 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate void 917c478bd9Sstevel@tonic-gate dst_init() 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate char *s; 947c478bd9Sstevel@tonic-gate int len; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (done_init != 0) 977c478bd9Sstevel@tonic-gate return; 987c478bd9Sstevel@tonic-gate done_init = 1; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate s = getenv("DSTKEYPATH"); 1017c478bd9Sstevel@tonic-gate len = 0; 1027c478bd9Sstevel@tonic-gate if (s) { 1037c478bd9Sstevel@tonic-gate struct stat statbuf; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate len = strlen(s); 1067c478bd9Sstevel@tonic-gate if (len > PATH_MAX) { 1077c478bd9Sstevel@tonic-gate EREPORT(("%s is longer than %d characters, ignoring\n", 1087c478bd9Sstevel@tonic-gate s, PATH_MAX)); 1097c478bd9Sstevel@tonic-gate } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { 1107c478bd9Sstevel@tonic-gate EREPORT(("%s is not a valid directory\n", s)); 1117c478bd9Sstevel@tonic-gate } else { 1127c478bd9Sstevel@tonic-gate char *tmp; 1137c478bd9Sstevel@tonic-gate tmp = (char *) malloc(len + 2); 1147c478bd9Sstevel@tonic-gate memcpy(tmp, s, len + 1); 1157c478bd9Sstevel@tonic-gate if (tmp[strlen(tmp) - 1] != '/') { 1167c478bd9Sstevel@tonic-gate tmp[strlen(tmp) + 1] = 0; 1177c478bd9Sstevel@tonic-gate tmp[strlen(tmp)] = '/'; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate dst_path = tmp; 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate memset(dst_t_func, 0, sizeof(dst_t_func)); 1237c478bd9Sstevel@tonic-gate /* first one is selected */ 1247c478bd9Sstevel@tonic-gate dst_hmac_md5_init(); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 127*9525b14bSRao Shoaib /*% 1287c478bd9Sstevel@tonic-gate * dst_check_algorithm 1297c478bd9Sstevel@tonic-gate * This function determines if the crypto system for the specified 1307c478bd9Sstevel@tonic-gate * algorithm is present. 1317c478bd9Sstevel@tonic-gate * Parameters 1327c478bd9Sstevel@tonic-gate * alg 1 KEY_RSA 1337c478bd9Sstevel@tonic-gate * 3 KEY_DSA 1347c478bd9Sstevel@tonic-gate * 157 KEY_HMAC_MD5 1357c478bd9Sstevel@tonic-gate * future algorithms TBD and registered with IANA. 1367c478bd9Sstevel@tonic-gate * Returns 1377c478bd9Sstevel@tonic-gate * 1 - The algorithm is available. 1387c478bd9Sstevel@tonic-gate * 0 - The algorithm is not available. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate int 1417c478bd9Sstevel@tonic-gate dst_check_algorithm(const int alg) 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate return (dst_t_func[alg] != NULL); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 146*9525b14bSRao Shoaib /*% 1477c478bd9Sstevel@tonic-gate * dst_s_get_key_struct 1487c478bd9Sstevel@tonic-gate * This function allocates key structure and fills in some of the 1497c478bd9Sstevel@tonic-gate * fields of the structure. 1507c478bd9Sstevel@tonic-gate * Parameters: 1517c478bd9Sstevel@tonic-gate * name: the name of the key 1527c478bd9Sstevel@tonic-gate * alg: the algorithm number 1537c478bd9Sstevel@tonic-gate * flags: the dns flags of the key 1547c478bd9Sstevel@tonic-gate * protocol: the dns protocol of the key 1557c478bd9Sstevel@tonic-gate * bits: the size of the key 1567c478bd9Sstevel@tonic-gate * Returns: 1577c478bd9Sstevel@tonic-gate * NULL if error 1587c478bd9Sstevel@tonic-gate * valid pointer otherwise 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate static DST_KEY * 1617c478bd9Sstevel@tonic-gate dst_s_get_key_struct(const char *name, const int alg, const int flags, 1627c478bd9Sstevel@tonic-gate const int protocol, const int bits) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate DST_KEY *new_key = NULL; 1657c478bd9Sstevel@tonic-gate 166*9525b14bSRao Shoaib if (dst_check_algorithm(alg)) /*%< make sure alg is available */ 1677c478bd9Sstevel@tonic-gate new_key = (DST_KEY *) malloc(sizeof(*new_key)); 1687c478bd9Sstevel@tonic-gate if (new_key == NULL) 1697c478bd9Sstevel@tonic-gate return (NULL); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate memset(new_key, 0, sizeof(*new_key)); 1727c478bd9Sstevel@tonic-gate new_key->dk_key_name = strdup(name); 173*9525b14bSRao Shoaib if (new_key->dk_key_name == NULL) { 174*9525b14bSRao Shoaib free(new_key); 175*9525b14bSRao Shoaib return (NULL); 176*9525b14bSRao Shoaib } 1777c478bd9Sstevel@tonic-gate new_key->dk_alg = alg; 1787c478bd9Sstevel@tonic-gate new_key->dk_flags = flags; 1797c478bd9Sstevel@tonic-gate new_key->dk_proto = protocol; 1807c478bd9Sstevel@tonic-gate new_key->dk_KEY_struct = NULL; 1817c478bd9Sstevel@tonic-gate new_key->dk_key_size = bits; 1827c478bd9Sstevel@tonic-gate new_key->dk_func = dst_t_func[alg]; 1837c478bd9Sstevel@tonic-gate return (new_key); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 186*9525b14bSRao Shoaib /*% 1877c478bd9Sstevel@tonic-gate * dst_compare_keys 1887c478bd9Sstevel@tonic-gate * Compares two keys for equality. 1897c478bd9Sstevel@tonic-gate * Parameters 1907c478bd9Sstevel@tonic-gate * key1, key2 Two keys to be compared. 1917c478bd9Sstevel@tonic-gate * Returns 1927c478bd9Sstevel@tonic-gate * 0 The keys are equal. 1937c478bd9Sstevel@tonic-gate * non-zero The keys are not equal. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate int 1977c478bd9Sstevel@tonic-gate dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate if (key1 == key2) 2007c478bd9Sstevel@tonic-gate return (0); 2017c478bd9Sstevel@tonic-gate if (key1 == NULL || key2 == NULL) 2027c478bd9Sstevel@tonic-gate return (4); 2037c478bd9Sstevel@tonic-gate if (key1->dk_alg != key2->dk_alg) 2047c478bd9Sstevel@tonic-gate return (1); 2057c478bd9Sstevel@tonic-gate if (key1->dk_key_size != key2->dk_key_size) 2067c478bd9Sstevel@tonic-gate return (2); 2077c478bd9Sstevel@tonic-gate if (key1->dk_id != key2->dk_id) 2087c478bd9Sstevel@tonic-gate return (3); 2097c478bd9Sstevel@tonic-gate return (key1->dk_func->compare(key1, key2)); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 212*9525b14bSRao Shoaib /*% 2137c478bd9Sstevel@tonic-gate * dst_sign_data 2147c478bd9Sstevel@tonic-gate * An incremental signing function. Data is signed in steps. 2157c478bd9Sstevel@tonic-gate * First the context must be initialized (SIG_MODE_INIT). 2167c478bd9Sstevel@tonic-gate * Then data is hashed (SIG_MODE_UPDATE). Finally the signature 2177c478bd9Sstevel@tonic-gate * itself is created (SIG_MODE_FINAL). This function can be called 2187c478bd9Sstevel@tonic-gate * once with INIT, UPDATE and FINAL modes all set, or it can be 2197c478bd9Sstevel@tonic-gate * called separately with a different mode set for each step. The 2207c478bd9Sstevel@tonic-gate * UPDATE step can be repeated. 2217c478bd9Sstevel@tonic-gate * Parameters 2227c478bd9Sstevel@tonic-gate * mode A bit mask used to specify operation(s) to be performed. 2237c478bd9Sstevel@tonic-gate * SIG_MODE_INIT 1 Initialize digest 2247c478bd9Sstevel@tonic-gate * SIG_MODE_UPDATE 2 Add data to digest 2257c478bd9Sstevel@tonic-gate * SIG_MODE_FINAL 4 Generate signature 2267c478bd9Sstevel@tonic-gate * from signature 2277c478bd9Sstevel@tonic-gate * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL 2287c478bd9Sstevel@tonic-gate * data Data to be signed. 2297c478bd9Sstevel@tonic-gate * len The length in bytes of data to be signed. 2307c478bd9Sstevel@tonic-gate * in_key Contains a private key to sign with. 2317c478bd9Sstevel@tonic-gate * KEY structures should be handled (created, converted, 2327c478bd9Sstevel@tonic-gate * compared, stored, freed) by the DST. 2337c478bd9Sstevel@tonic-gate * signature 2347c478bd9Sstevel@tonic-gate * The location to which the signature will be written. 2357c478bd9Sstevel@tonic-gate * sig_len Length of the signature field in bytes. 2367c478bd9Sstevel@tonic-gate * Return 2377c478bd9Sstevel@tonic-gate * 0 Successfull INIT or Update operation 238*9525b14bSRao Shoaib * >0 success FINAL (sign) operation 239*9525b14bSRao Shoaib * <0 failure 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate int 2437c478bd9Sstevel@tonic-gate dst_sign_data(const int mode, DST_KEY *in_key, void **context, 2447c478bd9Sstevel@tonic-gate const u_char *data, const int len, 2457c478bd9Sstevel@tonic-gate u_char *signature, const int sig_len) 2467c478bd9Sstevel@tonic-gate { 2477c478bd9Sstevel@tonic-gate DUMP(data, mode, len, "dst_sign_data()"); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_FINAL && 2507c478bd9Sstevel@tonic-gate (in_key->dk_KEY_struct == NULL || signature == NULL)) 2517c478bd9Sstevel@tonic-gate return (MISSING_KEY_OR_SIGNATURE); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (in_key->dk_func && in_key->dk_func->sign) 2547c478bd9Sstevel@tonic-gate return (in_key->dk_func->sign(mode, in_key, context, data, len, 2557c478bd9Sstevel@tonic-gate signature, sig_len)); 2567c478bd9Sstevel@tonic-gate return (UNKNOWN_KEYALG); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 259*9525b14bSRao Shoaib /*% 2607c478bd9Sstevel@tonic-gate * dst_verify_data 2617c478bd9Sstevel@tonic-gate * An incremental verify function. Data is verified in steps. 2627c478bd9Sstevel@tonic-gate * First the context must be initialized (SIG_MODE_INIT). 2637c478bd9Sstevel@tonic-gate * Then data is hashed (SIG_MODE_UPDATE). Finally the signature 2647c478bd9Sstevel@tonic-gate * is verified (SIG_MODE_FINAL). This function can be called 2657c478bd9Sstevel@tonic-gate * once with INIT, UPDATE and FINAL modes all set, or it can be 2667c478bd9Sstevel@tonic-gate * called separately with a different mode set for each step. The 2677c478bd9Sstevel@tonic-gate * UPDATE step can be repeated. 2687c478bd9Sstevel@tonic-gate * Parameters 2697c478bd9Sstevel@tonic-gate * mode Operations to perform this time. 2707c478bd9Sstevel@tonic-gate * SIG_MODE_INIT 1 Initialize digest 2717c478bd9Sstevel@tonic-gate * SIG_MODE_UPDATE 2 add data to digest 2727c478bd9Sstevel@tonic-gate * SIG_MODE_FINAL 4 verify signature 2737c478bd9Sstevel@tonic-gate * SIG_MODE_ALL 2747c478bd9Sstevel@tonic-gate * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) 2757c478bd9Sstevel@tonic-gate * data Data to pass through the hash function. 2767c478bd9Sstevel@tonic-gate * len Length of the data in bytes. 2777c478bd9Sstevel@tonic-gate * in_key Key for verification. 2787c478bd9Sstevel@tonic-gate * signature Location of signature. 2797c478bd9Sstevel@tonic-gate * sig_len Length of the signature in bytes. 2807c478bd9Sstevel@tonic-gate * Returns 2817c478bd9Sstevel@tonic-gate * 0 Verify success 2827c478bd9Sstevel@tonic-gate * Non-Zero Verify Failure 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate int 2867c478bd9Sstevel@tonic-gate dst_verify_data(const int mode, DST_KEY *in_key, void **context, 2877c478bd9Sstevel@tonic-gate const u_char *data, const int len, 2887c478bd9Sstevel@tonic-gate const u_char *signature, const int sig_len) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate DUMP(data, mode, len, "dst_verify_data()"); 2917c478bd9Sstevel@tonic-gate if (mode & SIG_MODE_FINAL && 2927c478bd9Sstevel@tonic-gate (in_key->dk_KEY_struct == NULL || signature == NULL)) 2937c478bd9Sstevel@tonic-gate return (MISSING_KEY_OR_SIGNATURE); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) 2967c478bd9Sstevel@tonic-gate return (UNSUPPORTED_KEYALG); 2977c478bd9Sstevel@tonic-gate return (in_key->dk_func->verify(mode, in_key, context, data, len, 2987c478bd9Sstevel@tonic-gate signature, sig_len)); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 301*9525b14bSRao Shoaib /*% 3027c478bd9Sstevel@tonic-gate * dst_read_private_key 3037c478bd9Sstevel@tonic-gate * Access a private key. First the list of private keys that have 3047c478bd9Sstevel@tonic-gate * already been read in is searched, then the key accessed on disk. 3057c478bd9Sstevel@tonic-gate * If the private key can be found, it is returned. If the key cannot 3067c478bd9Sstevel@tonic-gate * be found, a null pointer is returned. The options specify required 3077c478bd9Sstevel@tonic-gate * key characteristics. If the private key requested does not have 3087c478bd9Sstevel@tonic-gate * these characteristics, it will not be read. 3097c478bd9Sstevel@tonic-gate * Parameters 3107c478bd9Sstevel@tonic-gate * in_keyname The private key name. 3117c478bd9Sstevel@tonic-gate * in_id The id of the private key. 3127c478bd9Sstevel@tonic-gate * options DST_FORCE_READ Read from disk - don't use a previously 3137c478bd9Sstevel@tonic-gate * read key. 3147c478bd9Sstevel@tonic-gate * DST_CAN_SIGN The key must be useable for signing. 3157c478bd9Sstevel@tonic-gate * DST_NO_AUTHEN The key must be useable for authentication. 3167c478bd9Sstevel@tonic-gate * DST_STANDARD Return any key 3177c478bd9Sstevel@tonic-gate * Returns 3187c478bd9Sstevel@tonic-gate * NULL If there is no key found in the current directory or 3197c478bd9Sstevel@tonic-gate * this key has not been loaded before. 3207c478bd9Sstevel@tonic-gate * !NULL Success - KEY structure returned. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate DST_KEY * 3247c478bd9Sstevel@tonic-gate dst_read_key(const char *in_keyname, const u_int16_t in_id, 3257c478bd9Sstevel@tonic-gate const int in_alg, const int type) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate char keyname[PATH_MAX]; 3287c478bd9Sstevel@tonic-gate DST_KEY *dg_key = NULL, *pubkey = NULL; 3297c478bd9Sstevel@tonic-gate 330*9525b14bSRao Shoaib if (!dst_check_algorithm(in_alg)) { /*%< make sure alg is available */ 3317c478bd9Sstevel@tonic-gate EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", 3327c478bd9Sstevel@tonic-gate in_alg)); 3337c478bd9Sstevel@tonic-gate return (NULL); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) 3367c478bd9Sstevel@tonic-gate return (NULL); 3377c478bd9Sstevel@tonic-gate if (in_keyname == NULL) { 3387c478bd9Sstevel@tonic-gate EREPORT(("dst_read_private_key(): Null key name passed in\n")); 3397c478bd9Sstevel@tonic-gate return (NULL); 340*9525b14bSRao Shoaib } else if (strlen(in_keyname) >= sizeof(keyname)) { 341*9525b14bSRao Shoaib EREPORT(("dst_read_private_key(): keyname too big\n")); 342*9525b14bSRao Shoaib return (NULL); 3437c478bd9Sstevel@tonic-gate } else 3447c478bd9Sstevel@tonic-gate strcpy(keyname, in_keyname); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* before I read in the public key, check if it is allowed to sign */ 3477c478bd9Sstevel@tonic-gate if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) 3487c478bd9Sstevel@tonic-gate return (NULL); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (type == DST_PUBLIC) 3517c478bd9Sstevel@tonic-gate return pubkey; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, 3547c478bd9Sstevel@tonic-gate pubkey->dk_flags, pubkey->dk_proto, 3557c478bd9Sstevel@tonic-gate 0))) 3567c478bd9Sstevel@tonic-gate return (dg_key); 3577c478bd9Sstevel@tonic-gate /* Fill in private key and some fields in the general key structure */ 3587c478bd9Sstevel@tonic-gate if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, 3597c478bd9Sstevel@tonic-gate pubkey->dk_alg) == 0) 3607c478bd9Sstevel@tonic-gate dg_key = dst_free_key(dg_key); 3617c478bd9Sstevel@tonic-gate 362*9525b14bSRao Shoaib (void)dst_free_key(pubkey); 3637c478bd9Sstevel@tonic-gate return (dg_key); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate int 3677c478bd9Sstevel@tonic-gate dst_write_key(const DST_KEY *key, const int type) 3687c478bd9Sstevel@tonic-gate { 3697c478bd9Sstevel@tonic-gate int pub = 0, priv = 0; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate if (key == NULL) 3727c478bd9Sstevel@tonic-gate return (0); 373*9525b14bSRao Shoaib if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ 3747c478bd9Sstevel@tonic-gate EREPORT(("dst_write_key(): Algorithm %d not suppored\n", 3757c478bd9Sstevel@tonic-gate key->dk_alg)); 3767c478bd9Sstevel@tonic-gate return (UNSUPPORTED_KEYALG); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) 3797c478bd9Sstevel@tonic-gate return (0); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (type & DST_PUBLIC) 3827c478bd9Sstevel@tonic-gate if ((pub = dst_s_write_public_key(key)) < 0) 3837c478bd9Sstevel@tonic-gate return (pub); 3847c478bd9Sstevel@tonic-gate if (type & DST_PRIVATE) 3857c478bd9Sstevel@tonic-gate if ((priv = dst_s_write_private_key(key)) < 0) 3867c478bd9Sstevel@tonic-gate return (priv); 3877c478bd9Sstevel@tonic-gate return (priv+pub); 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 390*9525b14bSRao Shoaib /*% 3917c478bd9Sstevel@tonic-gate * dst_write_private_key 3927c478bd9Sstevel@tonic-gate * Write a private key to disk. The filename will be of the form: 393*9525b14bSRao Shoaib * K<key->dk_name>+<key->dk_alg+><key-d>k_id.><private key suffix>. 3947c478bd9Sstevel@tonic-gate * If there is already a file with this name, an error is returned. 3957c478bd9Sstevel@tonic-gate * 3967c478bd9Sstevel@tonic-gate * Parameters 3977c478bd9Sstevel@tonic-gate * key A DST managed key structure that contains 3987c478bd9Sstevel@tonic-gate * all information needed about a key. 3997c478bd9Sstevel@tonic-gate * Return 400*9525b14bSRao Shoaib * >= 0 Correct behavior. Returns length of encoded key value 4017c478bd9Sstevel@tonic-gate * written to disk. 402*9525b14bSRao Shoaib * < 0 error. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate static int 4067c478bd9Sstevel@tonic-gate dst_s_write_private_key(const DST_KEY *key) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate u_char encoded_block[RAW_KEY_SIZE]; 4097c478bd9Sstevel@tonic-gate char file[PATH_MAX]; 4107c478bd9Sstevel@tonic-gate int len; 4117c478bd9Sstevel@tonic-gate FILE *fp; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* First encode the key into the portable key format */ 4147c478bd9Sstevel@tonic-gate if (key == NULL) 4157c478bd9Sstevel@tonic-gate return (-1); 4167c478bd9Sstevel@tonic-gate if (key->dk_KEY_struct == NULL) 417*9525b14bSRao Shoaib return (0); /*%< null key has no private key */ 4187c478bd9Sstevel@tonic-gate if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { 4197c478bd9Sstevel@tonic-gate EREPORT(("dst_write_private_key(): Unsupported operation %d\n", 4207c478bd9Sstevel@tonic-gate key->dk_alg)); 4217c478bd9Sstevel@tonic-gate return (-5); 4227c478bd9Sstevel@tonic-gate } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, 4237c478bd9Sstevel@tonic-gate sizeof(encoded_block))) <= 0) { 4247c478bd9Sstevel@tonic-gate EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); 4257c478bd9Sstevel@tonic-gate return (-8); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate /* Now I can create the file I want to use */ 4287c478bd9Sstevel@tonic-gate dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, 4297c478bd9Sstevel@tonic-gate PRIVATE_KEY, PATH_MAX); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* Do not overwrite an existing file */ 4327c478bd9Sstevel@tonic-gate if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { 4337c478bd9Sstevel@tonic-gate int nn; 4347c478bd9Sstevel@tonic-gate if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { 4357c478bd9Sstevel@tonic-gate EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", 4367c478bd9Sstevel@tonic-gate file, len, nn, errno)); 437*9525b14bSRao Shoaib fclose(fp); 4387c478bd9Sstevel@tonic-gate return (-5); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate fclose(fp); 4417c478bd9Sstevel@tonic-gate } else { 4427c478bd9Sstevel@tonic-gate EREPORT(("dst_write_private_key(): Can not create file %s\n" 4437c478bd9Sstevel@tonic-gate ,file)); 4447c478bd9Sstevel@tonic-gate return (-6); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate memset(encoded_block, 0, len); 4477c478bd9Sstevel@tonic-gate return (len); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 450*9525b14bSRao Shoaib /*% 4517c478bd9Sstevel@tonic-gate * 4527c478bd9Sstevel@tonic-gate * dst_read_public_key 4537c478bd9Sstevel@tonic-gate * Read a public key from disk and store in a DST key structure. 4547c478bd9Sstevel@tonic-gate * Parameters 455*9525b14bSRao Shoaib * in_name K<in_name><in_id>.<public key suffix> is the 4567c478bd9Sstevel@tonic-gate * filename of the key file to be read. 4577c478bd9Sstevel@tonic-gate * Returns 4587c478bd9Sstevel@tonic-gate * NULL If the key does not exist or no name is supplied. 4597c478bd9Sstevel@tonic-gate * NON-NULL Initialized key structure if the key exists. 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate static DST_KEY * 4637c478bd9Sstevel@tonic-gate dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate int flags, proto, alg, len, dlen; 4667c478bd9Sstevel@tonic-gate int c; 4677c478bd9Sstevel@tonic-gate char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; 4687c478bd9Sstevel@tonic-gate u_char deckey[RAW_KEY_SIZE]; 4697c478bd9Sstevel@tonic-gate FILE *fp; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (in_name == NULL) { 4727c478bd9Sstevel@tonic-gate EREPORT(("dst_read_public_key(): No key name given\n")); 4737c478bd9Sstevel@tonic-gate return (NULL); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, 4767c478bd9Sstevel@tonic-gate PATH_MAX) == -1) { 4777c478bd9Sstevel@tonic-gate EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", 4787c478bd9Sstevel@tonic-gate in_name, in_id, PUBLIC_KEY)); 4797c478bd9Sstevel@tonic-gate return (NULL); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Open the file and read it's formatted contents up to key 4837c478bd9Sstevel@tonic-gate * File format: 484*9525b14bSRao Shoaib * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key> 4857c478bd9Sstevel@tonic-gate * flags, proto, alg stored as decimal (or hex numbers FIXME). 4867c478bd9Sstevel@tonic-gate * (FIXME: handle parentheses for line continuation.) 4877c478bd9Sstevel@tonic-gate */ 4887c478bd9Sstevel@tonic-gate if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { 4897c478bd9Sstevel@tonic-gate EREPORT(("dst_read_public_key(): Public Key not found %s\n", 4907c478bd9Sstevel@tonic-gate name)); 4917c478bd9Sstevel@tonic-gate return (NULL); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate /* Skip domain name, which ends at first blank */ 4947c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 4957c478bd9Sstevel@tonic-gate if (isspace(c)) 4967c478bd9Sstevel@tonic-gate break; 4977c478bd9Sstevel@tonic-gate /* Skip blank to get to next field */ 4987c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 4997c478bd9Sstevel@tonic-gate if (!isspace(c)) 5007c478bd9Sstevel@tonic-gate break; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* Skip optional TTL -- if initial digit, skip whole word. */ 5037c478bd9Sstevel@tonic-gate if (isdigit(c)) { 5047c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5057c478bd9Sstevel@tonic-gate if (isspace(c)) 5067c478bd9Sstevel@tonic-gate break; 5077c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5087c478bd9Sstevel@tonic-gate if (!isspace(c)) 5097c478bd9Sstevel@tonic-gate break; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate /* Skip optional "IN" */ 5127c478bd9Sstevel@tonic-gate if (c == 'I' || c == 'i') { 5137c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5147c478bd9Sstevel@tonic-gate if (isspace(c)) 5157c478bd9Sstevel@tonic-gate break; 5167c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5177c478bd9Sstevel@tonic-gate if (!isspace(c)) 5187c478bd9Sstevel@tonic-gate break; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate /* Locate and skip "KEY" */ 5217c478bd9Sstevel@tonic-gate if (c != 'K' && c != 'k') { 5227c478bd9Sstevel@tonic-gate EREPORT(("\"KEY\" doesn't appear in file: %s", name)); 5237c478bd9Sstevel@tonic-gate return NULL; 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5267c478bd9Sstevel@tonic-gate if (isspace(c)) 5277c478bd9Sstevel@tonic-gate break; 5287c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5297c478bd9Sstevel@tonic-gate if (!isspace(c)) 5307c478bd9Sstevel@tonic-gate break; 531*9525b14bSRao Shoaib ungetc(c, fp); /*%< return the charcter to the input field */ 5327c478bd9Sstevel@tonic-gate /* Handle hex!! FIXME. */ 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { 5357c478bd9Sstevel@tonic-gate EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" 5367c478bd9Sstevel@tonic-gate ,name)); 5377c478bd9Sstevel@tonic-gate return (NULL); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate /* read in the key string */ 5407c478bd9Sstevel@tonic-gate fgets(enckey, sizeof(enckey), fp); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* If we aren't at end-of-file, something is wrong. */ 5437c478bd9Sstevel@tonic-gate while ((c = getc(fp)) != EOF) 5447c478bd9Sstevel@tonic-gate if (!isspace(c)) 5457c478bd9Sstevel@tonic-gate break; 5467c478bd9Sstevel@tonic-gate if (!feof(fp)) { 5477c478bd9Sstevel@tonic-gate EREPORT(("Key too long in file: %s", name)); 5487c478bd9Sstevel@tonic-gate return NULL; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate fclose(fp); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate if ((len = strlen(enckey)) <= 0) 5537c478bd9Sstevel@tonic-gate return (NULL); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* discard \n */ 5567c478bd9Sstevel@tonic-gate enckey[--len] = '\0'; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* remove leading spaces */ 5597c478bd9Sstevel@tonic-gate for (notspace = (char *) enckey; isspace((*notspace)&0xff); len--) 5607c478bd9Sstevel@tonic-gate notspace++; 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate dlen = b64_pton(notspace, deckey, sizeof(deckey)); 5637c478bd9Sstevel@tonic-gate if (dlen < 0) { 5647c478bd9Sstevel@tonic-gate EREPORT(("dst_read_public_key: bad return from b64_pton = %d", 5657c478bd9Sstevel@tonic-gate dlen)); 5667c478bd9Sstevel@tonic-gate return (NULL); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate /* store key and info in a key structure that is returned */ 5697c478bd9Sstevel@tonic-gate /* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, 5707c478bd9Sstevel@tonic-gate dlen);*/ 5717c478bd9Sstevel@tonic-gate return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 574*9525b14bSRao Shoaib /*% 5757c478bd9Sstevel@tonic-gate * dst_write_public_key 5767c478bd9Sstevel@tonic-gate * Write a key to disk in DNS format. 5777c478bd9Sstevel@tonic-gate * Parameters 5787c478bd9Sstevel@tonic-gate * key Pointer to a DST key structure. 5797c478bd9Sstevel@tonic-gate * Returns 5807c478bd9Sstevel@tonic-gate * 0 Failure 5817c478bd9Sstevel@tonic-gate * 1 Success 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate static int 5857c478bd9Sstevel@tonic-gate dst_s_write_public_key(const DST_KEY *key) 5867c478bd9Sstevel@tonic-gate { 5877c478bd9Sstevel@tonic-gate FILE *fp; 5887c478bd9Sstevel@tonic-gate char filename[PATH_MAX]; 5897c478bd9Sstevel@tonic-gate u_char out_key[RAW_KEY_SIZE]; 5907c478bd9Sstevel@tonic-gate char enc_key[RAW_KEY_SIZE]; 5917c478bd9Sstevel@tonic-gate int len = 0; 5927c478bd9Sstevel@tonic-gate int mode; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate memset(out_key, 0, sizeof(out_key)); 5957c478bd9Sstevel@tonic-gate if (key == NULL) { 5967c478bd9Sstevel@tonic-gate EREPORT(("dst_write_public_key(): No key specified \n")); 5977c478bd9Sstevel@tonic-gate return (0); 5987c478bd9Sstevel@tonic-gate } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) 5997c478bd9Sstevel@tonic-gate return (0); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate /* Make the filename */ 6027c478bd9Sstevel@tonic-gate if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, 6037c478bd9Sstevel@tonic-gate key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { 6047c478bd9Sstevel@tonic-gate EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", 6057c478bd9Sstevel@tonic-gate key->dk_key_name, key->dk_id, PUBLIC_KEY)); 6067c478bd9Sstevel@tonic-gate return (0); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate /* XXX in general this should be a check for symmetric keys */ 6097c478bd9Sstevel@tonic-gate mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644; 6107c478bd9Sstevel@tonic-gate /* create public key file */ 6117c478bd9Sstevel@tonic-gate if ((fp = dst_s_fopen(filename, "w+", mode)) == NULL) { 6127c478bd9Sstevel@tonic-gate EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", 6137c478bd9Sstevel@tonic-gate filename, errno)); 6147c478bd9Sstevel@tonic-gate return (0); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate /*write out key first base64 the key data */ 6177c478bd9Sstevel@tonic-gate if (key->dk_flags & DST_EXTEND_FLAG) 6187c478bd9Sstevel@tonic-gate b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); 6197c478bd9Sstevel@tonic-gate else 6207c478bd9Sstevel@tonic-gate b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); 6217c478bd9Sstevel@tonic-gate fprintf(fp, "%s IN KEY %d %d %d %s\n", 6227c478bd9Sstevel@tonic-gate key->dk_key_name, 6237c478bd9Sstevel@tonic-gate key->dk_flags, key->dk_proto, key->dk_alg, enc_key); 6247c478bd9Sstevel@tonic-gate fclose(fp); 6257c478bd9Sstevel@tonic-gate return (1); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 628*9525b14bSRao Shoaib /*% 6297c478bd9Sstevel@tonic-gate * dst_dnskey_to_public_key 6307c478bd9Sstevel@tonic-gate * This function converts the contents of a DNS KEY RR into a DST 6317c478bd9Sstevel@tonic-gate * key structure. 6327c478bd9Sstevel@tonic-gate * Paramters 6337c478bd9Sstevel@tonic-gate * len Length of the RDATA of the KEY RR RDATA 6347c478bd9Sstevel@tonic-gate * rdata A pointer to the the KEY RR RDATA. 6357c478bd9Sstevel@tonic-gate * in_name Key name to be stored in key structure. 6367c478bd9Sstevel@tonic-gate * Returns 6377c478bd9Sstevel@tonic-gate * NULL Failure 6387c478bd9Sstevel@tonic-gate * NON-NULL Success. Pointer to key structure. 6397c478bd9Sstevel@tonic-gate * Caller's responsibility to free() it. 6407c478bd9Sstevel@tonic-gate */ 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate DST_KEY * 6437c478bd9Sstevel@tonic-gate dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate DST_KEY *key_st; 6467c478bd9Sstevel@tonic-gate int alg ; 6477c478bd9Sstevel@tonic-gate int start = DST_KEY_START; 6487c478bd9Sstevel@tonic-gate 649*9525b14bSRao Shoaib if (rdata == NULL || len <= DST_KEY_ALG) /*%< no data */ 6507c478bd9Sstevel@tonic-gate return (NULL); 6517c478bd9Sstevel@tonic-gate alg = (u_int8_t) rdata[DST_KEY_ALG]; 652*9525b14bSRao Shoaib if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ 6537c478bd9Sstevel@tonic-gate EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", 6547c478bd9Sstevel@tonic-gate alg)); 6557c478bd9Sstevel@tonic-gate return (NULL); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (in_name == NULL) 6597c478bd9Sstevel@tonic-gate return (NULL); 660*9525b14bSRao Shoaib 661*9525b14bSRao Shoaib if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) 662*9525b14bSRao Shoaib return (NULL); 663*9525b14bSRao Shoaib 6647c478bd9Sstevel@tonic-gate key_st->dk_id = dst_s_dns_key_id(rdata, len); 6657c478bd9Sstevel@tonic-gate key_st->dk_flags = dst_s_get_int16(rdata); 6667c478bd9Sstevel@tonic-gate key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; 6677c478bd9Sstevel@tonic-gate if (key_st->dk_flags & DST_EXTEND_FLAG) { 6687c478bd9Sstevel@tonic-gate u_int32_t ext_flags; 6697c478bd9Sstevel@tonic-gate ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); 6707c478bd9Sstevel@tonic-gate key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); 6717c478bd9Sstevel@tonic-gate start += 2; 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * now point to the begining of the data representing the encoding 6757c478bd9Sstevel@tonic-gate * of the key 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if (key_st->dk_func && key_st->dk_func->from_dns_key) { 6787c478bd9Sstevel@tonic-gate if (key_st->dk_func->from_dns_key(key_st, &rdata[start], 6797c478bd9Sstevel@tonic-gate len - start) > 0) 6807c478bd9Sstevel@tonic-gate return (key_st); 6817c478bd9Sstevel@tonic-gate } else 6827c478bd9Sstevel@tonic-gate EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", 6837c478bd9Sstevel@tonic-gate alg)); 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate SAFE_FREE(key_st); 6867c478bd9Sstevel@tonic-gate return (key_st); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 689*9525b14bSRao Shoaib /*% 6907c478bd9Sstevel@tonic-gate * dst_public_key_to_dnskey 6917c478bd9Sstevel@tonic-gate * Function to encode a public key into DNS KEY wire format 6927c478bd9Sstevel@tonic-gate * Parameters 6937c478bd9Sstevel@tonic-gate * key Key structure to encode. 6947c478bd9Sstevel@tonic-gate * out_storage Location to write the encoded key to. 6957c478bd9Sstevel@tonic-gate * out_len Size of the output array. 6967c478bd9Sstevel@tonic-gate * Returns 6977c478bd9Sstevel@tonic-gate * <0 Failure 6987c478bd9Sstevel@tonic-gate * >=0 Number of bytes written to out_storage 6997c478bd9Sstevel@tonic-gate */ 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate int 7027c478bd9Sstevel@tonic-gate dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, 7037c478bd9Sstevel@tonic-gate const int out_len) 7047c478bd9Sstevel@tonic-gate { 7057c478bd9Sstevel@tonic-gate u_int16_t val; 7067c478bd9Sstevel@tonic-gate int loc = 0; 7077c478bd9Sstevel@tonic-gate int enc_len = 0; 7087c478bd9Sstevel@tonic-gate if (key == NULL) 7097c478bd9Sstevel@tonic-gate return (-1); 7107c478bd9Sstevel@tonic-gate 711*9525b14bSRao Shoaib if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ 7127c478bd9Sstevel@tonic-gate EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", 7137c478bd9Sstevel@tonic-gate key->dk_alg)); 7147c478bd9Sstevel@tonic-gate return (UNSUPPORTED_KEYALG); 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate memset(out_storage, 0, out_len); 7177c478bd9Sstevel@tonic-gate val = (u_int16_t)(key->dk_flags & 0xffff); 7187c478bd9Sstevel@tonic-gate dst_s_put_int16(out_storage, val); 7197c478bd9Sstevel@tonic-gate loc += 2; 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate out_storage[loc++] = (u_char) key->dk_proto; 7227c478bd9Sstevel@tonic-gate out_storage[loc++] = (u_char) key->dk_alg; 7237c478bd9Sstevel@tonic-gate 724*9525b14bSRao Shoaib if (key->dk_flags > 0xffff) { /*%< Extended flags */ 7257c478bd9Sstevel@tonic-gate val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); 7267c478bd9Sstevel@tonic-gate dst_s_put_int16(&out_storage[loc], val); 7277c478bd9Sstevel@tonic-gate loc += 2; 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate if (key->dk_KEY_struct == NULL) 7307c478bd9Sstevel@tonic-gate return (loc); 7317c478bd9Sstevel@tonic-gate if (key->dk_func && key->dk_func->to_dns_key) { 7327c478bd9Sstevel@tonic-gate enc_len = key->dk_func->to_dns_key(key, 7337c478bd9Sstevel@tonic-gate (u_char *) &out_storage[loc], 7347c478bd9Sstevel@tonic-gate out_len - loc); 7357c478bd9Sstevel@tonic-gate if (enc_len > 0) 7367c478bd9Sstevel@tonic-gate return (enc_len + loc); 7377c478bd9Sstevel@tonic-gate else 7387c478bd9Sstevel@tonic-gate return (-1); 7397c478bd9Sstevel@tonic-gate } else 7407c478bd9Sstevel@tonic-gate EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", 7417c478bd9Sstevel@tonic-gate key->dk_alg)); 7427c478bd9Sstevel@tonic-gate return (-1); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 745*9525b14bSRao Shoaib /*% 7467c478bd9Sstevel@tonic-gate * dst_buffer_to_key 7477c478bd9Sstevel@tonic-gate * Function to encode a string of raw data into a DST key 7487c478bd9Sstevel@tonic-gate * Parameters 7497c478bd9Sstevel@tonic-gate * alg The algorithm (HMAC only) 7507c478bd9Sstevel@tonic-gate * key A pointer to the data 7517c478bd9Sstevel@tonic-gate * keylen The length of the data 7527c478bd9Sstevel@tonic-gate * Returns 7537c478bd9Sstevel@tonic-gate * NULL an error occurred 7547c478bd9Sstevel@tonic-gate * NON-NULL the DST key 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate DST_KEY * 757*9525b14bSRao Shoaib dst_buffer_to_key(const char *key_name, /*!< name of the key */ 758*9525b14bSRao Shoaib const int alg, /*!< algorithm */ 759*9525b14bSRao Shoaib const int flags, /*!< dns flags */ 760*9525b14bSRao Shoaib const int protocol, /*!< dns protocol */ 761*9525b14bSRao Shoaib const u_char *key_buf, /*!< key in dns wire fmt */ 762*9525b14bSRao Shoaib const int key_len) /*!< size of key */ 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate DST_KEY *dkey = NULL; 7667c478bd9Sstevel@tonic-gate int dnslen; 7677c478bd9Sstevel@tonic-gate u_char dns[2048]; 7687c478bd9Sstevel@tonic-gate 769*9525b14bSRao Shoaib if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ 7707c478bd9Sstevel@tonic-gate EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); 7717c478bd9Sstevel@tonic-gate return (NULL); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 774*9525b14bSRao Shoaib dkey = dst_s_get_key_struct(key_name, alg, flags, protocol, -1); 7757c478bd9Sstevel@tonic-gate 776*9525b14bSRao Shoaib if (dkey == NULL || dkey->dk_func == NULL || 777*9525b14bSRao Shoaib dkey->dk_func->from_dns_key == NULL) 778*9525b14bSRao Shoaib return (dst_free_key(dkey)); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { 7817c478bd9Sstevel@tonic-gate EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); 7827c478bd9Sstevel@tonic-gate return (dst_free_key(dkey)); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate dnslen = dst_key_to_dnskey(dkey, dns, sizeof(dns)); 7867c478bd9Sstevel@tonic-gate dkey->dk_id = dst_s_dns_key_id(dns, dnslen); 7877c478bd9Sstevel@tonic-gate return (dkey); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate int 7917c478bd9Sstevel@tonic-gate dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len) 7927c478bd9Sstevel@tonic-gate { 7937c478bd9Sstevel@tonic-gate int len; 7947c478bd9Sstevel@tonic-gate /* this function will extrac the secret of HMAC into a buffer */ 7957c478bd9Sstevel@tonic-gate if (key == NULL) 7967c478bd9Sstevel@tonic-gate return (0); 7977c478bd9Sstevel@tonic-gate if (key->dk_func != NULL && key->dk_func->to_dns_key != NULL) { 7987c478bd9Sstevel@tonic-gate len = key->dk_func->to_dns_key(key, out_buff, buf_len); 7997c478bd9Sstevel@tonic-gate if (len < 0) 8007c478bd9Sstevel@tonic-gate return (0); 8017c478bd9Sstevel@tonic-gate return (len); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate return (0); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 806*9525b14bSRao Shoaib /*% 8077c478bd9Sstevel@tonic-gate * dst_s_read_private_key_file 8087c478bd9Sstevel@tonic-gate * Function reads in private key from a file. 8097c478bd9Sstevel@tonic-gate * Fills out the KEY structure. 8107c478bd9Sstevel@tonic-gate * Parameters 8117c478bd9Sstevel@tonic-gate * name Name of the key to be read. 8127c478bd9Sstevel@tonic-gate * pk_key Structure that the key is returned in. 8137c478bd9Sstevel@tonic-gate * in_id Key identifier (tag) 8147c478bd9Sstevel@tonic-gate * Return 8157c478bd9Sstevel@tonic-gate * 1 if everthing works 8167c478bd9Sstevel@tonic-gate * 0 if there is any problem 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate static int 8207c478bd9Sstevel@tonic-gate dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id, 8217c478bd9Sstevel@tonic-gate int in_alg) 8227c478bd9Sstevel@tonic-gate { 8237c478bd9Sstevel@tonic-gate int cnt, alg, len, major, minor, file_major, file_minor; 8247c478bd9Sstevel@tonic-gate int ret, id; 8257c478bd9Sstevel@tonic-gate char filename[PATH_MAX]; 8267c478bd9Sstevel@tonic-gate u_char in_buff[RAW_KEY_SIZE], *p; 8277c478bd9Sstevel@tonic-gate FILE *fp; 8287c478bd9Sstevel@tonic-gate int dnslen; 8297c478bd9Sstevel@tonic-gate u_char dns[2048]; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate if (name == NULL || pk_key == NULL) { 8327c478bd9Sstevel@tonic-gate EREPORT(("dst_read_private_key_file(): No key name given\n")); 8337c478bd9Sstevel@tonic-gate return (0); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate /* Make the filename */ 8367c478bd9Sstevel@tonic-gate if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, 8377c478bd9Sstevel@tonic-gate PATH_MAX) == -1) { 8387c478bd9Sstevel@tonic-gate EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", 8397c478bd9Sstevel@tonic-gate name, in_id, PRIVATE_KEY)); 8407c478bd9Sstevel@tonic-gate return (0); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate /* first check if we can find the key file */ 8437c478bd9Sstevel@tonic-gate if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { 8447c478bd9Sstevel@tonic-gate EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", 8457c478bd9Sstevel@tonic-gate filename, dst_path[0] ? dst_path : 8467c478bd9Sstevel@tonic-gate (char *) getcwd(NULL, PATH_MAX - 1))); 8477c478bd9Sstevel@tonic-gate return (0); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate /* now read the header info from the file */ 8507c478bd9Sstevel@tonic-gate if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { 8517c478bd9Sstevel@tonic-gate fclose(fp); 8527c478bd9Sstevel@tonic-gate EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", 8537c478bd9Sstevel@tonic-gate filename)); 8547c478bd9Sstevel@tonic-gate return (0); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate /* decrypt key */ 8577c478bd9Sstevel@tonic-gate fclose(fp); 8587c478bd9Sstevel@tonic-gate if (memcmp(in_buff, "Private-key-format: v", 20) != 0) 8597c478bd9Sstevel@tonic-gate goto fail; 8607c478bd9Sstevel@tonic-gate len = cnt; 8617c478bd9Sstevel@tonic-gate p = in_buff; 8627c478bd9Sstevel@tonic-gate 863*9525b14bSRao Shoaib if (!dst_s_verify_str((const char **) (void *)&p, 864*9525b14bSRao Shoaib "Private-key-format: v")) { 8657c478bd9Sstevel@tonic-gate EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); 8667c478bd9Sstevel@tonic-gate goto fail; 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate /* read in file format */ 8697c478bd9Sstevel@tonic-gate sscanf((char *)p, "%d.%d", &file_major, &file_minor); 8707c478bd9Sstevel@tonic-gate sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); 8717c478bd9Sstevel@tonic-gate if (file_major < 1) { 8727c478bd9Sstevel@tonic-gate EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", 8737c478bd9Sstevel@tonic-gate file_major, file_minor, name)); 8747c478bd9Sstevel@tonic-gate goto fail; 8757c478bd9Sstevel@tonic-gate } else if (file_major > major || file_minor > minor) 8767c478bd9Sstevel@tonic-gate EREPORT(( 8777c478bd9Sstevel@tonic-gate "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", 8787c478bd9Sstevel@tonic-gate name, file_major, file_minor)); 8797c478bd9Sstevel@tonic-gate 880*9525b14bSRao Shoaib while (*p++ != '\n') ; /*%< skip to end of line */ 8817c478bd9Sstevel@tonic-gate 882*9525b14bSRao Shoaib if (!dst_s_verify_str((const char **) (void *)&p, "Algorithm: ")) 8837c478bd9Sstevel@tonic-gate goto fail; 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate if (sscanf((char *)p, "%d", &alg) != 1) 8867c478bd9Sstevel@tonic-gate goto fail; 887*9525b14bSRao Shoaib while (*p++ != '\n') ; /*%< skip to end of line */ 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) 8907c478bd9Sstevel@tonic-gate SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); 8917c478bd9Sstevel@tonic-gate pk_key->dk_key_name = (char *) strdup(name); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* allocate and fill in key structure */ 8947c478bd9Sstevel@tonic-gate if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) 8957c478bd9Sstevel@tonic-gate goto fail; 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate ret = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p); 8987c478bd9Sstevel@tonic-gate if (ret < 0) 8997c478bd9Sstevel@tonic-gate goto fail; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate dnslen = dst_key_to_dnskey(pk_key, dns, sizeof(dns)); 9027c478bd9Sstevel@tonic-gate id = dst_s_dns_key_id(dns, dnslen); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate /* Make sure the actual key tag matches the input tag used in the filename 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate if (id != in_id) { 9077c478bd9Sstevel@tonic-gate EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); 9087c478bd9Sstevel@tonic-gate goto fail; 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate pk_key->dk_id = (u_int16_t) id; 9117c478bd9Sstevel@tonic-gate pk_key->dk_alg = alg; 9127c478bd9Sstevel@tonic-gate memset(in_buff, 0, cnt); 9137c478bd9Sstevel@tonic-gate return (1); 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate fail: 9167c478bd9Sstevel@tonic-gate memset(in_buff, 0, cnt); 9177c478bd9Sstevel@tonic-gate return (0); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 920*9525b14bSRao Shoaib /*% 9217c478bd9Sstevel@tonic-gate * Generate and store a public/private keypair. 9227c478bd9Sstevel@tonic-gate * Keys will be stored in formatted files. 923*9525b14bSRao Shoaib * 9247c478bd9Sstevel@tonic-gate * Parameters 925*9525b14bSRao Shoaib & 926*9525b14bSRao Shoaib *\par name Name of the new key. Used to create key files 927*9525b14bSRao Shoaib *\li K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private. 928*9525b14bSRao Shoaib *\par bits Size of the new key in bits. 929*9525b14bSRao Shoaib *\par exp What exponent to use: 930*9525b14bSRao Shoaib *\li 0 use exponent 3 931*9525b14bSRao Shoaib *\li non-zero use Fermant4 932*9525b14bSRao Shoaib *\par flags The default value of the DNS Key flags. 933*9525b14bSRao Shoaib *\li The DNS Key RR Flag field is defined in RFC2065, 9347c478bd9Sstevel@tonic-gate * section 3.3. The field has 16 bits. 935*9525b14bSRao Shoaib *\par protocol 936*9525b14bSRao Shoaib *\li Default value of the DNS Key protocol field. 937*9525b14bSRao Shoaib *\li The DNS Key protocol field is defined in RFC2065, 9387c478bd9Sstevel@tonic-gate * section 3.4. The field has 8 bits. 939*9525b14bSRao Shoaib *\par alg What algorithm to use. Currently defined: 940*9525b14bSRao Shoaib *\li KEY_RSA 1 941*9525b14bSRao Shoaib *\li KEY_DSA 3 942*9525b14bSRao Shoaib *\li KEY_HMAC 157 943*9525b14bSRao Shoaib *\par out_id The key tag is returned. 9447c478bd9Sstevel@tonic-gate * 9457c478bd9Sstevel@tonic-gate * Return 946*9525b14bSRao Shoaib *\li NULL Failure 947*9525b14bSRao Shoaib *\li non-NULL the generated key pair 9487c478bd9Sstevel@tonic-gate * Caller frees the result, and its dk_name pointer. 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate DST_KEY * 9517c478bd9Sstevel@tonic-gate dst_generate_key(const char *name, const int bits, const int exp, 9527c478bd9Sstevel@tonic-gate const int flags, const int protocol, const int alg) 9537c478bd9Sstevel@tonic-gate { 9547c478bd9Sstevel@tonic-gate DST_KEY *new_key = NULL; 9557c478bd9Sstevel@tonic-gate int dnslen; 9567c478bd9Sstevel@tonic-gate u_char dns[2048]; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate if (name == NULL) 9597c478bd9Sstevel@tonic-gate return (NULL); 9607c478bd9Sstevel@tonic-gate 961*9525b14bSRao Shoaib if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ 9627c478bd9Sstevel@tonic-gate EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); 9637c478bd9Sstevel@tonic-gate return (NULL); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); 9677c478bd9Sstevel@tonic-gate if (new_key == NULL) 9687c478bd9Sstevel@tonic-gate return (NULL); 969*9525b14bSRao Shoaib if (bits == 0) /*%< null key we are done */ 9707c478bd9Sstevel@tonic-gate return (new_key); 9717c478bd9Sstevel@tonic-gate if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { 9727c478bd9Sstevel@tonic-gate EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", 9737c478bd9Sstevel@tonic-gate alg)); 9747c478bd9Sstevel@tonic-gate return (dst_free_key(new_key)); 9757c478bd9Sstevel@tonic-gate } 976*9525b14bSRao Shoaib if (new_key->dk_func->generate(new_key, exp) <= 0) { 9777c478bd9Sstevel@tonic-gate EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", 9787c478bd9Sstevel@tonic-gate new_key->dk_key_name, new_key->dk_alg, 9797c478bd9Sstevel@tonic-gate new_key->dk_key_size, exp)); 9807c478bd9Sstevel@tonic-gate return (dst_free_key(new_key)); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate dnslen = dst_key_to_dnskey(new_key, dns, sizeof(dns)); 9847c478bd9Sstevel@tonic-gate if (dnslen != UNSUPPORTED_KEYALG) 9857c478bd9Sstevel@tonic-gate new_key->dk_id = dst_s_dns_key_id(dns, dnslen); 9867c478bd9Sstevel@tonic-gate else 9877c478bd9Sstevel@tonic-gate new_key->dk_id = 0; 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate return (new_key); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 992*9525b14bSRao Shoaib /*% 9937c478bd9Sstevel@tonic-gate * Release all data structures pointed to by a key structure. 994*9525b14bSRao Shoaib * 9957c478bd9Sstevel@tonic-gate * Parameters 996*9525b14bSRao Shoaib *\li f_key Key structure to be freed. 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate DST_KEY * 10007c478bd9Sstevel@tonic-gate dst_free_key(DST_KEY *f_key) 10017c478bd9Sstevel@tonic-gate { 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if (f_key == NULL) 10047c478bd9Sstevel@tonic-gate return (f_key); 10057c478bd9Sstevel@tonic-gate if (f_key->dk_func && f_key->dk_func->destroy) 10067c478bd9Sstevel@tonic-gate f_key->dk_KEY_struct = 10077c478bd9Sstevel@tonic-gate f_key->dk_func->destroy(f_key->dk_KEY_struct); 10087c478bd9Sstevel@tonic-gate else { 10097c478bd9Sstevel@tonic-gate EREPORT(("dst_free_key(): Unknown key alg %d\n", 10107c478bd9Sstevel@tonic-gate f_key->dk_alg)); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate if (f_key->dk_KEY_struct) { 10137c478bd9Sstevel@tonic-gate free(f_key->dk_KEY_struct); 10147c478bd9Sstevel@tonic-gate f_key->dk_KEY_struct = NULL; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate if (f_key->dk_key_name) 10177c478bd9Sstevel@tonic-gate SAFE_FREE(f_key->dk_key_name); 10187c478bd9Sstevel@tonic-gate SAFE_FREE(f_key); 10197c478bd9Sstevel@tonic-gate return (NULL); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 1022*9525b14bSRao Shoaib /*% 10237c478bd9Sstevel@tonic-gate * Return the maximim size of signature from the key specified in bytes 1024*9525b14bSRao Shoaib * 10257c478bd9Sstevel@tonic-gate * Parameters 1026*9525b14bSRao Shoaib *\li key 1027*9525b14bSRao Shoaib * 10287c478bd9Sstevel@tonic-gate * Returns 1029*9525b14bSRao Shoaib * \li bytes 10307c478bd9Sstevel@tonic-gate */ 10317c478bd9Sstevel@tonic-gate int 10327c478bd9Sstevel@tonic-gate dst_sig_size(DST_KEY *key) { 10337c478bd9Sstevel@tonic-gate switch (key->dk_alg) { 10347c478bd9Sstevel@tonic-gate case KEY_HMAC_MD5: 10357c478bd9Sstevel@tonic-gate return (16); 10367c478bd9Sstevel@tonic-gate case KEY_HMAC_SHA1: 10377c478bd9Sstevel@tonic-gate return (20); 10387c478bd9Sstevel@tonic-gate case KEY_RSA: 10397c478bd9Sstevel@tonic-gate return (key->dk_key_size + 7) / 8; 10407c478bd9Sstevel@tonic-gate case KEY_DSA: 10417c478bd9Sstevel@tonic-gate return (40); 10427c478bd9Sstevel@tonic-gate default: 10437c478bd9Sstevel@tonic-gate EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); 10447c478bd9Sstevel@tonic-gate return -1; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate 1048*9525b14bSRao Shoaib /*! \file */ 1049