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