1 /* 2 * Program to generate cryptographic keys for NTP clients and servers 3 * 4 * This program generates files "ntpkey_<type>_<hostname>.<filestamp>", 5 * where <type> is the file type, <hostname> is the generating host and 6 * <filestamp> is the NTP seconds in decimal format. The NTP programs 7 * expect generic names such as "ntpkey_<type>_whimsy.udel.edu" with the 8 * association maintained by soft links. 9 * 10 * Files are prefixed with a header giving the name and date of creation 11 * followed by a type-specific descriptive label and PEM-encoded data 12 * string compatible with programs of the OpenSSL library. 13 * 14 * Note that private keys can be password encrypted as per OpenSSL 15 * conventions. 16 * 17 * The file types include 18 * 19 * ntpkey_MD5key_<hostname>.<filestamp> 20 * MD5 (128-bit) keys used to compute message digests in symmetric 21 * key cryptography 22 * 23 * ntpkey_RSAkey_<hostname>.<filestamp> 24 * ntpkey_host_<hostname> (RSA) link 25 * RSA private/public host key pair used for public key signatures 26 * and data encryption 27 * 28 * ntpkey_DSAkey_<hostname>.<filestamp> 29 * ntpkey_sign_<hostname> (RSA or DSA) link 30 * DSA private/public sign key pair used for public key signatures, 31 * but not data encryption 32 * 33 * ntpkey_IFFpar_<hostname>.<filestamp> 34 * ntpkey_iff_<hostname> (IFF server/client) link 35 * ntpkey_iffkey_<hostname> (IFF client) link 36 * Schnorr (IFF) server/client identity parameters 37 * 38 * ntpkey_IFFkey_<hostname>.<filestamp> 39 * Schnorr (IFF) client identity parameters 40 * 41 * ntpkey_GQpar_<hostname>.<filestamp>, 42 * ntpkey_gq_<hostname> (GQ) link 43 * Guillou-Quisquater (GQ) identity parameters 44 * 45 * ntpkey_MVpar_<hostname>.<filestamp>, 46 * Mu-Varadharajan (MV) server identity parameters 47 * 48 * ntpkey_MVkeyX_<hostname>.<filestamp>, 49 * ntpkey_mv_<hostname> (MV server) link 50 * ntpkey_mvkey_<hostname> (MV client) link 51 * Mu-Varadharajan (MV) client identity parameters 52 * 53 * ntpkey_XXXcert_<hostname>.<filestamp> 54 * ntpkey_cert_<hostname> (RSA or DSA) link 55 * X509v3 certificate using RSA or DSA public keys and signatures. 56 * XXX is a code identifying the message digest and signature 57 * encryption algorithm 58 * 59 * Available digest/signature schemes 60 * 61 * RSA: RSA-MD2, RSA-MD5, RSA-SHA, RSA-SHA1, RSA-MDC2, EVP-RIPEMD160 62 * DSA: DSA-SHA, DSA-SHA1 63 * 64 * Note: Once in a while because of some statistical fluke this program 65 * fails to generate and verify some cryptographic data, as indicated by 66 * exit status -1. In this case simply run the program again. If the 67 * program does complete with return code 0, the data are correct as 68 * verified. 69 * 70 * These cryptographic routines are characterized by the prime modulus 71 * size in bits. The default value of 512 bits is a compromise between 72 * cryptographic strength and computing time and is ordinarily 73 * considered adequate for this application. The routines have been 74 * tested with sizes of 256, 512, 1024 and 2048 bits. Not all message 75 * digest and signature encryption schemes work with sizes less than 512 76 * bits. The computing time for sizes greater than 2048 bits is 77 * prohibitive on all but the fastest processors. An UltraSPARC Blade 78 * 1000 took something over nine minutes to generate and verify the 79 * values with size 2048. An old SPARC IPC would take a week. 80 * 81 * The OpenSSL library used by this program expects a random seed file. 82 * As described in the OpenSSL documentation, the file name defaults to 83 * first the RANDFILE environment variable in the user's home directory 84 * and then .rnd in the user's home directory. 85 */ 86 #ifdef HAVE_CONFIG_H 87 # include <config.h> 88 #endif 89 #include <string.h> 90 #include <stdio.h> 91 #include <stdlib.h> 92 #include <unistd.h> 93 #include <sys/stat.h> 94 #include <sys/time.h> 95 #if HAVE_SYS_TYPES_H 96 # include <sys/types.h> 97 #endif 98 #include "ntp_types.h" 99 #include "l_stdlib.h" 100 101 #ifdef SYS_WINNT 102 extern int ntp_getopt P((int, char **, const char *)); 103 #define getopt ntp_getopt 104 #define optarg ntp_optarg 105 #endif 106 107 #ifdef OPENSSL 108 #include "openssl/bn.h" 109 #include "openssl/evp.h" 110 #include "openssl/err.h" 111 #include "openssl/rand.h" 112 #include "openssl/pem.h" 113 #include "openssl/x509v3.h" 114 #include <openssl/objects.h> 115 #endif /* OPENSSL */ 116 117 /* 118 * Cryptodefines 119 */ 120 #define MD5KEYS 16 /* number of MD5 keys generated */ 121 #define JAN_1970 ULONG_CONST(2208988800) /* NTP seconds */ 122 #define YEAR ((long)60*60*24*365) /* one year in seconds */ 123 #define MAXFILENAME 256 /* max file name length */ 124 #define MAXHOSTNAME 256 /* max host name length */ 125 #ifdef OPENSSL 126 #define PLEN 512 /* default prime modulus size (bits) */ 127 128 /* 129 * Strings used in X509v3 extension fields 130 */ 131 #define KEY_USAGE "digitalSignature,keyCertSign" 132 #define BASIC_CONSTRAINTS "critical,CA:TRUE" 133 #define EXT_KEY_PRIVATE "private" 134 #define EXT_KEY_TRUST "trustRoot" 135 #endif /* OPENSSL */ 136 137 /* 138 * Prototypes 139 */ 140 FILE *fheader P((const char *, const char *)); 141 void fslink P((const char *, const char *)); 142 int gen_md5 P((char *)); 143 #ifdef OPENSSL 144 EVP_PKEY *gen_rsa P((char *)); 145 EVP_PKEY *gen_dsa P((char *)); 146 EVP_PKEY *gen_iff P((char *)); 147 EVP_PKEY *gen_gqpar P((char *)); 148 EVP_PKEY *gen_gqkey P((char *, EVP_PKEY *)); 149 EVP_PKEY *gen_mv P((char *)); 150 int x509 P((EVP_PKEY *, const EVP_MD *, char *, char *)); 151 void cb P((int, int, void *)); 152 EVP_PKEY *genkey P((char *, char *)); 153 u_long asn2ntp P((ASN1_TIME *)); 154 #endif /* OPENSSL */ 155 156 /* 157 * Program variables 158 */ 159 extern char *optarg; /* command line argument */ 160 int debug = 0; /* debug, not de bug */ 161 int rval; /* return status */ 162 #ifdef OPENSSL 163 u_int modulus = PLEN; /* prime modulus size (bits) */ 164 #endif 165 int nkeys = 0; /* MV keys */ 166 time_t epoch; /* Unix epoch (seconds) since 1970 */ 167 char *hostname; /* host name (subject name) */ 168 char *trustname; /* trusted host name (issuer name) */ 169 char filename[MAXFILENAME + 1]; /* file name */ 170 char *passwd1 = NULL; /* input private key password */ 171 char *passwd2 = NULL; /* output private key password */ 172 #ifdef OPENSSL 173 long d0, d1, d2, d3; /* callback counters */ 174 #endif /* OPENSSL */ 175 176 #ifdef SYS_WINNT 177 BOOL init_randfile(); 178 179 /* 180 * Don't try to follow symbolic links 181 */ 182 int 183 readlink(char * link, char * file, int len) { 184 return (-1); 185 } 186 /* 187 * Don't try to create a symbolic link for now. 188 * Just move the file to the name you need. 189 */ 190 int 191 symlink(char *filename, char *linkname) { 192 DeleteFile(linkname); 193 MoveFile(filename, linkname); 194 return 0; 195 } 196 void 197 InitWin32Sockets() { 198 WORD wVersionRequested; 199 WSADATA wsaData; 200 wVersionRequested = MAKEWORD(2,0); 201 if (WSAStartup(wVersionRequested, &wsaData)) 202 { 203 fprintf(stderr, "No useable winsock.dll"); 204 exit(1); 205 } 206 } 207 #endif /* SYS_WINNT */ 208 209 /* 210 * Main program 211 */ 212 int 213 main( 214 int argc, /* command line options */ 215 char **argv 216 ) 217 { 218 struct timeval tv; /* initialization vector */ 219 #ifdef OPENSSL 220 X509 *cert = NULL; /* X509 certificate */ 221 EVP_PKEY *pkey_host = NULL; /* host key */ 222 EVP_PKEY *pkey_sign = NULL; /* sign key */ 223 EVP_PKEY *pkey_iff = NULL; /* IFF parameters */ 224 EVP_PKEY *pkey_gq = NULL; /* GQ parameters */ 225 EVP_PKEY *pkey_mv = NULL; /* MV parameters */ 226 #endif 227 int md5key = 0; /* generate MD5 keys */ 228 #ifdef OPENSSL 229 int hostkey = 0; /* generate RSA keys */ 230 int iffkey = 0; /* generate IFF parameters */ 231 int gqpar = 0; /* generate GQ parameters */ 232 int gqkey = 0; /* update GQ keys */ 233 int mvpar = 0; /* generate MV parameters */ 234 int mvkey = 0; /* update MV keys */ 235 char *sign = NULL; /* sign key */ 236 EVP_PKEY *pkey = NULL; /* temp key */ 237 const EVP_MD *ectx; /* EVP digest */ 238 char pathbuf[MAXFILENAME + 1]; 239 const char *scheme = NULL; /* digest/signature scheme */ 240 char *exten = NULL; /* private extension */ 241 char *grpkey = NULL; /* identity extension */ 242 int nid; /* X509 digest/signature scheme */ 243 FILE *fstr = NULL; /* file handle */ 244 int iffsw = 0; /* IFF key switch */ 245 #endif /* OPENSSL */ 246 char hostbuf[MAXHOSTNAME + 1]; 247 u_int temp; 248 249 #ifdef SYS_WINNT 250 /* Initialize before OpenSSL checks */ 251 InitWin32Sockets(); 252 if(!init_randfile()) 253 fprintf(stderr, "Unable to initialize .rnd file\n"); 254 #endif 255 256 #ifdef OPENSSL 257 if (SSLeay() != OPENSSL_VERSION_NUMBER) { 258 fprintf(stderr, 259 "OpenSSL version mismatch. Built against %lx, you have %lx\n", 260 OPENSSL_VERSION_NUMBER, SSLeay()); 261 return (-1); 262 263 } else { 264 fprintf(stderr, 265 "Using OpenSSL version %lx\n", SSLeay()); 266 } 267 #endif /* OPENSSL */ 268 269 /* 270 * Process options, initialize host name and timestamp. 271 */ 272 gethostname(hostbuf, MAXHOSTNAME); 273 hostname = hostbuf; 274 #ifdef OPENSSL 275 trustname = hostbuf; 276 passwd1 = hostbuf; 277 #endif 278 #ifndef SYS_WINNT 279 gettimeofday(&tv, 0); 280 #else 281 gettimeofday(&tv); 282 #endif 283 epoch = tv.tv_sec; 284 rval = 0; 285 while ((temp = getopt(argc, argv, 286 #ifdef OPENSSL 287 "c:deGgHIi:Mm:nPp:q:S:s:TV:v:" 288 #else 289 "dM" 290 #endif 291 )) != -1) { 292 switch(temp) { 293 294 #ifdef OPENSSL 295 /* 296 * -c select public certificate type 297 */ 298 case 'c': 299 scheme = optarg; 300 continue; 301 #endif 302 303 /* 304 * -d debug 305 */ 306 case 'd': 307 debug++; 308 continue; 309 310 #ifdef OPENSSL 311 /* 312 * -e write identity keys 313 */ 314 case 'e': 315 iffsw++; 316 continue; 317 #endif 318 319 #ifdef OPENSSL 320 /* 321 * -G generate GQ parameters and keys 322 */ 323 case 'G': 324 gqpar++; 325 continue; 326 #endif 327 328 #ifdef OPENSSL 329 /* 330 * -g update GQ keys 331 */ 332 case 'g': 333 gqkey++; 334 continue; 335 #endif 336 337 #ifdef OPENSSL 338 /* 339 * -H generate host key (RSA) 340 */ 341 case 'H': 342 hostkey++; 343 continue; 344 #endif 345 346 #ifdef OPENSSL 347 /* 348 * -I generate IFF parameters 349 */ 350 case 'I': 351 iffkey++; 352 continue; 353 #endif 354 355 #ifdef OPENSSL 356 /* 357 * -i set issuer name 358 */ 359 case 'i': 360 trustname = optarg; 361 continue; 362 #endif 363 364 /* 365 * -M generate MD5 keys 366 */ 367 case 'M': 368 md5key++; 369 continue; 370 371 #ifdef OPENSSL 372 /* 373 * -m select modulus (256-2048) 374 */ 375 case 'm': 376 if (sscanf(optarg, "%d", &modulus) != 1) 377 fprintf(stderr, 378 "invalid option -m %s\n", optarg); 379 continue; 380 #endif 381 382 #ifdef OPENSSL 383 /* 384 * -P generate PC private certificate 385 */ 386 case 'P': 387 exten = EXT_KEY_PRIVATE; 388 continue; 389 #endif 390 391 #ifdef OPENSSL 392 /* 393 * -p output private key password 394 */ 395 case 'p': 396 passwd2 = optarg; 397 continue; 398 #endif 399 400 #ifdef OPENSSL 401 /* 402 * -q input private key password 403 */ 404 case 'q': 405 passwd1 = optarg; 406 continue; 407 #endif 408 409 #ifdef OPENSSL 410 /* 411 * -S generate sign key (RSA or DSA) 412 */ 413 case 'S': 414 sign = optarg; 415 continue; 416 #endif 417 418 #ifdef OPENSSL 419 /* 420 * -s set subject name 421 */ 422 case 's': 423 hostname = optarg; 424 continue; 425 #endif 426 427 #ifdef OPENSSL 428 /* 429 * -T trusted certificate (TC scheme) 430 */ 431 case 'T': 432 exten = EXT_KEY_TRUST; 433 continue; 434 #endif 435 436 #ifdef OPENSSL 437 /* 438 * -V <keys> generate MV parameters 439 */ 440 case 'V': 441 mvpar++; 442 if (sscanf(optarg, "%d", &nkeys) != 1) 443 fprintf(stderr, 444 "invalid option -V %s\n", optarg); 445 continue; 446 #endif 447 448 #ifdef OPENSSL 449 /* 450 * -v <key> update MV keys 451 */ 452 case 'v': 453 mvkey++; 454 if (sscanf(optarg, "%d", &nkeys) != 1) 455 fprintf(stderr, 456 "invalid option -v %s\n", optarg); 457 continue; 458 #endif 459 460 /* 461 * None of the above. 462 */ 463 default: 464 fprintf(stderr, "Option ignored\n"); 465 continue; 466 } 467 } 468 469 if (passwd1 != NULL && passwd2 == NULL) 470 passwd2 = passwd1; 471 #ifdef OPENSSL 472 /* 473 * Seed random number generator and grow weeds. 474 */ 475 ERR_load_crypto_strings(); 476 OpenSSL_add_all_algorithms(); 477 if (RAND_file_name(pathbuf, MAXFILENAME) == NULL) { 478 fprintf(stderr, "RAND_file_name %s\n", 479 ERR_error_string(ERR_get_error(), NULL)); 480 return (-1); 481 } 482 temp = RAND_load_file(pathbuf, -1); 483 if (temp == 0) { 484 fprintf(stderr, 485 "RAND_load_file %s not found or empty\n", pathbuf); 486 return (-1); 487 } 488 fprintf(stderr, 489 "Random seed file %s %u bytes\n", pathbuf, temp); 490 RAND_add(&epoch, sizeof(epoch), 4.0); 491 #endif 492 493 /* 494 * Generate new parameters and keys as requested. These replace 495 * any values already generated. 496 */ 497 if (md5key) 498 gen_md5("MD5"); 499 #ifdef OPENSSL 500 if (hostkey) 501 pkey_host = genkey("RSA", "host"); 502 if (sign != NULL) 503 pkey_sign = genkey(sign, "sign"); 504 if (iffkey) 505 pkey_iff = gen_iff("iff"); 506 if (gqpar) 507 pkey_gq = gen_gqpar("gq"); 508 if (mvpar) 509 pkey_mv = gen_mv("mv"); 510 511 /* 512 * If there is no new host key, look for an existing one. If not 513 * found, create it. 514 */ 515 while (pkey_host == NULL && rval == 0 && !iffsw) { 516 sprintf(filename, "ntpkey_host_%s", hostname); 517 if ((fstr = fopen(filename, "r")) != NULL) { 518 pkey_host = PEM_read_PrivateKey(fstr, NULL, 519 NULL, passwd1); 520 fclose(fstr); 521 readlink(filename, filename, sizeof(filename)); 522 if (pkey_host == NULL) { 523 fprintf(stderr, "Host key\n%s\n", 524 ERR_error_string(ERR_get_error(), 525 NULL)); 526 rval = -1; 527 } else { 528 fprintf(stderr, 529 "Using host key %s\n", filename); 530 } 531 break; 532 533 } else if ((pkey_host = genkey("RSA", "host")) == 534 NULL) { 535 rval = -1; 536 break; 537 } 538 } 539 540 /* 541 * If there is no new sign key, look for an existing one. If not 542 * found, use the host key instead. 543 */ 544 pkey = pkey_sign; 545 while (pkey_sign == NULL && rval == 0 && !iffsw) { 546 sprintf(filename, "ntpkey_sign_%s", hostname); 547 if ((fstr = fopen(filename, "r")) != NULL) { 548 pkey_sign = PEM_read_PrivateKey(fstr, NULL, 549 NULL, passwd1); 550 fclose(fstr); 551 readlink(filename, filename, sizeof(filename)); 552 if (pkey_sign == NULL) { 553 fprintf(stderr, "Sign key\n%s\n", 554 ERR_error_string(ERR_get_error(), 555 NULL)); 556 rval = -1; 557 } else { 558 fprintf(stderr, "Using sign key %s\n", 559 filename); 560 } 561 break; 562 } else { 563 pkey = pkey_host; 564 fprintf(stderr, "Using host key as sign key\n"); 565 break; 566 } 567 } 568 569 /* 570 * If there is no new IFF file, look for an existing one. 571 */ 572 if (pkey_iff == NULL && rval == 0) { 573 sprintf(filename, "ntpkey_iff_%s", hostname); 574 if ((fstr = fopen(filename, "r")) != NULL) { 575 pkey_iff = PEM_read_PrivateKey(fstr, NULL, 576 NULL, passwd1); 577 fclose(fstr); 578 readlink(filename, filename, sizeof(filename)); 579 if (pkey_iff == NULL) { 580 fprintf(stderr, "IFF parameters\n%s\n", 581 ERR_error_string(ERR_get_error(), 582 NULL)); 583 rval = -1; 584 } else { 585 fprintf(stderr, 586 "Using IFF parameters %s\n", 587 filename); 588 } 589 } 590 } 591 592 /* 593 * If there is no new GQ file, look for an existing one. 594 */ 595 if (pkey_gq == NULL && rval == 0 && !iffsw) { 596 sprintf(filename, "ntpkey_gq_%s", hostname); 597 if ((fstr = fopen(filename, "r")) != NULL) { 598 pkey_gq = PEM_read_PrivateKey(fstr, NULL, NULL, 599 passwd1); 600 fclose(fstr); 601 readlink(filename, filename, sizeof(filename)); 602 if (pkey_gq == NULL) { 603 fprintf(stderr, "GQ parameters\n%s\n", 604 ERR_error_string(ERR_get_error(), 605 NULL)); 606 rval = -1; 607 } else { 608 fprintf(stderr, 609 "Using GQ parameters %s\n", 610 filename); 611 } 612 } 613 } 614 615 /* 616 * If there is a GQ parameter file, create GQ private/public 617 * keys and extract the public key for the certificate. 618 */ 619 if (pkey_gq != NULL && rval == 0) { 620 gen_gqkey("gq", pkey_gq); 621 grpkey = BN_bn2hex(pkey_gq->pkey.rsa->q); 622 } 623 624 /* 625 * Generate a X509v3 certificate. 626 */ 627 while (scheme == NULL && rval == 0 && !iffsw) { 628 sprintf(filename, "ntpkey_cert_%s", hostname); 629 if ((fstr = fopen(filename, "r")) != NULL) { 630 cert = PEM_read_X509(fstr, NULL, NULL, NULL); 631 fclose(fstr); 632 readlink(filename, filename, sizeof(filename)); 633 if (cert == NULL) { 634 fprintf(stderr, "Cert \n%s\n", 635 ERR_error_string(ERR_get_error(), 636 NULL)); 637 rval = -1; 638 } else { 639 nid = OBJ_obj2nid( 640 cert->cert_info->signature->algorithm); 641 scheme = OBJ_nid2sn(nid); 642 fprintf(stderr, 643 "Using scheme %s from %s\n", scheme, 644 filename); 645 break; 646 } 647 } 648 scheme = "RSA-MD5"; 649 } 650 if (pkey != NULL && rval == 0 && !iffsw) { 651 ectx = EVP_get_digestbyname(scheme); 652 if (ectx == NULL) { 653 fprintf(stderr, 654 "Invalid digest/signature combination %s\n", 655 scheme); 656 rval = -1; 657 } else { 658 x509(pkey, ectx, grpkey, exten); 659 } 660 } 661 662 /* 663 * Write the IFF client parameters and keys as a DSA private key 664 * encoded in PEM. Note the private key is obscured. 665 */ 666 if (pkey_iff != NULL && rval == 0 && iffsw) { 667 DSA *dsa; 668 char *sptr; 669 670 sptr = strrchr(filename, '.'); 671 sprintf(filename, "ntpkey_IFFkey_%s.%s", trustname, 672 ++sptr); 673 fprintf(stderr, "Writing new IFF key %s\n", filename); 674 fprintf(stdout, "# %s\n# %s", filename, ctime(&epoch)); 675 dsa = pkey_iff->pkey.dsa; 676 BN_copy(dsa->priv_key, BN_value_one()); 677 pkey = EVP_PKEY_new(); 678 EVP_PKEY_assign_DSA(pkey, dsa); 679 PEM_write_PrivateKey(stdout, pkey, passwd2 ? 680 EVP_des_cbc() : NULL, NULL, 0, NULL, passwd2); 681 fclose(stdout); 682 if (debug) 683 DSA_print_fp(stdout, dsa, 0); 684 } 685 686 /* 687 * Return the marbles. 688 */ 689 if (grpkey != NULL) 690 OPENSSL_free(grpkey); 691 if (pkey_host != NULL) 692 EVP_PKEY_free(pkey_host); 693 if (pkey_sign != NULL) 694 EVP_PKEY_free(pkey_sign); 695 if (pkey_iff != NULL) 696 EVP_PKEY_free(pkey_iff); 697 if (pkey_gq != NULL) 698 EVP_PKEY_free(pkey_gq); 699 if (pkey_mv != NULL) 700 EVP_PKEY_free(pkey_mv); 701 #endif /* OPENSSL */ 702 return (rval); 703 } 704 705 706 #if 0 707 /* 708 * Generate random MD5 key with password. 709 */ 710 int 711 gen_md5( 712 char *id /* file name id */ 713 ) 714 { 715 BIGNUM *key; 716 BIGNUM *keyid; 717 FILE *str; 718 u_char bin[16]; 719 720 fprintf(stderr, "Generating MD5 keys...\n"); 721 str = fheader("MD5key", hostname); 722 keyid = BN_new(); key = BN_new(); 723 BN_rand(keyid, 16, -1, 0); 724 BN_rand(key, 128, -1, 0); 725 BN_bn2bin(key, bin); 726 PEM_write_fp(str, MD5, NULL, bin); 727 fclose(str); 728 fslink(id, hostname); 729 return (1); 730 } 731 732 733 #else 734 /* 735 * Generate semi-random MD5 keys compatible with NTPv3 and NTPv4 736 */ 737 int 738 gen_md5( 739 char *id /* file name id */ 740 ) 741 { 742 u_char md5key[16]; /* MD5 key */ 743 FILE *str; 744 u_int temp = 0; /* Initialize to prevent warnings during compile */ 745 int i, j; 746 747 fprintf(stderr, "Generating MD5 keys...\n"); 748 str = fheader("MD5key", hostname); 749 srandom(epoch); 750 for (i = 1; i <= MD5KEYS; i++) { 751 for (j = 0; j < 16; j++) { 752 while (1) { 753 temp = random() & 0xff; 754 if (temp == '#') 755 continue; 756 if (temp > 0x20 && temp < 0x7f) 757 break; 758 } 759 md5key[j] = (u_char)temp; 760 } 761 md5key[15] = '\0'; 762 fprintf(str, "%2d MD5 %16s # MD5 key\n", i, 763 md5key); 764 } 765 fclose(str); 766 fslink(id, hostname); 767 return (1); 768 } 769 #endif /* OPENSSL */ 770 771 772 #ifdef OPENSSL 773 /* 774 * Generate RSA public/private key pair 775 */ 776 EVP_PKEY * /* public/private key pair */ 777 gen_rsa( 778 char *id /* file name id */ 779 ) 780 { 781 EVP_PKEY *pkey; /* private key */ 782 RSA *rsa; /* RSA parameters and key pair */ 783 FILE *str; 784 785 fprintf(stderr, "Generating RSA keys (%d bits)...\n", modulus); 786 rsa = RSA_generate_key(modulus, 3, cb, "RSA"); 787 fprintf(stderr, "\n"); 788 if (rsa == NULL) { 789 fprintf(stderr, "RSA generate keys fails\n%s\n", 790 ERR_error_string(ERR_get_error(), NULL)); 791 rval = -1; 792 return (NULL); 793 } 794 795 /* 796 * For signature encryption it is not necessary that the RSA 797 * parameters be strictly groomed and once in a while the 798 * modulus turns out to be non-prime. Just for grins, we check 799 * the primality. 800 */ 801 if (!RSA_check_key(rsa)) { 802 fprintf(stderr, "Invalid RSA key\n%s\n", 803 ERR_error_string(ERR_get_error(), NULL)); 804 RSA_free(rsa); 805 rval = -1; 806 return (NULL); 807 } 808 809 /* 810 * Write the RSA parameters and keys as a RSA private key 811 * encoded in PEM. 812 */ 813 str = fheader("RSAkey", hostname); 814 pkey = EVP_PKEY_new(); 815 EVP_PKEY_assign_RSA(pkey, rsa); 816 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 817 NULL, 0, NULL, passwd2); 818 fclose(str); 819 if (debug) 820 RSA_print_fp(stdout, rsa, 0); 821 fslink(id, hostname); 822 return (pkey); 823 } 824 825 826 /* 827 * Generate DSA public/private key pair 828 */ 829 EVP_PKEY * /* public/private key pair */ 830 gen_dsa( 831 char *id /* file name id */ 832 ) 833 { 834 EVP_PKEY *pkey; /* private key */ 835 DSA *dsa; /* DSA parameters */ 836 u_char seed[20]; /* seed for parameters */ 837 FILE *str; 838 839 /* 840 * Generate DSA parameters. 841 */ 842 fprintf(stderr, 843 "Generating DSA parameters (%d bits)...\n", modulus); 844 RAND_bytes(seed, sizeof(seed)); 845 dsa = DSA_generate_parameters(modulus, seed, sizeof(seed), NULL, 846 NULL, cb, "DSA"); 847 fprintf(stderr, "\n"); 848 if (dsa == NULL) { 849 fprintf(stderr, "DSA generate parameters fails\n%s\n", 850 ERR_error_string(ERR_get_error(), NULL)); 851 rval = -1; 852 return (NULL); 853 } 854 855 /* 856 * Generate DSA keys. 857 */ 858 fprintf(stderr, "Generating DSA keys (%d bits)...\n", modulus); 859 if (!DSA_generate_key(dsa)) { 860 fprintf(stderr, "DSA generate keys fails\n%s\n", 861 ERR_error_string(ERR_get_error(), NULL)); 862 DSA_free(dsa); 863 rval = -1; 864 return (NULL); 865 } 866 867 /* 868 * Write the DSA parameters and keys as a DSA private key 869 * encoded in PEM. 870 */ 871 str = fheader("DSAkey", hostname); 872 pkey = EVP_PKEY_new(); 873 EVP_PKEY_assign_DSA(pkey, dsa); 874 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 875 NULL, 0, NULL, passwd2); 876 fclose(str); 877 if (debug) 878 DSA_print_fp(stdout, dsa, 0); 879 fslink(id, hostname); 880 return (pkey); 881 } 882 883 884 /* 885 * Generate Schnorr (IFF) parameters and keys 886 * 887 * The Schnorr (IFF)identity scheme is intended for use when 888 * certificates are generated by some other trusted certificate 889 * authority and the parameters cannot be conveyed in the certificate 890 * itself. For this purpose, new generations of IFF values must be 891 * securely transmitted to all members of the group before use. There 892 * are two kinds of files: server/client files that include private and 893 * public parameters and client files that include only public 894 * parameters. The scheme is self contained and independent of new 895 * generations of host keys, sign keys and certificates. 896 * 897 * The IFF values hide in a DSA cuckoo structure which uses the same 898 * parameters. The values are used by an identity scheme based on DSA 899 * cryptography and described in Stimson p. 285. The p is a 512-bit 900 * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1 901 * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a 902 * private random group key b (0 < b < q), then computes public 903 * v = g^(q - a). All values except the group key are known to all group 904 * members; the group key is known to the group servers, but not the 905 * group clients. Alice challenges Bob to confirm identity using the 906 * protocol described below. 907 */ 908 EVP_PKEY * /* DSA cuckoo nest */ 909 gen_iff( 910 char *id /* file name id */ 911 ) 912 { 913 EVP_PKEY *pkey; /* private key */ 914 DSA *dsa; /* DSA parameters */ 915 u_char seed[20]; /* seed for parameters */ 916 BN_CTX *ctx; /* BN working space */ 917 BIGNUM *b, *r, *k, *u, *v, *w; /* BN temp */ 918 FILE *str; 919 u_int temp; 920 921 /* 922 * Generate DSA parameters for use as IFF parameters. 923 */ 924 fprintf(stderr, "Generating IFF parameters (%d bits)...\n", 925 modulus); 926 RAND_bytes(seed, sizeof(seed)); 927 dsa = DSA_generate_parameters(modulus, seed, sizeof(seed), NULL, 928 NULL, cb, "IFF"); 929 fprintf(stderr, "\n"); 930 if (dsa == NULL) { 931 fprintf(stderr, "DSA generate parameters fails\n%s\n", 932 ERR_error_string(ERR_get_error(), NULL)); 933 rval = -1; 934 return (NULL);; 935 } 936 937 /* 938 * Generate the private and public keys. The DSA parameters and 939 * these keys are distributed to all members of the group. 940 */ 941 fprintf(stderr, "Generating IFF keys (%d bits)...\n", modulus); 942 b = BN_new(); r = BN_new(); k = BN_new(); 943 u = BN_new(); v = BN_new(); w = BN_new(); ctx = BN_CTX_new(); 944 BN_rand(b, BN_num_bits(dsa->q), -1, 0); /* a */ 945 BN_mod(b, b, dsa->q, ctx); 946 BN_sub(v, dsa->q, b); 947 BN_mod_exp(v, dsa->g, v, dsa->p, ctx); /* g^(q - b) mod p */ 948 BN_mod_exp(u, dsa->g, b, dsa->p, ctx); /* g^b mod p */ 949 BN_mod_mul(u, u, v, dsa->p, ctx); 950 temp = BN_is_one(u); 951 fprintf(stderr, 952 "Confirm g^(q - b) g^b = 1 mod p: %s\n", temp == 1 ? 953 "yes" : "no"); 954 if (!temp) { 955 BN_free(b); BN_free(r); BN_free(k); 956 BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx); 957 rval = -1; 958 return (NULL); 959 } 960 dsa->priv_key = BN_dup(b); /* private key */ 961 dsa->pub_key = BN_dup(v); /* public key */ 962 963 /* 964 * Here is a trial round of the protocol. First, Alice rolls 965 * random r (0 < r < q) and sends it to Bob. She needs only 966 * modulus q. 967 */ 968 BN_rand(r, BN_num_bits(dsa->q), -1, 0); /* r */ 969 BN_mod(r, r, dsa->q, ctx); 970 971 /* 972 * Bob rolls random k (0 < k < q), computes y = k + b r mod q 973 * and x = g^k mod p, then sends (y, x) to Alice. He needs 974 * moduli p, q and the group key b. 975 */ 976 BN_rand(k, BN_num_bits(dsa->q), -1, 0); /* k, 0 < k < q */ 977 BN_mod(k, k, dsa->q, ctx); 978 BN_mod_mul(v, dsa->priv_key, r, dsa->q, ctx); /* b r mod q */ 979 BN_add(v, v, k); 980 BN_mod(v, v, dsa->q, ctx); /* y = k + b r mod q */ 981 BN_mod_exp(u, dsa->g, k, dsa->p, ctx); /* x = g^k mod p */ 982 983 /* 984 * Alice computes g^y v^r and verifies the result is equal to x. 985 * She needs modulus p, generator g, and the public key v, as 986 * well as her original r. 987 */ 988 BN_mod_exp(v, dsa->g, v, dsa->p, ctx); /* g^y mod p */ 989 BN_mod_exp(w, dsa->pub_key, r, dsa->p, ctx); /* v^r */ 990 BN_mod_mul(v, w, v, dsa->p, ctx); /* product mod p */ 991 temp = BN_cmp(u, v); 992 fprintf(stderr, 993 "Confirm g^k = g^(k + b r) g^(q - b) r: %s\n", temp == 994 0 ? "yes" : "no"); 995 BN_free(b); BN_free(r); BN_free(k); 996 BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx); 997 if (temp != 0) { 998 DSA_free(dsa); 999 rval = -1; 1000 return (NULL); 1001 } 1002 1003 /* 1004 * Write the IFF server parameters and keys as a DSA private key 1005 * encoded in PEM. 1006 * 1007 * p modulus p 1008 * q modulus q 1009 * g generator g 1010 * priv_key b 1011 * public_key v 1012 */ 1013 str = fheader("IFFpar", trustname); 1014 pkey = EVP_PKEY_new(); 1015 EVP_PKEY_assign_DSA(pkey, dsa); 1016 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 1017 NULL, 0, NULL, passwd2); 1018 fclose(str); 1019 if (debug) 1020 DSA_print_fp(stdout, dsa, 0); 1021 fslink(id, trustname); 1022 return (pkey); 1023 } 1024 1025 1026 /* 1027 * Generate Guillou-Quisquater (GQ) parameters and keys 1028 * 1029 * The Guillou-Quisquater (GQ) identity scheme is intended for use when 1030 * the parameters, keys and certificates are generated by this program. 1031 * The scheme uses a certificate extension field do convey the public 1032 * key of a particular group identified by a group key known only to 1033 * members of the group. The scheme is self contained and independent of 1034 * new generations of host keys and sign keys. 1035 * 1036 * The GQ parameters hide in a RSA cuckoo structure which uses the same 1037 * parameters. The values are used by an identity scheme based on RSA 1038 * cryptography and described in Stimson p. 300 (with errors). The 512- 1039 * bit public modulus is n = p q, where p and q are secret large primes. 1040 * The TA rolls private random group key b as RSA exponent. These values 1041 * are known to all group members. 1042 * 1043 * When rolling new certificates, a member recomputes the private and 1044 * public keys. The private key u is a random roll, while the public key 1045 * is the inverse obscured by the group key v = (u^-1)^b. These values 1046 * replace the private and public keys normally generated by the RSA 1047 * scheme. Alice challenges Bob to confirm identity using the protocol 1048 * described below. 1049 */ 1050 EVP_PKEY * /* RSA cuckoo nest */ 1051 gen_gqpar( 1052 char *id /* file name id */ 1053 ) 1054 { 1055 EVP_PKEY *pkey; /* private key */ 1056 RSA *rsa; /* GQ parameters */ 1057 BN_CTX *ctx; /* BN working space */ 1058 FILE *str; 1059 1060 /* 1061 * Generate RSA parameters for use as GQ parameters. 1062 */ 1063 fprintf(stderr, 1064 "Generating GQ parameters (%d bits)...\n", modulus); 1065 rsa = RSA_generate_key(modulus, 3, cb, "GQ"); 1066 fprintf(stderr, "\n"); 1067 if (rsa == NULL) { 1068 fprintf(stderr, "RSA generate keys fails\n%s\n", 1069 ERR_error_string(ERR_get_error(), NULL)); 1070 rval = -1; 1071 return (NULL); 1072 } 1073 1074 /* 1075 * Generate the group key b, which is saved in the e member of 1076 * the RSA structure. These values are distributed to all 1077 * members of the group, but shielded from all other groups. We 1078 * don't use all the parameters, but set the unused ones to a 1079 * small number to minimize the file size. 1080 */ 1081 ctx = BN_CTX_new(); 1082 BN_rand(rsa->e, BN_num_bits(rsa->n), -1, 0); /* b */ 1083 BN_mod(rsa->e, rsa->e, rsa->n, ctx); 1084 BN_copy(rsa->d, BN_value_one()); 1085 BN_copy(rsa->p, BN_value_one()); 1086 BN_copy(rsa->q, BN_value_one()); 1087 BN_copy(rsa->dmp1, BN_value_one()); 1088 BN_copy(rsa->dmq1, BN_value_one()); 1089 BN_copy(rsa->iqmp, BN_value_one()); 1090 1091 /* 1092 * Write the GQ parameters as a RSA private key encoded in PEM. 1093 * The public and private keys are filled in later. 1094 * 1095 * n modulus n 1096 * e group key b 1097 * (remaining values are not used) 1098 */ 1099 str = fheader("GQpar", trustname); 1100 pkey = EVP_PKEY_new(); 1101 EVP_PKEY_assign_RSA(pkey, rsa); 1102 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 1103 NULL, 0, NULL, passwd2); 1104 fclose(str); 1105 if (debug) 1106 RSA_print_fp(stdout, rsa, 0); 1107 fslink(id, trustname); 1108 return (pkey); 1109 } 1110 1111 1112 /* 1113 * Update Guillou-Quisquater (GQ) parameters 1114 */ 1115 EVP_PKEY * /* RSA cuckoo nest */ 1116 gen_gqkey( 1117 char *id, /* file name id */ 1118 EVP_PKEY *gqpar /* GQ parameters */ 1119 ) 1120 { 1121 EVP_PKEY *pkey; /* private key */ 1122 RSA *rsa; /* RSA parameters */ 1123 BN_CTX *ctx; /* BN working space */ 1124 BIGNUM *u, *v, *g, *k, *r, *y; /* BN temps */ 1125 FILE *str; 1126 u_int temp; 1127 1128 /* 1129 * Generate GQ keys. Note that the group key b is the e member 1130 * of 1131 * the GQ parameters. 1132 */ 1133 fprintf(stderr, "Updating GQ keys (%d bits)...\n", modulus); 1134 ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); 1135 g = BN_new(); k = BN_new(); r = BN_new(); y = BN_new(); 1136 1137 /* 1138 * When generating his certificate, Bob rolls random private key 1139 * u. 1140 */ 1141 rsa = gqpar->pkey.rsa; 1142 BN_rand(u, BN_num_bits(rsa->n), -1, 0); /* u */ 1143 BN_mod(u, u, rsa->n, ctx); 1144 BN_mod_inverse(v, u, rsa->n, ctx); /* u^-1 mod n */ 1145 BN_mod_mul(k, v, u, rsa->n, ctx); 1146 1147 /* 1148 * Bob computes public key v = (u^-1)^b, which is saved in an 1149 * extension field on his certificate. We check that u^b v = 1150 * 1 mod n. 1151 */ 1152 BN_mod_exp(v, v, rsa->e, rsa->n, ctx); 1153 BN_mod_exp(g, u, rsa->e, rsa->n, ctx); /* u^b */ 1154 BN_mod_mul(g, g, v, rsa->n, ctx); /* u^b (u^-1)^b */ 1155 temp = BN_is_one(g); 1156 fprintf(stderr, 1157 "Confirm u^b (u^-1)^b = 1 mod n: %s\n", temp ? "yes" : 1158 "no"); 1159 if (!temp) { 1160 BN_free(u); BN_free(v); 1161 BN_free(g); BN_free(k); BN_free(r); BN_free(y); 1162 BN_CTX_free(ctx); 1163 RSA_free(rsa); 1164 rval = -1; 1165 return (NULL); 1166 } 1167 BN_copy(rsa->p, u); /* private key */ 1168 BN_copy(rsa->q, v); /* public key */ 1169 1170 /* 1171 * Here is a trial run of the protocol. First, Alice rolls 1172 * random r (0 < r < n) and sends it to Bob. She needs only 1173 * modulus n from the parameters. 1174 */ 1175 BN_rand(r, BN_num_bits(rsa->n), -1, 0); /* r */ 1176 BN_mod(r, r, rsa->n, ctx); 1177 1178 /* 1179 * Bob rolls random k (0 < k < n), computes y = k u^r mod n and 1180 * g = k^b mod n, then sends (y, g) to Alice. He needs modulus n 1181 * from the parameters and his private key u. 1182 */ 1183 BN_rand(k, BN_num_bits(rsa->n), -1, 0); /* k */ 1184 BN_mod(k, k, rsa->n, ctx); 1185 BN_mod_exp(y, rsa->p, r, rsa->n, ctx); /* u^r mod n */ 1186 BN_mod_mul(y, k, y, rsa->n, ctx); /* y = k u^r mod n */ 1187 BN_mod_exp(g, k, rsa->e, rsa->n, ctx); /* g = k^b mod n */ 1188 1189 /* 1190 * Alice computes v^r y^b mod n and verifies the result is equal 1191 * to g. She needs modulus n, generator g and group key b from 1192 * the parameters and Bob's public key v = (u^-1)^b from his 1193 * certificate. 1194 */ 1195 BN_mod_exp(v, rsa->q, r, rsa->n, ctx); /* v^r mod n */ 1196 BN_mod_exp(y, y, rsa->e, rsa->n, ctx); /* y^b mod n */ 1197 BN_mod_mul(y, v, y, rsa->n, ctx); /* v^r y^b mod n */ 1198 temp = BN_cmp(y, g); 1199 fprintf(stderr, "Confirm g^k = v^r y^b mod n: %s\n", temp == 0 ? 1200 "yes" : "no"); 1201 BN_CTX_free(ctx); BN_free(u); BN_free(v); 1202 BN_free(g); BN_free(k); BN_free(r); BN_free(y); 1203 if (temp != 0) { 1204 RSA_free(rsa); 1205 rval = -1; 1206 return (NULL); 1207 } 1208 1209 /* 1210 * Write the GQ parameters and keys as a RSA private key encoded 1211 * in PEM. 1212 * 1213 * n modulus n 1214 * e group key b 1215 * p private key u 1216 * q public key (u^-1)^b 1217 * (remaining values are not used) 1218 */ 1219 str = fheader("GQpar", trustname); 1220 pkey = EVP_PKEY_new(); 1221 EVP_PKEY_assign_RSA(pkey, rsa); 1222 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 1223 NULL, 0, NULL, passwd2); 1224 fclose(str); 1225 if (debug) 1226 RSA_print_fp(stdout, rsa, 0); 1227 fslink(id, trustname); 1228 return (pkey); 1229 } 1230 1231 1232 /* 1233 * Generate Mu-Varadharajan (MV) parameters and keys 1234 * 1235 * The Mu-Varadharajan (MV) cryptosystem is useful when servers 1236 * broadcast messages to clients, but clients never send messages to 1237 * servers. There is one encryption key for the server and a separate 1238 * decryption key for each client. It operates something like a 1239 * pay-per-view satellite broadcasting system where the session key is 1240 * encrypted by the broadcaster and the decryption keys are held in a 1241 * tamperproof set-top box. We don't use it this way, but read on. 1242 * 1243 * The MV parameters and private encryption key hide in a DSA cuckoo 1244 * structure which uses the same parameters, but generated in a 1245 * different way. The values are used in an encryption scheme similar to 1246 * El Gamal cryptography and a polynomial formed from the expansion of 1247 * product terms (x - x[j]), as described in Mu, Y., and V. 1248 * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001, 1249 * 223-231. The paper has significant errors and serious omissions. 1250 * 1251 * Let q be the product of n distinct primes s'[j] (j = 1...n), where 1252 * each s'[j] has m significant bits. Let p be a prime p = 2 * q + 1, so 1253 * that q and each s'[j] divide p - 1 and p has M = n * m + 1 1254 * significant bits. Let g be a generator of Zp; that is, gcd(g, p - 1) 1255 * = 1 and g^q = 1 mod p. We do modular arithmetic over Zq and then 1256 * project into Zp* as exponents of g. Sometimes we have to compute an 1257 * inverse b^-1 of random b in Zq, but for that purpose we require 1258 * gcd(b, q) = 1. We expect M to be in the 500-bit range and n 1259 * relatively small, like 30. Associated with each s'[j] is an element 1260 * s[j] such that s[j] s'[j] = s'[j] mod q. We find s[j] as the quotient 1261 * (q + s'[j]) / s'[j]. These are the parameters of the scheme and they 1262 * are expensive to compute. 1263 * 1264 * We set up an instance of the scheme as follows. A set of random 1265 * values x[j] mod q (j = 1...n), are generated as the zeros of a 1266 * polynomial of order n. The product terms (x - x[j]) are expanded to 1267 * form coefficients a[i] mod q (i = 0...n) in powers of x. These are 1268 * used as exponents of the generator g mod p to generate the private 1269 * encryption key A. The pair (gbar, ghat) of public server keys and the 1270 * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used 1271 * to construct the decryption keys. The devil is in the details. 1272 * 1273 * This routine generates a private encryption file including the 1274 * private encryption key E and public key (gbar, ghat). It then 1275 * generates decryption files including the private key (xbar[j], 1276 * xhat[j]) for each client. E is a permutation that encrypts a block 1277 * y = E x. The jth client computes the inverse permutation E^-1 = 1278 * gbar^xhat[j] ghat^xbar[j] and decrypts the block x = E^-1 y. 1279 * 1280 * The distinguishing characteristic of this scheme is the capability to 1281 * revoke keys. Included in the calculation of E, gbar and ghat is the 1282 * product s = prod(s'[j]) (j = 1...n) above. If the factor s'[j] is 1283 * subsequently removed from the product and E, gbar and ghat 1284 * recomputed, the jth client will no longer be able to compute E^-1 and 1285 * thus unable to decrypt the block. 1286 */ 1287 EVP_PKEY * /* DSA cuckoo nest */ 1288 gen_mv( 1289 char *id /* file name id */ 1290 ) 1291 { 1292 EVP_PKEY *pkey, *pkey1; /* private key */ 1293 DSA *dsa; /* DSA parameters */ 1294 DSA *sdsa; /* DSA parameters */ 1295 BN_CTX *ctx; /* BN working space */ 1296 BIGNUM **x; /* polynomial zeros vector */ 1297 BIGNUM **a; /* polynomial coefficient vector */ 1298 BIGNUM **g; /* public key vector */ 1299 BIGNUM **s, **s1; /* private enabling keys */ 1300 BIGNUM **xbar, **xhat; /* private keys vector */ 1301 BIGNUM *b; /* group key */ 1302 BIGNUM *b1; /* inverse group key */ 1303 BIGNUM *ss; /* enabling key */ 1304 BIGNUM *biga; /* master encryption key */ 1305 BIGNUM *bige; /* session encryption key */ 1306 BIGNUM *gbar, *ghat; /* public key */ 1307 BIGNUM *u, *v, *w; /* BN scratch */ 1308 int i, j, n; 1309 FILE *str; 1310 u_int temp; 1311 char ident[20]; 1312 1313 /* 1314 * Generate MV parameters. 1315 * 1316 * The object is to generate a multiplicative group Zp* modulo a 1317 * prime p and a subset Zq mod q, where q is the product of n 1318 * distinct primes s'[j] (j = 1...n) and q divides p - 1. We 1319 * first generate n distinct primes, which may have to be 1320 * regenerated later. As a practical matter, it is tough to find 1321 * more than 31 distinct primes for modulus 512 or 61 primes for 1322 * modulus 1024. The latter can take several hundred iterations 1323 * and several minutes on a Sun Blade 1000. 1324 */ 1325 n = nkeys; 1326 fprintf(stderr, 1327 "Generating MV parameters for %d keys (%d bits)...\n", n, 1328 modulus / n); 1329 ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); w = BN_new(); 1330 b = BN_new(); b1 = BN_new(); 1331 dsa = DSA_new(); 1332 dsa->p = BN_new(); 1333 dsa->q = BN_new(); 1334 dsa->g = BN_new(); 1335 s = malloc((n + 1) * sizeof(BIGNUM)); 1336 s1 = malloc((n + 1) * sizeof(BIGNUM)); 1337 for (j = 1; j <= n; j++) 1338 s1[j] = BN_new(); 1339 temp = 0; 1340 for (j = 1; j <= n; j++) { 1341 while (1) { 1342 fprintf(stderr, "Birthdays %d\r", temp); 1343 BN_generate_prime(s1[j], modulus / n, 0, NULL, 1344 NULL, NULL, NULL); 1345 for (i = 1; i < j; i++) { 1346 if (BN_cmp(s1[i], s1[j]) == 0) 1347 break; 1348 } 1349 if (i == j) 1350 break; 1351 temp++; 1352 } 1353 } 1354 fprintf(stderr, "Birthday keys rejected %d\n", temp); 1355 1356 /* 1357 * Compute the modulus q as the product of the primes. Compute 1358 * the modulus p as 2 * q + 1 and test p for primality. If p 1359 * is composite, replace one of the primes with a new distinct 1360 * one and try again. Note that q will hardly be a secret since 1361 * we have to reveal p to servers and clients. However, 1362 * factoring q to find the primes should be adequately hard, as 1363 * this is the same problem considered hard in RSA. Question: is 1364 * it as hard to find n small prime factors totalling n bits as 1365 * it is to find two large prime factors totalling n bits? 1366 * Remember, the bad guy doesn't know n. 1367 */ 1368 temp = 0; 1369 while (1) { 1370 fprintf(stderr, "Duplicate keys rejected %d\r", ++temp); 1371 BN_one(dsa->q); 1372 for (j = 1; j <= n; j++) 1373 BN_mul(dsa->q, dsa->q, s1[j], ctx); 1374 BN_copy(dsa->p, dsa->q); 1375 BN_add(dsa->p, dsa->p, dsa->p); 1376 BN_add_word(dsa->p, 1); 1377 if (BN_is_prime(dsa->p, BN_prime_checks, NULL, ctx, 1378 NULL)) 1379 break; 1380 1381 j = temp % n + 1; 1382 while (1) { 1383 BN_generate_prime(u, modulus / n, 0, 0, NULL, 1384 NULL, NULL); 1385 for (i = 1; i <= n; i++) { 1386 if (BN_cmp(u, s1[i]) == 0) 1387 break; 1388 } 1389 if (i > n) 1390 break; 1391 } 1392 BN_copy(s1[j], u); 1393 } 1394 fprintf(stderr, "Duplicate keys rejected %d\n", temp); 1395 1396 /* 1397 * Compute the generator g using a random roll such that 1398 * gcd(g, p - 1) = 1 and g^q = 1. This is a generator of p, not 1399 * q. 1400 */ 1401 BN_copy(v, dsa->p); 1402 BN_sub_word(v, 1); 1403 while (1) { 1404 BN_rand(dsa->g, BN_num_bits(dsa->p) - 1, 0, 0); 1405 BN_mod(dsa->g, dsa->g, dsa->p, ctx); 1406 BN_gcd(u, dsa->g, v, ctx); 1407 if (!BN_is_one(u)) 1408 continue; 1409 1410 BN_mod_exp(u, dsa->g, dsa->q, dsa->p, ctx); 1411 if (BN_is_one(u)) 1412 break; 1413 } 1414 1415 /* 1416 * Compute s[j] such that s[j] * s'[j] = s'[j] for all j. The 1417 * easy way to do this is to compute q + s'[j] and divide the 1418 * result by s'[j]. Exercise for the student: prove the 1419 * remainder is always zero. 1420 */ 1421 for (j = 1; j <= n; j++) { 1422 s[j] = BN_new(); 1423 BN_add(s[j], dsa->q, s1[j]); 1424 BN_div(s[j], u, s[j], s1[j], ctx); 1425 } 1426 1427 /* 1428 * Setup is now complete. Roll random polynomial roots x[j] 1429 * (0 < x[j] < q) for all j. While it may not be strictly 1430 * necessary, Make sure each root has no factors in common with 1431 * q. 1432 */ 1433 fprintf(stderr, 1434 "Generating polynomial coefficients for %d roots (%d bits)\n", 1435 n, BN_num_bits(dsa->q)); 1436 x = malloc((n + 1) * sizeof(BIGNUM)); 1437 for (j = 1; j <= n; j++) { 1438 x[j] = BN_new(); 1439 while (1) { 1440 BN_rand(x[j], BN_num_bits(dsa->q), 0, 0); 1441 BN_mod(x[j], x[j], dsa->q, ctx); 1442 BN_gcd(u, x[j], dsa->q, ctx); 1443 if (BN_is_one(u)) 1444 break; 1445 } 1446 } 1447 1448 /* 1449 * Generate polynomial coefficients a[i] (i = 0...n) from the 1450 * expansion of root products (x - x[j]) mod q for all j. The 1451 * method is a present from Charlie Boncelet. 1452 */ 1453 a = malloc((n + 1) * sizeof(BIGNUM)); 1454 for (i = 0; i <= n; i++) { 1455 a[i] = BN_new(); 1456 BN_one(a[i]); 1457 } 1458 for (j = 1; j <= n; j++) { 1459 BN_zero(w); 1460 for (i = 0; i < j; i++) { 1461 BN_copy(u, dsa->q); 1462 BN_mod_mul(v, a[i], x[j], dsa->q, ctx); 1463 BN_sub(u, u, v); 1464 BN_add(u, u, w); 1465 BN_copy(w, a[i]); 1466 BN_mod(a[i], u, dsa->q, ctx); 1467 } 1468 } 1469 1470 /* 1471 * Generate g[i] = g^a[i] mod p for all i and the generator g. 1472 */ 1473 fprintf(stderr, "Generating g[i] parameters\n"); 1474 g = malloc((n + 1) * sizeof(BIGNUM)); 1475 for (i = 0; i <= n; i++) { 1476 g[i] = BN_new(); 1477 BN_mod_exp(g[i], dsa->g, a[i], dsa->p, ctx); 1478 } 1479 1480 /* 1481 * Verify prod(g[i]^(a[i] x[j]^i)) = 1 for all i, j; otherwise, 1482 * exit. Note the a[i] x[j]^i exponent is computed mod q, but 1483 * the g[i] is computed mod p. also note the expression given in 1484 * the paper is incorrect. 1485 */ 1486 temp = 1; 1487 for (j = 1; j <= n; j++) { 1488 BN_one(u); 1489 for (i = 0; i <= n; i++) { 1490 BN_set_word(v, i); 1491 BN_mod_exp(v, x[j], v, dsa->q, ctx); 1492 BN_mod_mul(v, v, a[i], dsa->q, ctx); 1493 BN_mod_exp(v, dsa->g, v, dsa->p, ctx); 1494 BN_mod_mul(u, u, v, dsa->p, ctx); 1495 } 1496 if (!BN_is_one(u)) 1497 temp = 0; 1498 } 1499 fprintf(stderr, 1500 "Confirm prod(g[i]^(x[j]^i)) = 1 for all i, j: %s\n", temp ? 1501 "yes" : "no"); 1502 if (!temp) { 1503 rval = -1; 1504 return (NULL); 1505 } 1506 1507 /* 1508 * Make private encryption key A. Keep it around for awhile, 1509 * since it is expensive to compute. 1510 */ 1511 biga = BN_new(); 1512 BN_one(biga); 1513 for (j = 1; j <= n; j++) { 1514 for (i = 0; i < n; i++) { 1515 BN_set_word(v, i); 1516 BN_mod_exp(v, x[j], v, dsa->q, ctx); 1517 BN_mod_exp(v, g[i], v, dsa->p, ctx); 1518 BN_mod_mul(biga, biga, v, dsa->p, ctx); 1519 } 1520 } 1521 1522 /* 1523 * Roll private random group key b mod q (0 < b < q), where 1524 * gcd(b, q) = 1 to guarantee b^1 exists, then compute b^-1 1525 * mod q. If b is changed, the client keys must be recomputed. 1526 */ 1527 while (1) { 1528 BN_rand(b, BN_num_bits(dsa->q), 0, 0); 1529 BN_mod(b, b, dsa->q, ctx); 1530 BN_gcd(u, b, dsa->q, ctx); 1531 if (BN_is_one(u)) 1532 break; 1533 } 1534 BN_mod_inverse(b1, b, dsa->q, ctx); 1535 1536 /* 1537 * Make private client keys (xbar[j], xhat[j]) for all j. Note 1538 * that the keys for the jth client involve s[j], but not s'[j] 1539 * or the product s = prod(s'[j]) mod q, which is the enabling 1540 * key. 1541 */ 1542 xbar = malloc((n + 1) * sizeof(BIGNUM)); 1543 xhat = malloc((n + 1) * sizeof(BIGNUM)); 1544 for (j = 1; j <= n; j++) { 1545 xbar[j] = BN_new(); xhat[j] = BN_new(); 1546 BN_zero(xbar[j]); 1547 BN_set_word(v, n); 1548 for (i = 1; i <= n; i++) { 1549 if (i == j) 1550 continue; 1551 BN_mod_exp(u, x[i], v, dsa->q, ctx); 1552 BN_add(xbar[j], xbar[j], u); 1553 } 1554 BN_mod_mul(xbar[j], xbar[j], b1, dsa->q, ctx); 1555 BN_mod_exp(xhat[j], x[j], v, dsa->q, ctx); 1556 BN_mod_mul(xhat[j], xhat[j], s[j], dsa->q, ctx); 1557 } 1558 1559 /* 1560 * The enabling key is initially q by construction. We can 1561 * revoke client j by dividing q by s'[j]. The quotient becomes 1562 * the enabling key s. Note we always have to revoke one key; 1563 * otherwise, the plaintext and cryptotext would be identical. 1564 */ 1565 ss = BN_new(); 1566 BN_copy(ss, dsa->q); 1567 BN_div(ss, u, dsa->q, s1[n], ctx); 1568 1569 /* 1570 * Make private server encryption key E = A^s and public server 1571 * keys gbar = g^s mod p and ghat = g^(s b) mod p. The (gbar, 1572 * ghat) is the public key provided to the server, which uses it 1573 * to compute the session encryption key and public key included 1574 * in its messages. These values must be regenerated if the 1575 * enabling key is changed. 1576 */ 1577 bige = BN_new(); gbar = BN_new(); ghat = BN_new(); 1578 BN_mod_exp(bige, biga, ss, dsa->p, ctx); 1579 BN_mod_exp(gbar, dsa->g, ss, dsa->p, ctx); 1580 BN_mod_mul(v, ss, b, dsa->q, ctx); 1581 BN_mod_exp(ghat, dsa->g, v, dsa->p, ctx); 1582 1583 /* 1584 * We produce the key media in three steps. The first step is to 1585 * generate the private values that do not depend on the 1586 * enabling key. These include the server values p, q, g, b, A 1587 * and the client values s'[j], xbar[j] and xhat[j] for each j. 1588 * The p, xbar[j] and xhat[j] values are encoded in private 1589 * files which are distributed to respective clients. The p, q, 1590 * g, A and s'[j] values (will be) written to a secret file to 1591 * be read back later. 1592 * 1593 * The secret file (will be) read back at some later time to 1594 * enable/disable individual keys and generate/regenerate the 1595 * enabling key s. The p, q, E, gbar and ghat values are written 1596 * to a secret file to be read back later by the server. 1597 * 1598 * The server reads the secret file and rolls the session key 1599 * k, which is used only once, then computes E^k, gbar^k and 1600 * ghat^k. The E^k is the session encryption key. The encrypted 1601 * data, gbar^k and ghat^k are transmtted to clients in an 1602 * extension field. The client receives the message and computes 1603 * x = (gbar^k)^xbar[j] (ghat^k)^xhat[j], finds the session 1604 * encryption key E^k as the inverse x^-1 and decrypts the data. 1605 */ 1606 BN_copy(dsa->g, bige); 1607 dsa->priv_key = BN_dup(gbar); 1608 dsa->pub_key = BN_dup(ghat); 1609 1610 /* 1611 * Write the MV server parameters and keys as a DSA private key 1612 * encoded in PEM. 1613 * 1614 * p modulus p 1615 * q modulus q (used only to generate k) 1616 * g E mod p 1617 * priv_key gbar mod p 1618 * pub_key ghat mod p 1619 */ 1620 str = fheader("MVpar", trustname); 1621 pkey = EVP_PKEY_new(); 1622 EVP_PKEY_assign_DSA(pkey, dsa); 1623 PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, 1624 NULL, 0, NULL, passwd2); 1625 fclose(str); 1626 if (debug) 1627 DSA_print_fp(stdout, dsa, 0); 1628 fslink(id, trustname); 1629 1630 /* 1631 * Write the parameters and private key (xbar[j], xhat[j]) for 1632 * all j as a DSA private key encoded in PEM. It is used only by 1633 * the designated recipient(s) who pay a suitably outrageous fee 1634 * for its use. 1635 */ 1636 sdsa = DSA_new(); 1637 sdsa->p = BN_dup(dsa->p); 1638 sdsa->q = BN_dup(BN_value_one()); 1639 sdsa->g = BN_dup(BN_value_one()); 1640 sdsa->priv_key = BN_new(); 1641 sdsa->pub_key = BN_new(); 1642 for (j = 1; j <= n; j++) { 1643 BN_copy(sdsa->priv_key, xbar[j]); 1644 BN_copy(sdsa->pub_key, xhat[j]); 1645 BN_mod_exp(v, dsa->priv_key, sdsa->pub_key, dsa->p, 1646 ctx); 1647 BN_mod_exp(u, dsa->pub_key, sdsa->priv_key, dsa->p, 1648 ctx); 1649 BN_mod_mul(u, u, v, dsa->p, ctx); 1650 BN_mod_mul(u, u, dsa->g, dsa->p, ctx); 1651 BN_free(xbar[j]); BN_free(xhat[j]); 1652 BN_free(x[j]); BN_free(s[j]); BN_free(s1[j]); 1653 if (!BN_is_one(u)) { 1654 fprintf(stderr, "Revoke key %d\n", j); 1655 continue; 1656 } 1657 1658 /* 1659 * Write the client parameters as a DSA private key 1660 * encoded in PEM. We don't make links for these. 1661 * 1662 * p modulus p 1663 * priv_key xbar[j] mod q 1664 * pub_key xhat[j] mod q 1665 * (remaining values are not used) 1666 */ 1667 sprintf(ident, "MVkey%d", j); 1668 str = fheader(ident, trustname); 1669 pkey1 = EVP_PKEY_new(); 1670 EVP_PKEY_set1_DSA(pkey1, sdsa); 1671 PEM_write_PrivateKey(str, pkey1, passwd2 ? 1672 EVP_des_cbc() : NULL, NULL, 0, NULL, passwd2); 1673 fclose(str); 1674 fprintf(stderr, "ntpkey_%s_%s.%lu\n", ident, trustname, 1675 epoch + JAN_1970); 1676 if (debug) 1677 DSA_print_fp(stdout, sdsa, 0); 1678 EVP_PKEY_free(pkey1); 1679 } 1680 1681 /* 1682 * Free the countries. 1683 */ 1684 for (i = 0; i <= n; i++) { 1685 BN_free(a[i]); 1686 BN_free(g[i]); 1687 } 1688 BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx); 1689 BN_free(b); BN_free(b1); BN_free(biga); BN_free(bige); 1690 BN_free(ss); BN_free(gbar); BN_free(ghat); 1691 DSA_free(sdsa); 1692 1693 /* 1694 * Free the world. 1695 */ 1696 free(x); free(a); free(g); free(s); free(s1); 1697 free(xbar); free(xhat); 1698 return (pkey); 1699 } 1700 1701 1702 /* 1703 * Generate X509v3 scertificate. 1704 * 1705 * The certificate consists of the version number, serial number, 1706 * validity interval, issuer name, subject name and public key. For a 1707 * self-signed certificate, the issuer name is the same as the subject 1708 * name and these items are signed using the subject private key. The 1709 * validity interval extends from the current time to the same time one 1710 * year hence. For NTP purposes, it is convenient to use the NTP seconds 1711 * of the current time as the serial number. 1712 */ 1713 int 1714 x509 ( 1715 EVP_PKEY *pkey, /* generic signature algorithm */ 1716 const EVP_MD *md, /* generic digest algorithm */ 1717 char *gqpub, /* identity extension (hex string) */ 1718 char *exten /* private cert extension */ 1719 ) 1720 { 1721 X509 *cert; /* X509 certificate */ 1722 X509_NAME *subj; /* distinguished (common) name */ 1723 X509_EXTENSION *ex; /* X509v3 extension */ 1724 FILE *str; /* file handle */ 1725 ASN1_INTEGER *serial; /* serial number */ 1726 const char *id; /* digest/signature scheme name */ 1727 char pathbuf[MAXFILENAME + 1]; 1728 1729 /* 1730 * Generate X509 self-signed certificate. 1731 * 1732 * Set the certificate serial to the NTP seconds for grins. Set 1733 * the version to 3. Set the subject name and issuer name to the 1734 * subject name in the request. Set the initial validity to the 1735 * current time and the final validity one year hence. 1736 */ 1737 id = OBJ_nid2sn(md->pkey_type); 1738 fprintf(stderr, "Generating certificate %s\n", id); 1739 cert = X509_new(); 1740 X509_set_version(cert, 2L); 1741 serial = ASN1_INTEGER_new(); 1742 ASN1_INTEGER_set(serial, epoch + JAN_1970); 1743 X509_set_serialNumber(cert, serial); 1744 ASN1_INTEGER_free(serial); 1745 X509_gmtime_adj(X509_get_notBefore(cert), 0L); 1746 X509_gmtime_adj(X509_get_notAfter(cert), YEAR); 1747 subj = X509_get_subject_name(cert); 1748 X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC, 1749 (unsigned char *) hostname, strlen(hostname), -1, 0); 1750 subj = X509_get_issuer_name(cert); 1751 X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC, 1752 (unsigned char *) trustname, strlen(trustname), -1, 0); 1753 if (!X509_set_pubkey(cert, pkey)) { 1754 fprintf(stderr, "Assign key fails\n%s\n", 1755 ERR_error_string(ERR_get_error(), NULL)); 1756 X509_free(cert); 1757 rval = -1; 1758 return (0); 1759 } 1760 1761 /* 1762 * Add X509v3 extensions if present. These represent the minimum 1763 * set defined in RFC3280 less the certificate_policy extension, 1764 * which is seriously obfuscated in OpenSSL. 1765 */ 1766 /* 1767 * The basic_constraints extension CA:TRUE allows servers to 1768 * sign client certficitates. 1769 */ 1770 fprintf(stderr, "%s: %s\n", LN_basic_constraints, 1771 BASIC_CONSTRAINTS); 1772 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, 1773 BASIC_CONSTRAINTS); 1774 if (!X509_add_ext(cert, ex, -1)) { 1775 fprintf(stderr, "Add extension field fails\n%s\n", 1776 ERR_error_string(ERR_get_error(), NULL)); 1777 rval = -1; 1778 return (0); 1779 } 1780 X509_EXTENSION_free(ex); 1781 1782 /* 1783 * The key_usage extension designates the purposes the key can 1784 * be used for. 1785 */ 1786 fprintf(stderr, "%s: %s\n", LN_key_usage, KEY_USAGE); 1787 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, KEY_USAGE); 1788 if (!X509_add_ext(cert, ex, -1)) { 1789 fprintf(stderr, "Add extension field fails\n%s\n", 1790 ERR_error_string(ERR_get_error(), NULL)); 1791 rval = -1; 1792 return (0); 1793 } 1794 X509_EXTENSION_free(ex); 1795 /* 1796 * The subject_key_identifier is used for the GQ public key. 1797 * This should not be controversial. 1798 */ 1799 if (gqpub != NULL) { 1800 fprintf(stderr, "%s\n", LN_subject_key_identifier); 1801 ex = X509V3_EXT_conf_nid(NULL, NULL, 1802 NID_subject_key_identifier, gqpub); 1803 if (!X509_add_ext(cert, ex, -1)) { 1804 fprintf(stderr, 1805 "Add extension field fails\n%s\n", 1806 ERR_error_string(ERR_get_error(), NULL)); 1807 rval = -1; 1808 return (0); 1809 } 1810 X509_EXTENSION_free(ex); 1811 } 1812 1813 /* 1814 * The extended key usage extension is used for special purpose 1815 * here. The semantics probably do not conform to the designer's 1816 * intent and will likely change in future. 1817 * 1818 * "trustRoot" designates a root authority 1819 * "private" designates a private certificate 1820 */ 1821 if (exten != NULL) { 1822 fprintf(stderr, "%s: %s\n", LN_ext_key_usage, exten); 1823 ex = X509V3_EXT_conf_nid(NULL, NULL, 1824 NID_ext_key_usage, exten); 1825 if (!X509_add_ext(cert, ex, -1)) { 1826 fprintf(stderr, 1827 "Add extension field fails\n%s\n", 1828 ERR_error_string(ERR_get_error(), NULL)); 1829 rval = -1; 1830 return (0); 1831 } 1832 X509_EXTENSION_free(ex); 1833 } 1834 1835 /* 1836 * Sign and verify. 1837 */ 1838 X509_sign(cert, pkey, md); 1839 if (!X509_verify(cert, pkey)) { 1840 fprintf(stderr, "Verify %s certificate fails\n%s\n", id, 1841 ERR_error_string(ERR_get_error(), NULL)); 1842 X509_free(cert); 1843 rval = -1; 1844 return (0); 1845 } 1846 1847 /* 1848 * Write the certificate encoded in PEM. 1849 */ 1850 sprintf(pathbuf, "%scert", id); 1851 str = fheader(pathbuf, hostname); 1852 PEM_write_X509(str, cert); 1853 fclose(str); 1854 if (debug) 1855 X509_print_fp(stdout, cert); 1856 X509_free(cert); 1857 fslink("cert", hostname); 1858 return (1); 1859 } 1860 1861 #if 0 /* asn2ntp is not used */ 1862 /* 1863 * asn2ntp - convert ASN1_TIME time structure to NTP time 1864 */ 1865 u_long 1866 asn2ntp ( 1867 ASN1_TIME *asn1time /* pointer to ASN1_TIME structure */ 1868 ) 1869 { 1870 char *v; /* pointer to ASN1_TIME string */ 1871 struct tm tm; /* time decode structure time */ 1872 1873 /* 1874 * Extract time string YYMMDDHHMMSSZ from ASN.1 time structure. 1875 * Note that the YY, MM, DD fields start with one, the HH, MM, 1876 * SS fiels start with zero and the Z character should be 'Z' 1877 * for UTC. Also note that years less than 50 map to years 1878 * greater than 100. Dontcha love ASN.1? 1879 */ 1880 if (asn1time->length > 13) 1881 return (-1); 1882 v = (char *)asn1time->data; 1883 tm.tm_year = (v[0] - '0') * 10 + v[1] - '0'; 1884 if (tm.tm_year < 50) 1885 tm.tm_year += 100; 1886 tm.tm_mon = (v[2] - '0') * 10 + v[3] - '0' - 1; 1887 tm.tm_mday = (v[4] - '0') * 10 + v[5] - '0'; 1888 tm.tm_hour = (v[6] - '0') * 10 + v[7] - '0'; 1889 tm.tm_min = (v[8] - '0') * 10 + v[9] - '0'; 1890 tm.tm_sec = (v[10] - '0') * 10 + v[11] - '0'; 1891 tm.tm_wday = 0; 1892 tm.tm_yday = 0; 1893 tm.tm_isdst = 0; 1894 return (mktime(&tm) + JAN_1970); 1895 } 1896 #endif 1897 1898 /* 1899 * Callback routine 1900 */ 1901 void 1902 cb ( 1903 int n1, /* arg 1 */ 1904 int n2, /* arg 2 */ 1905 void *chr /* arg 3 */ 1906 ) 1907 { 1908 switch (n1) { 1909 case 0: 1910 d0++; 1911 fprintf(stderr, "%s %d %d %lu\r", (char *)chr, n1, n2, 1912 d0); 1913 break; 1914 case 1: 1915 d1++; 1916 fprintf(stderr, "%s\t\t%d %d %lu\r", (char *)chr, n1, 1917 n2, d1); 1918 break; 1919 case 2: 1920 d2++; 1921 fprintf(stderr, "%s\t\t\t\t%d %d %lu\r", (char *)chr, 1922 n1, n2, d2); 1923 break; 1924 case 3: 1925 d3++; 1926 fprintf(stderr, "%s\t\t\t\t\t\t%d %d %lu\r", 1927 (char *)chr, n1, n2, d3); 1928 break; 1929 } 1930 } 1931 1932 1933 /* 1934 * Generate key 1935 */ 1936 EVP_PKEY * /* public/private key pair */ 1937 genkey( 1938 char *type, /* key type (RSA or DSA) */ 1939 char *id /* file name id */ 1940 ) 1941 { 1942 if (type == NULL) 1943 return (NULL); 1944 if (strcmp(type, "RSA") == 0) 1945 return (gen_rsa(id)); 1946 1947 else if (strcmp(type, "DSA") == 0) 1948 return (gen_dsa(id)); 1949 1950 fprintf(stderr, "Invalid %s key type %s\n", id, type); 1951 rval = -1; 1952 return (NULL); 1953 } 1954 #endif /* OPENSSL */ 1955 1956 1957 /* 1958 * Generate file header 1959 */ 1960 FILE * 1961 fheader ( 1962 const char *id, /* file name id */ 1963 const char *name /* owner name */ 1964 ) 1965 { 1966 FILE *str; /* file handle */ 1967 1968 sprintf(filename, "ntpkey_%s_%s.%lu", id, name, epoch + 1969 JAN_1970); 1970 if ((str = fopen(filename, "w")) == NULL) { 1971 perror("Write"); 1972 exit (-1); 1973 } 1974 fprintf(str, "# %s\n# %s", filename, ctime(&epoch)); 1975 return (str); 1976 } 1977 1978 1979 /* 1980 * Generate symbolic links 1981 */ 1982 void 1983 fslink( 1984 const char *id, /* file name id */ 1985 const char *name /* owner name */ 1986 ) 1987 { 1988 char linkname[MAXFILENAME]; /* link name */ 1989 int temp; 1990 1991 sprintf(linkname, "ntpkey_%s_%s", id, name); 1992 remove(linkname); 1993 temp = symlink(filename, linkname); 1994 if (temp < 0) 1995 perror(id); 1996 fprintf(stderr, "Generating new %s file and link\n", id); 1997 fprintf(stderr, "%s->%s\n", linkname, filename); 1998 } 1999