From: Harlan Stenn Date: Sat, 15 Sep 2007 20:40:14 +0000 (-0400) Subject: Crypto cleanup from Dave Mills.\n[Bug 897] Check RAND_status() - we may not need... X-Git-Tag: NTP_4_2_5P77~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d872790eebda4ec2d7fca22a66d0323610b0557a;p=thirdparty%2Fntp.git Crypto cleanup from Dave Mills.\n[Bug 897] Check RAND_status() - we may not need a .rnd file bk: 46ec432ej15KovG6qPKdzU5S_bXxHg --- diff --git a/ChangeLog b/ChangeLog index acc9a99d4..285ce55c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ +* [Bug 897] Check RAND_status() - we may not need a .rnd file. +* Crypto cleanup from Dave Mills. * [Bug 911] Fix error message in cmd_args.c. * [Bug 895] Log assertion failures via syslog(), not stderr. * Documentation updates from Dave Mills. diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index a9a0e84c6..986bea10e 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -217,7 +217,7 @@ static struct ctl_var peer_var[] = { { CP_OUT, RO, "out" }, /* 39 */ #ifdef OPENSSL { CP_FLAGS, RO, "flags" }, /* 40 */ - { CP_HOST, RO, "group" }, /* 41 */ + { CP_HOST, RO, "host" }, /* 41 */ { CP_VALID, RO, "valid" }, /* 42 */ { CP_INITSEQ, RO, "initsequence" }, /* 43 */ { CP_INITKEY, RO, "initkey" }, /* 44 */ @@ -1429,7 +1429,7 @@ ctl_putsys( case CS_GROUP: if (sys_groupname != NULL) - ctl_putstr(sys_var[CS_HOST].text, sys_groupname, + ctl_putstr(sys_var[CS_GROUP].text, sys_groupname, strlen(sys_groupname)); break; diff --git a/ntpd/ntp_crypto.c b/ntpd/ntp_crypto.c index 7e7ca3d5e..2c26cddbc 100644 --- a/ntpd/ntp_crypto.c +++ b/ntpd/ntp_crypto.c @@ -122,6 +122,7 @@ char *sys_groupname = NULL; /* group name */ * Global cryptodata in network byte order */ struct cert_info *cinfo = NULL; /* certificate info/value cache */ +struct cert_info *cert_host = NULL; /* host certificate */ struct pkey_info *pkinfo = NULL; /* key info/value cache */ struct value hostval; /* host value */ struct value pubkey; /* public key */ @@ -167,7 +168,7 @@ static int cert_sign (struct exten *, struct value *); static int cert_valid (struct cert_info *, EVP_PKEY *); static struct cert_info *cert_install (struct exten *, struct peer *); static void cert_free (struct cert_info *); -static struct pkey_info *crypto_key (char *); +static struct pkey_info *crypto_key (char *, char *); static void bighash (BIGNUM *, BIGNUM *); static struct cert_info *crypto_cert (char *); @@ -1248,16 +1249,29 @@ crypto_xmit( break; /* - * Send certificate response or sign request. Use the values - * from the certificate cache. If the request contains no - * subject name, assume the name of this host. This is for - * backwards compatibility. Private certificates are never sent. - * - * If a sign request, send the host certificate, which is self- - * signed and may or may not be trusted. If a certificate - * response, do not send the host certificate. + * Send sign request. Use the host certificate, which is self- + * signed and may or may not be trusted. */ case CRYPTO_SIGN: + if (tstamp < cert_host->first || tstamp > + cert_host->last) + rval = XEVNT_SRV; + else + rval = crypto_send(fp, &cert_host->cert, &len); + break; + + /* + * Send certificate response. Use the name in the extension + * field to find the certificate in the cache. If the request + * contains no subject name, assume the name of this host. This + * is for backwards compatibility. Private certificates are + * never sent. + * + * There may be several certificates matching the request. First + * choice is a self-signed trusted certificate; second choice is + * any certificate signed by another host. There is no third + * choice. + */ case CRYPTO_CERT | CRYPTO_RESP: vallen = ntohl(ep->vallen); if (vallen == 8) { @@ -1740,21 +1754,21 @@ crypto_ident( if (peer->crypto & CRYPTO_FLAG_IFF) { snprintf(filename, MAXFILENAME, "ntpkey_iffpar_%s", peer->issuer); - peer->ident_pkey = crypto_key(filename); + peer->ident_pkey = crypto_key(filename, NULL); if (peer->ident_pkey != NULL) return (CRYPTO_IFF); } if (peer->crypto & CRYPTO_FLAG_GQ) { snprintf(filename, MAXFILENAME, "ntpkey_gqpar_%s", peer->issuer); - peer->ident_pkey = crypto_key(filename); + peer->ident_pkey = crypto_key(filename, NULL); if (peer->ident_pkey != NULL) return (CRYPTO_GQ); } if (peer->crypto & CRYPTO_FLAG_MV) { snprintf(filename, MAXFILENAME, "ntpkey_mvpar_%s", peer->issuer); - peer->ident_pkey = crypto_key(filename); + peer->ident_pkey = crypto_key(filename, NULL); if (peer->ident_pkey != NULL) return (CRYPTO_MV); } @@ -2256,6 +2270,10 @@ crypto_bob( sdsa->s = BN_dup(bk); BN_CTX_free(bctx); BN_free(r); BN_free(bn); BN_free(bk); +#ifdef DEBUG + if (debug > 1) + DSA_print_fp(stdout, dsa, 0); +#endif /* * Encode the values in ASN.1 and sign. The filestamp is from @@ -2549,6 +2567,10 @@ crypto_bob2( sdsa->s = BN_dup(g); BN_CTX_free(bctx); BN_free(r); BN_free(k); BN_free(g); BN_free(y); +#ifdef DEBUG + if (debug > 1) + RSA_print_fp(stdout, rsa, 0); +#endif /* * Encode the values in ASN.1 and sign. The filestamp is from @@ -2648,6 +2670,10 @@ crypto_gq( /* * Compute v^r y^b mod n. */ + if (peer->grpkey == NULL) { + msyslog(LOG_INFO, "crypto_gq: missing group key"); + return (XEVNT_ID); + } BN_mod_exp(v, peer->grpkey, peer->iffval, rsa->n, bctx); /* v^r mod n */ BN_mod_exp(y, sdsa->r, rsa->e, rsa->n, bctx); /* y^b mod n */ @@ -2872,6 +2898,10 @@ crypto_bob3( BN_mod_exp(sdsa->q, dsa->priv_key, k, dsa->p, bctx); /* gbar */ BN_mod_exp(sdsa->g, dsa->pub_key, k, dsa->p, bctx); /* ghat */ BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u); +#ifdef DEBUG + if (debug > 1) + DSA_print_fp(stdout, dsa, 0); +#endif /* * Encode the values in ASN.1 and sign. The filestamp is from @@ -3249,7 +3279,7 @@ cert_install( * so, X signs Y. */ if (strcmp(yp->issuer, xp->subject) != 0 || - xp->flags & CERT_ERROR) + xp->flags & CERT_ERROR) continue; if (cert_valid(yp, xp->pkey) != XEVNT_OK) { @@ -3293,7 +3323,7 @@ cert_install( if (strcmp(yp->subject, peer->subject) != 0) continue; - peer->grpkey = yp->grpkey; + peer->grpkey = xp->grpkey; peer->crypto |= CRYPTO_FLAG_VALID; /* @@ -3349,11 +3379,20 @@ cert_parse( const char *ptr; int temp, cnt, i; +#if 0 +u_char *pta; + +pta = asn1cert; +for (i = 0; i < len; i++) +printf("%02x:", 0xff & *pta++); +printf("\n%x %ld\n", asn1cert, len); +#endif + /* * Decode ASN.1 objects and construct certificate structure. */ uptr = asn1cert; - if ((cert = d2i_X509(NULL, &uptr, len)) == NULL) { + if ((cert = d2i_X509(NULL, (u_char **)&uptr, len)) == NULL) { msyslog(LOG_ERR, "cert_parse: %s", ERR_error_string(ERR_get_error(), NULL)); return (NULL); @@ -3549,7 +3588,8 @@ cert_free( */ static struct pkey_info * crypto_key( - char *cp /* file name */ + char *cp, /* file name */ + char *passwd1 /* password */ ) { FILE *str; /* file handle */ @@ -3608,7 +3648,7 @@ crypto_key( * Read and decrypt PEM-encoded private key. If it fails to * decrypt, game over. */ - pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd); + pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd1); fclose(str); if (pkey == NULL) { msyslog(LOG_ERR, "crypto_key: %s", @@ -3726,13 +3766,13 @@ crypto_cert( fclose(str); return (NULL); } + fclose(str); free(header); if (strcmp(name, "CERTIFICATE") != 0) { msyslog(LOG_INFO, "crypto_cert: wrong PEM type %s", name); free(name); free(data); - fclose(str); return (NULL); } free(name); @@ -3741,9 +3781,8 @@ crypto_cert( * Parse certificate and generate info/value structure. The * pointer and copy nonsense is due something broken in Solaris. */ - free(data); ret = cert_parse(data, len, fstamp); - fclose(str); + free(data); if (ret == NULL) return (NULL); @@ -3799,47 +3838,44 @@ crypto_setup(void) OPENSSL_VERSION_NUMBER, SSLeay()); exit (-1); } + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); /* * Load required random seed file and seed the random number - * generator. Be default, it is found in the user home + * generator. Be default, it is found as .rnd in the user home * directory. The root home directory may be / or /root, * depending on the system. Wiggle the contents a bit and write * it back so the sequence does not repeat when we next restart. */ - ERR_load_crypto_strings(); - if (rand_file == NULL) { - if ((RAND_file_name(filename, MAXFILENAME)) != NULL) { - rand_file = emalloc(strlen(filename) + 1); - strcpy(rand_file, filename); + if (!RAND_status()) { + if (rand_file == NULL) + RAND_file_name(filename, MAXFILENAME); + else if (*rand_file == '/') + strcpy(filename, rand_file); + else + snprintf(filename, MAXFILENAME, "%s/%s", + keysdir, rand_file); + if (filename == NULL) { + msyslog(LOG_ERR, + "crypto_setup: seed file unknown name"); + exit (-1); } - } else if (*rand_file != '/') { - snprintf(filename, MAXFILENAME, "%s/%s", keysdir, - rand_file); - free(rand_file); - rand_file = emalloc(strlen(filename) + 1); - strcpy(rand_file, filename); - } - if (rand_file == NULL) { - msyslog(LOG_ERR, - "crypto_setup: random seed file unknown name"); - exit (-1); - } - if ((bytes = RAND_load_file(rand_file, -1)) == 0) { - msyslog(LOG_ERR, - "crypto_setup: random seed file %s missing", - rand_file); - exit (-1); - } - get_systime(&seed); - RAND_seed(&seed, sizeof(l_fp)); - RAND_write_file(rand_file); - OpenSSL_add_all_algorithms(); + if ((bytes = RAND_load_file(filename, -1)) == 0) { + msyslog(LOG_ERR, + "crypto_setup: random seed file %s missing", + filename); + exit (-1); + } + get_systime(&seed); + RAND_seed(&seed, sizeof(l_fp)); + RAND_write_file(filename); #ifdef DEBUG - if (debug) - printf( - "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n", - SSLeay(), rand_file, bytes); + if (debug) + printf( + "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n", + SSLeay(), filename, bytes); + } #endif /* @@ -3865,21 +3901,21 @@ crypto_setup(void) * sign key. */ snprintf(filename, MAXFILENAME, "ntpkey_host_%s", sys_hostname); - pinfo = crypto_key(filename); + pinfo = crypto_key(filename, passwd); if (pinfo == NULL) { msyslog(LOG_ERR, "crypto_setup: host key file %s not found or corrupt", filename); exit (-1); } - host_pkey = pinfo->pkey; - sign_pkey = host_pkey; - hostval.fstamp = htonl(pinfo->fstamp); - if (host_pkey->type != EVP_PKEY_RSA) { + if (pinfo->pkey->type != EVP_PKEY_RSA) { msyslog(LOG_ERR, "crypto_setup: host key is not RSA key type"); exit (-1); } + host_pkey = pinfo->pkey; + sign_pkey = host_pkey; + hostval.fstamp = htonl(pinfo->fstamp); hostval.vallen = htonl(strlen(sys_hostname)); hostval.ptr = (u_char *)sys_hostname; @@ -3890,8 +3926,8 @@ crypto_setup(void) ptr = emalloc(len); pubkey.ptr = ptr; i2d_PublicKey(host_pkey, &ptr); - pubkey.vallen = htonl(len); pubkey.fstamp = hostval.fstamp; + pubkey.vallen = htonl(len); /* * Load optional sign key from file "ntpkey_sign_". If @@ -3900,7 +3936,7 @@ crypto_setup(void) if (sign_file != NULL) { snprintf(filename, MAXFILENAME, "ntpkey_sign_%s", sign_file); - pinfo = crypto_key(filename); + pinfo = crypto_key(filename, passwd); if (pinfo != NULL) sign_pkey = pinfo->pkey; } @@ -3913,7 +3949,7 @@ crypto_setup(void) cinfo = crypto_cert(filename); if (cinfo == NULL) { msyslog(LOG_ERR, - "crypto_setup: certificate file %s not found or corrupt", + "crypto_setup: certificate file %s not found or corrupt", filename); exit (-1); } @@ -3929,7 +3965,6 @@ crypto_setup(void) msyslog(LOG_ERR, "crypto_setup: certificate %s not for this host %s", filename, sys_hostname); - cert_free(cinfo); exit (-1); } @@ -3940,7 +3975,6 @@ crypto_setup(void) msyslog(LOG_ERR, "crypto_setup: certificate %s is not self-signed", filename); - cert_free(cinfo); exit (-1); } @@ -3952,17 +3986,16 @@ crypto_setup(void) msyslog(LOG_ERR, "crypto_setup: trusted host %s missing group name", cinfo->subject); - cert_free(cinfo); exit (-1); } if (strcmp(cinfo->subject, sys_groupname) != 0) { msyslog(LOG_ERR, "crypto_setup: trusted host %s name and group name %s mismatch", cinfo->subject, sys_groupname); - cert_free(cinfo); exit (-1); } } + cert_host = cinfo; if (sys_groupname != NULL) { /* @@ -3971,7 +4004,7 @@ crypto_setup(void) */ snprintf(filename, MAXFILENAME, "ntpkey_iffkey_%s", sys_groupname); - iffkey_info = crypto_key(filename); + iffkey_info = crypto_key(filename, passwd); if (iffkey_info != NULL) crypto_flags |= CRYPTO_FLAG_IFF; @@ -3981,7 +4014,7 @@ crypto_setup(void) */ snprintf(filename, MAXFILENAME, "ntpkey_gqkey_%s", sys_groupname); - gqkey_info = crypto_key(filename); + gqkey_info = crypto_key(filename, passwd); if (gqkey_info != NULL) crypto_flags |= CRYPTO_FLAG_GQ; @@ -3991,14 +4024,13 @@ crypto_setup(void) */ snprintf(filename, MAXFILENAME, "ntpkey_mvkey_%s", sys_groupname); - mvkey_info = crypto_key(filename); + mvkey_info = crypto_key(filename, passwd); if (mvkey_info != NULL) crypto_flags |= CRYPTO_FLAG_MV; } /* - * We have survived tedious and careful checking; now strike up - * the dance. + * We met the enemy and he is us. Now strike up the dance. */ crypto_flags |= CRYPTO_FLAG_ENAB | (cinfo->nid << 16); #ifdef DEBUG diff --git a/util/ntp-keygen.c b/util/ntp-keygen.c index 66ea1e103..8cdb66317 100644 --- a/util/ntp-keygen.c +++ b/util/ntp-keygen.c @@ -44,20 +44,14 @@ * * ntpkey_IFFkey_. * ntpkey_iffkey_ - * ntpkey_IFFpar_. - * ntpkey_iffpar_ * Schnorr (IFF) identity parameters and keys * * ntpkey_GQkey_., * ntpkey_gqkey_ - * ntpkey_GQpar_., - * ntpkey_gqpar_ * Guillou-Quisquater (GQ) identity parameters and keys * * ntpkey_MVkeyX_., * ntpkey_mvkey_ - * ntpkey_MVparX_., - * ntpkey_mvpar_ * Mu-Varadharajan (MV) identity parameters and keys * * Note: Once in a while because of some statistical fluke this program @@ -146,9 +140,8 @@ int gen_md5 (char *); #ifdef OPENSSL EVP_PKEY *gen_rsa (char *); EVP_PKEY *gen_dsa (char *); -EVP_PKEY *gen_iff (char *); -EVP_PKEY *gen_gqpar (char *); -EVP_PKEY *gen_gqkey (char *, EVP_PKEY *); +EVP_PKEY *gen_iffkey (char *); +EVP_PKEY *gen_gqkey (char *); EVP_PKEY *gen_mv (char *); int x509 (EVP_PKEY *, const EVP_MD *, char *, char *); void cb (int, int, void *); @@ -226,14 +219,13 @@ main( X509 *cert = NULL; /* X509 certificate */ EVP_PKEY *pkey_host = NULL; /* host key */ EVP_PKEY *pkey_sign = NULL; /* sign key */ - EVP_PKEY *pkey_iffkey = NULL; /* IFF keys and parameters */ - EVP_PKEY *pkey_gqpar = NULL; /* GQ parameters */ - EVP_PKEY *pkey_gqkey = NULL; /* GQ keys */ + EVP_PKEY *pkey_iffkey = NULL; /* IFF keys */ + EVP_PKEY *pkey_gqkey = NULL; /* GQ parameters */ EVP_PKEY *pkey_mv = NULL; /* MV parameters */ int hostkey = 0; /* generate RSA keys */ - int iffkey = 0; /* generate IFF keys and parameters */ - int gqpar = 0; /* generate GQ parameters */ - int gqkey = 0; /* update GQ keys */ + int iffkey = 0; /* generate IFF keys */ + int gqpar = 0; /* generate GQ keys */ + int gqkey = 0; /* not used */ int mvpar = 0; /* generate MV parameters */ int mvkey = 0; /* update MV keys */ char *sign = NULL; /* sign key */ @@ -245,7 +237,6 @@ main( char *grpkey = NULL; /* identity extension */ int nid; /* X509 digest/signature scheme */ FILE *fstr = NULL; /* file handle */ - u_int temp; #define iffsw HAVE_OPT(ID_KEY) #endif /* OPENSSL */ char hostbuf[MAXHOSTNAME + 1]; @@ -309,7 +300,7 @@ main( gqpar++; if (HAVE_OPT( GQ_KEYS )) - gqkey++; + gqkey++; /* not used */ if (HAVE_OPT( HOST_KEY )) hostkey++; @@ -366,32 +357,38 @@ main( */ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - if (RAND_file_name(pathbuf, MAXFILENAME) == NULL) { - fprintf(stderr, "RAND_file_name %s\n", - ERR_error_string(ERR_get_error(), NULL)); - exit (-1); - } - temp = RAND_load_file(pathbuf, -1); - if (temp == 0) { + if (!RAND_status()) { + u_int temp; + + if (RAND_file_name(pathbuf, MAXFILENAME) == NULL) { + fprintf(stderr, "RAND_file_name %s\n", + ERR_error_string(ERR_get_error(), NULL)); + exit (-1); + } + temp = RAND_load_file(pathbuf, -1); + if (temp == 0) { + fprintf(stderr, + "RAND_load_file %s not found or empty\n", + pathbuf); + exit (-1); + } fprintf(stderr, - "RAND_load_file %s not found or empty\n", pathbuf); - exit (-1); + "Random seed file %s %u bytes\n", pathbuf, temp); + RAND_add(&epoch, sizeof(epoch), 4.0); } - fprintf(stderr, - "Random seed file %s %u bytes\n", pathbuf, temp); - RAND_add(&epoch, sizeof(epoch), 4.0); #endif /* - * Generate new parameters and keys as requested. These replace - * any values already generated. + * Generate new MD5 keys if requested. These replace any + * keysalready generated. */ if (md5key) gen_md5("MD5"); #ifdef OPENSSL /* - * Create new host keys if requested; otherwise, look for - * existing host keys. If not found, create a new host RSA + * Create a new encrypted RSA host key file if requested; + * otherwise, look for an existing host key file. If not found, + * create a new encrypted RSA host key file containing a * public/private key pair. */ if (hostkey) @@ -414,9 +411,9 @@ main( } /* - * Create new sign keys if requested; otherwise, look for - * existing sign keys. If not found, use the host keys instead. - * Either RSA or DSA keys can be selected by option. + * Create new encrypted RSA or DSA sign key file if requested; + * otherwise, look for an existing sign key file. If not found, + * use the host keys instead. */ if (sign != NULL) pkey_sign = genkey(sign, "sign"); @@ -434,78 +431,79 @@ main( } /* - * Create new GQ parameters if requested; otherwise, look for - * existing GQ parameters. The parameters are instantiated in - * all group hosts. The keys are generated separately by each - * host. + * Create new encrypted GQ parameter file if requested; + * otherwise, look for an exisiting file. If found, fetch the + * public key for the certificate. */ - if (gqpar) { - pkey_gqpar = gen_gqpar("gqpar"); - if (pkey_gqpar != NULL) - gqkey++; - } - if (pkey_gqpar == NULL) { - sprintf(filename, "ntpkey_gqpar_%s", trustname); - pkey_gqpar = readkey(filename, passwd1, &fstamp); - if (pkey_gqpar != NULL) { + if (gqpar) + pkey_gqkey = gen_gqkey("gqkey"); + if (pkey_gqkey == NULL) { + sprintf(filename, "ntpkey_gqkey_%s", trustname); + pkey_gqkey = readkey(filename, passwd1, &fstamp); + if (pkey_gqkey != NULL) { readlink(filename, filename, sizeof(filename)); fprintf(stderr, "Using GQ parameters %s\n", filename); } } + if (pkey_gqkey != NULL) + grpkey = BN_bn2hex(pkey_gqkey->pkey.rsa->q); /* - * Write the GQ parameters to the stdout stream redirected to a - * file. Ordinarily, the file is copied to another machine and - * installed under the name in the file header. + * Write the nonencrypted GQ parameters to the stdout stream. + * The parameer file is the keys file with the private key + * obscured. */ - if (pkey_gqpar != NULL && strcmp(passwd1, passwd2) != 0) { + if (pkey_gqkey != NULL && HAVE_OPT(ID_KEY)) { RSA *rsa; epoch = fstamp - JAN_1970; - sprintf(filename, "ntpkey_GQpar_%s.%u", trustname, + sprintf(filename, "ntpkey_gqpar_%s.%u", trustname, fstamp); - fprintf(stderr, - "Writing GQ parameters %s to stdout\n", filename); + fprintf(stderr, "Writing GQ parameters %s to stdout\n", + filename); fprintf(stdout, "# %s\n# %s\n", filename, ctime(&epoch)); - rsa = pkey_gqpar->pkey.rsa; + rsa = pkey_gqkey->pkey.rsa; + BN_copy(rsa->p, BN_value_one()); + BN_copy(rsa->q, BN_value_one()); pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); - PEM_write_PrivateKey(stdout, pkey, EVP_des_cbc(), NULL, - 0, NULL, passwd2); + PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, + NULL); fclose(stdout); if (debug) RSA_print_fp(stderr, rsa, 0); } /* - * Create new GQ keys if requested. Otherwise, look for - * exisiting GQ keys and fetch the public key for the - * certificate.. + * Write the encrypted GQ keys to the stdout stream. */ - if (pkey_gqpar != NULL && gqkey) - pkey_gqkey = gen_gqkey("gqkey", pkey_gqpar); - if (pkey_gqkey == NULL) { - sprintf(filename, "ntpkey_gqkey_%s", trustname); - pkey_gqkey = readkey(filename, passwd1, &fstamp); - if (pkey_gqkey != NULL) { - readlink(filename, filename, sizeof(filename)); - fprintf(stderr, "Using GQ keys %s\n", - filename); - } + if (pkey_gqkey != NULL && strcmp(passwd1, passwd2) != 0) { + RSA *rsa; + + sprintf(filename, "ntpkey_GQkey_%s.%u", trustname, + fstamp); + fprintf(stderr, "Writing GQ keys %s to stdout\n", + filename); + fprintf(stdout, "# %s\n# %s\n", filename, + ctime(&epoch)); + rsa = pkey_gqkey->pkey.rsa; + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pkey, rsa); + PEM_write_PrivateKey(stdout, pkey, + EVP_des_cbc(), NULL, 0, NULL, passwd2); + fclose(stdout); + if (debug) + RSA_print_fp(stderr, rsa, 0); } - if (pkey_gqkey != NULL) - grpkey = BN_bn2hex(pkey_gqkey->pkey.rsa->q); /* - * Create new IFF keys if requested; otherwise, look for - * existing IFF keys. In the IFF scheme the keys include the - * parameters, which are not generated separately as in the GQ - * scheme. + * Create new encrypted IFF keys file if requested; otherwise, + * look for existing keys file. */ if (iffkey) - pkey_iffkey = gen_iff("iffkey"); + pkey_iffkey = gen_iffkey("iffkey"); if (pkey_iffkey == NULL) { sprintf(filename, "ntpkey_iffkey_%s", trustname); pkey_iffkey = readkey(filename, passwd1, &fstamp); @@ -517,24 +515,45 @@ main( } /* - * Write the IFF parameters to the stdout stream redirected to a - * file. Ordinarily, the file is copied to another machine and - * installed under the name in the file header. Then, a soft - * link is installed to it from "ntpkey_iffkey_". + * Write the nonencrypted IFF parameters to the stdout stream. + * The parameer file is the keys file with the private key + * obscured. + */ + if (pkey_iffkey != NULL && HAVE_OPT(ID_KEY)) { + DSA *dsa; + + epoch = fstamp - JAN_1970; + sprintf(filename, "ntpkey_iffpar_%s.%u", trustname, + fstamp); + fprintf(stderr, "Writing IFF parameters %s to stdout\n", + filename); + fprintf(stdout, "# %s\n# %s\n", filename, + ctime(&epoch)); + dsa = pkey_iffkey->pkey.dsa; + BN_copy(dsa->priv_key, BN_value_one()); + pkey = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(pkey, dsa); + PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, + NULL); + fclose(stdout); + if (debug) + DSA_print_fp(stderr, dsa, 0); + } + + /* + * Write the encrypted IFF keys to the stdout stream. */ if (pkey_iffkey != NULL && strcmp(passwd1, passwd2) != 0) { DSA *dsa; epoch = fstamp - JAN_1970; - sprintf(filename, "ntpkey_IFFpar_%s.%u", trustname, + sprintf(filename, "ntpkey_IFFkey_%s.%u", trustname, fstamp); - fprintf(stderr, - "Writing IFF client key %s to stdout\n", filename); + fprintf(stderr, "Writing IFF keys %s to stdout\n", + filename); fprintf(stdout, "# %s\n# %s\n", filename, ctime(&epoch)); dsa = pkey_iffkey->pkey.dsa; - if (HAVE_OPT(ID_KEY)) - BN_copy(dsa->priv_key, BN_value_one()); pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsa); PEM_write_PrivateKey(stdout, pkey, EVP_des_cbc(), NULL, @@ -550,7 +569,7 @@ main( */ if (mvpar) pkey_mv = gen_mv("mv"); - if (strcmp(passwd1, passwd2) != 0) + if (strcmp(passwd1, passwd2) != 0 || HAVE_OPT(ID_KEY)) exit (0); /* @@ -609,8 +628,6 @@ gen_md5( fprintf(stderr, "Generating MD5 keys...\n"); str = fheader("MD5key", trustname); keyid = BN_new(); key = BN_new(); - NTP_INSIST(keyid != NULL); - NTP_INSIST(key != NULL); BN_rand(keyid, 16, -1, 0); BN_rand(key, 128, -1, 0); BN_bn2bin(key, bin); @@ -767,9 +784,8 @@ gen_rsa( * Write the RSA parameters and keys as a RSA private key * encoded in PEM. */ - str = fheader("RSAkey", hostname); + str = fheader("RSApar", hostname); pkey = EVP_PKEY_new(); - NTP_INSIST(pkey != NULL); EVP_PKEY_assign_RSA(pkey, rsa); PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL, passwd2); @@ -826,7 +842,6 @@ gen_dsa( */ str = fheader("DSAkey", hostname); pkey = EVP_PKEY_new(); - NTP_INSIST(pkey != NULL); EVP_PKEY_assign_DSA(pkey, dsa); PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL, passwd2); @@ -862,8 +877,11 @@ gen_dsa( * group clients. Alice challenges Bob to confirm identity using the * protocol described below. */ +/* + * Generate Schnorr (IFF) keys. + */ EVP_PKEY * /* DSA cuckoo nest */ -gen_iff( +gen_iffkey( char *id /* file name id */ ) { @@ -895,21 +913,13 @@ gen_iff( * these keys are distributed to all members of the group. */ b = BN_new(); r = BN_new(); k = BN_new(); - NTP_INSIST(b != NULL); - NTP_INSIST(r != NULL); - NTP_INSIST(k != NULL); u = BN_new(); v = BN_new(); w = BN_new(); ctx = BN_CTX_new(); - NTP_INSIST(u != NULL); - NTP_INSIST(v != NULL); - NTP_INSIST(w != NULL); - NTP_INSIST(ctx != NULL); BN_rand(b, BN_num_bits(dsa->q), -1, 0); /* a */ BN_mod(b, b, dsa->q, ctx); BN_sub(v, dsa->q, b); BN_mod_exp(v, dsa->g, v, dsa->p, ctx); /* g^(q - b) mod p */ BN_mod_exp(u, dsa->g, b, dsa->p, ctx); /* g^b mod p */ BN_mod_mul(u, u, v, dsa->p, ctx); - NTP_INSIST(u->d != NULL); temp = BN_is_one(u); fprintf(stderr, "Confirm g^(q - b) g^b = 1 mod p: %s\n", temp == 1 ? @@ -962,14 +972,16 @@ gen_iff( } /* - * Write the IFF server parameters and keys as a DSA private key - * encoded in PEM. + * Write the IFF keys as an encrypted DSA private key encoded in + * PEM. * * p modulus p * q modulus q * g generator g * priv_key b * public_key v + * kinv not used + * r not used */ str = fheader("IFFkey", trustname); pkey = EVP_PKEY_new(); @@ -983,7 +995,6 @@ gen_iff( return (pkey); } - /* * Generate Guillou-Quisquater (GQ) parameters and keys * @@ -1008,21 +1019,27 @@ gen_iff( * scheme. Alice challenges Bob to confirm identity using the protocol * described below. */ +/* + * Generate Guillou-Quisquater (GQ) parameters file. + */ EVP_PKEY * /* RSA cuckoo nest */ -gen_gqpar( +gen_gqkey( char *id /* file name id */ ) { EVP_PKEY *pkey; /* private key */ - RSA *rsa; /* GQ parameters */ + RSA *rsa; /* RSA parameters */ BN_CTX *ctx; /* BN working space */ + BIGNUM *u, *v, *g, *k, *r, *y; /* BN temps */ FILE *str; + u_int temp; /* * Generate RSA parameters for use as GQ parameters. */ fprintf(stderr, - "Generating GQ parameters (%d bits)...\n", modulus); + "Generating GQ parameters (%d bits)...\n", + modulus); rsa = RSA_generate_key(modulus, 3, cb, "GQ"); fprintf(stderr, "\n"); if (rsa == NULL) { @@ -1030,74 +1047,22 @@ gen_gqpar( ERR_error_string(ERR_get_error(), NULL)); return (NULL); } + ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); + g = BN_new(); k = BN_new(); r = BN_new(); y = BN_new(); /* * Generate the group key b, which is saved in the e member of - * the RSA structure. These values are distributed to all - * members of the group, but shielded from all other groups. We - * don't use all the parameters, but set the unused ones to a - * small number to minimize the file size. + * the RSA structure. The group key is transmitted to each group + * member encrypted by the member private key. */ ctx = BN_CTX_new(); BN_rand(rsa->e, BN_num_bits(rsa->n), -1, 0); /* b */ BN_mod(rsa->e, rsa->e, rsa->n, ctx); - BN_copy(rsa->d, BN_value_one()); - BN_copy(rsa->p, BN_value_one()); - BN_copy(rsa->q, BN_value_one()); - BN_copy(rsa->dmp1, BN_value_one()); - BN_copy(rsa->dmq1, BN_value_one()); - BN_copy(rsa->iqmp, BN_value_one()); - - /* - * Write the GQ parameters as a RSA private key encoded in PEM. - * The public and private keys are filled in later. - * - * n modulus n - * e group key b - * (remaining values are not used) - */ - str = fheader("GQpar", trustname); - pkey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(pkey, rsa); - PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL, - passwd2); - fclose(str); - if (debug) - RSA_print_fp(stderr, rsa, 0); - fslink(id, trustname); - return (pkey); -} - - -/* - * Update Guillou-Quisquater (GQ) parameters - */ -EVP_PKEY * /* RSA cuckoo nest */ -gen_gqkey( - char *id, /* file name id */ - EVP_PKEY *gqpar /* GQ parameters */ - ) -{ - EVP_PKEY *pkey; /* private key */ - RSA *rsa; /* RSA parameters */ - BN_CTX *ctx; /* BN working space */ - BIGNUM *u, *v, *g, *k, *r, *y; /* BN temps */ - FILE *str; - u_int temp; - - /* - * Generate GQ keys. Note that the group key b is the e member - * of the GQ parameters. - */ - fprintf(stderr, "Updating GQ keys (%d bits)...\n", modulus); - ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); - g = BN_new(); k = BN_new(); r = BN_new(); y = BN_new(); /* * When generating his certificate, Bob rolls random private key * u. */ - rsa = gqpar->pkey.rsa; BN_rand(u, BN_num_bits(rsa->n), -1, 0); /* u */ BN_mod(u, u, rsa->n, ctx); BN_mod_inverse(v, u, rsa->n, ctx); /* u^-1 mod n */ @@ -1164,15 +1129,22 @@ gen_gqkey( } /* - * Write the GQ parameters and keys as a RSA private key encoded - * in PEM. + * Write the GQ parameter file as an encrypted RSA private key + * encoded in PEM. * * n modulus n * e group key b + * d not used * p private key u * q public key (u^-1)^b - * (remaining values are not used) + * dmp1 not used + * dmq1 not used + * iqmp not used */ + BN_copy(rsa->d, BN_value_one()); + BN_copy(rsa->dmp1, BN_value_one()); + BN_copy(rsa->dmq1, BN_value_one()); + BN_copy(rsa->iqmp, BN_value_one()); str = fheader("GQkey", trustname); pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); @@ -1284,27 +1256,15 @@ gen_mv( "Generating MV parameters for %d keys (%d bits)...\n", n, modulus / n); ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); w = BN_new(); - NTP_INSIST(ctx != NULL); - NTP_INSIST(u != NULL); - NTP_INSIST(v != NULL); - NTP_INSIST(w != NULL); b = BN_new(); b1 = BN_new(); - NTP_INSIST(b != NULL); - NTP_INSIST(b1 != NULL); dsa = DSA_new(); - NTP_INSIST(dsa != NULL); dsa->p = BN_new(); - NTP_INSIST(dsa->p != NULL); dsa->q = BN_new(); - NTP_INSIST(dsa->q != NULL); dsa->g = BN_new(); - NTP_INSIST(dsa->g != NULL); s = malloc((n + 1) * sizeof(BIGNUM)); s1 = malloc((n + 1) * sizeof(BIGNUM)); - for (j = 1; j <= n; j++) { + for (j = 1; j <= n; j++) s1[j] = BN_new(); - NTP_INSIST(s1[j] != NULL); - } temp = 0; for (j = 1; j <= n; j++) { while (1) { @@ -1373,7 +1333,6 @@ gen_mv( BN_rand(dsa->g, BN_num_bits(dsa->p) - 1, 0, 0); BN_mod(dsa->g, dsa->g, dsa->p, ctx); BN_gcd(u, dsa->g, v, ctx); - NTP_INSIST(u->d != NULL); if (!BN_is_one(u)) continue; @@ -1390,7 +1349,6 @@ gen_mv( */ for (j = 1; j <= n; j++) { s[j] = BN_new(); - NTP_INSIST(s[j] != NULL); BN_add(s[j], dsa->q, s1[j]); BN_div(s[j], u, s[j], s1[j], ctx); } @@ -1407,7 +1365,6 @@ gen_mv( x = malloc((n + 1) * sizeof(BIGNUM)); for (j = 1; j <= n; j++) { x[j] = BN_new(); - NTP_INSIST(x[j] != NULL); while (1) { BN_rand(x[j], BN_num_bits(dsa->q), 0, 0); BN_mod(x[j], x[j], dsa->q, ctx); @@ -1425,7 +1382,6 @@ gen_mv( a = malloc((n + 1) * sizeof(BIGNUM)); for (i = 0; i <= n; i++) { a[i] = BN_new(); - NTP_INSIST(a[i] != NULL); BN_one(a[i]); } for (j = 1; j <= n; j++) { @@ -1447,7 +1403,6 @@ gen_mv( g = malloc((n + 1) * sizeof(BIGNUM)); for (i = 0; i <= n; i++) { g[i] = BN_new(); - NTP_INSIST(g[i] != NULL); BN_mod_exp(g[i], dsa->g, a[i], dsa->p, ctx); } @@ -1482,7 +1437,6 @@ gen_mv( * since it is expensive to compute. */ biga = BN_new(); - NTP_INSIST(biga != NULL); BN_one(biga); for (j = 1; j <= n; j++) { for (i = 0; i < n; i++) { @@ -1517,8 +1471,6 @@ gen_mv( xhat = malloc((n + 1) * sizeof(BIGNUM)); for (j = 1; j <= n; j++) { xbar[j] = BN_new(); xhat[j] = BN_new(); - NTP_INSIST(xbar[j] != NULL); - NTP_INSIST(xhat[j] != NULL); BN_zero(xbar[j]); BN_set_word(v, n); for (i = 1; i <= n; i++) { @@ -1539,7 +1491,6 @@ gen_mv( * otherwise, the plaintext and cryptotext would be identical. */ ss = BN_new(); - NTP_INSIST(ss != NULL); BN_copy(ss, dsa->q); BN_div(ss, u, dsa->q, s1[n], ctx); @@ -1552,9 +1503,6 @@ gen_mv( * enabling key is changed. */ bige = BN_new(); gbar = BN_new(); ghat = BN_new(); - NTP_INSIST(bige != NULL); - NTP_INSIST(gbar != NULL); - NTP_INSIST(ghat != NULL); BN_mod_exp(bige, biga, ss, dsa->p, ctx); BN_mod_exp(gbar, dsa->g, ss, dsa->p, ctx); BN_mod_mul(v, ss, b, dsa->q, ctx); @@ -1599,7 +1547,6 @@ gen_mv( */ str = fheader("MVpar", trustname); pkey = EVP_PKEY_new(); - NTP_INSIST(pkey != NULL); EVP_PKEY_assign_DSA(pkey, dsa); PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL, passwd2); @@ -1615,14 +1562,11 @@ gen_mv( * for its use. */ sdsa = DSA_new(); - NTP_INSIST(sdsa != NULL); sdsa->p = BN_dup(dsa->p); sdsa->q = BN_dup(BN_value_one()); sdsa->g = BN_dup(BN_value_one()); sdsa->priv_key = BN_new(); - NTP_INSIST(sdsa->priv_key != NULL); sdsa->pub_key = BN_new(); - NTP_INSIST(sdsa->pub_key != NULL); for (j = 1; j <= n; j++) { BN_copy(sdsa->priv_key, xbar[j]); BN_copy(sdsa->pub_key, xhat[j]); @@ -1651,7 +1595,6 @@ gen_mv( sprintf(ident, "MVkey%d", j); str = fheader(ident, trustname); pkey1 = EVP_PKEY_new(); - NTP_INSIST(pkey1 != NULL); EVP_PKEY_set1_DSA(pkey1, sdsa); PEM_write_PrivateKey(str, pkey1, EVP_des_cbc(), NULL, 0, NULL, passwd2); @@ -1685,7 +1628,7 @@ gen_mv( /* - * Generate X509v3 scertificate. + * Generate X509v3 certificate. * * The certificate consists of the version number, serial number, * validity interval, issuer name, subject name and public key. For a @@ -1722,10 +1665,8 @@ x509 ( id = OBJ_nid2sn(md->pkey_type); fprintf(stderr, "Generating certificate %s\n", id); cert = X509_new(); - NTP_INSIST(cert != NULL); X509_set_version(cert, 2L); serial = ASN1_INTEGER_new(); - NTP_INSIST(serial != NULL); ASN1_INTEGER_set(serial, epoch + JAN_1970); X509_set_serialNumber(cert, serial); ASN1_INTEGER_free(serial);