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