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