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