📄 ntp-keygen.c
字号:
if (passwd1 != NULL && passwd2 == NULL) passwd2 = passwd1;#ifdef OPENSSL /* * Seed random number generator and grow weeds. */ 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)); return (-1); } temp = RAND_load_file(pathbuf, -1); if (temp == 0) { fprintf(stderr, "RAND_load_file %s not found or empty\n", pathbuf); return (-1); } 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. */ if (md5key) gen_md5("MD5");#ifdef OPENSSL if (hostkey) pkey_host = genkey("RSA", "host"); if (sign != NULL) pkey_sign = genkey(sign, "sign"); if (iffkey) pkey_iff = gen_iff("iff"); if (gqpar) pkey_gq = gen_gqpar("gq"); if (mvpar) pkey_mv = gen_mv("mv"); /* * If there is no new host key, look for an existing one. If not * found, create it. */ while (pkey_host == NULL && rval == 0 && !iffsw) { sprintf(filename, "ntpkey_host_%s", hostname); if ((fstr = fopen(filename, "r")) != NULL) { pkey_host = PEM_read_PrivateKey(fstr, NULL, NULL, passwd1); fclose(fstr); readlink(filename, filename, sizeof(filename)); if (pkey_host == NULL) { fprintf(stderr, "Host key\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; } else { fprintf(stderr, "Using host key %s\n", filename); } break; } else if ((pkey_host = genkey("RSA", "host")) == NULL) { rval = -1; break; } } /* * If there is no new sign key, look for an existing one. If not * found, use the host key instead. */ pkey = pkey_sign; while (pkey_sign == NULL && rval == 0 && !iffsw) { sprintf(filename, "ntpkey_sign_%s", hostname); if ((fstr = fopen(filename, "r")) != NULL) { pkey_sign = PEM_read_PrivateKey(fstr, NULL, NULL, passwd1); fclose(fstr); readlink(filename, filename, sizeof(filename)); if (pkey_sign == NULL) { fprintf(stderr, "Sign key\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; } else { fprintf(stderr, "Using sign key %s\n", filename); } break; } else { pkey = pkey_host; fprintf(stderr, "Using host key as sign key\n"); break; } } /* * If there is no new IFF file, look for an existing one. */ if (pkey_iff == NULL && rval == 0) { sprintf(filename, "ntpkey_iff_%s", hostname); if ((fstr = fopen(filename, "r")) != NULL) { pkey_iff = PEM_read_PrivateKey(fstr, NULL, NULL, passwd1); fclose(fstr); readlink(filename, filename, sizeof(filename)); if (pkey_iff == NULL) { fprintf(stderr, "IFF parameters\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; } else { fprintf(stderr, "Using IFF parameters %s\n", filename); } } } /* * If there is no new GQ file, look for an existing one. */ if (pkey_gq == NULL && rval == 0 && !iffsw) { sprintf(filename, "ntpkey_gq_%s", hostname); if ((fstr = fopen(filename, "r")) != NULL) { pkey_gq = PEM_read_PrivateKey(fstr, NULL, NULL, passwd1); fclose(fstr); readlink(filename, filename, sizeof(filename)); if (pkey_gq == NULL) { fprintf(stderr, "GQ parameters\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; } else { fprintf(stderr, "Using GQ parameters %s\n", filename); } } } /* * If there is a GQ parameter file, create GQ private/public * keys and extract the public key for the certificate. */ if (pkey_gq != NULL && rval == 0) { gen_gqkey("gq", pkey_gq); grpkey = BN_bn2hex(pkey_gq->pkey.rsa->q); } /* * Generate a X509v3 certificate. */ while (scheme == NULL && rval == 0 && !iffsw) { sprintf(filename, "ntpkey_cert_%s", hostname); if ((fstr = fopen(filename, "r")) != NULL) { cert = PEM_read_X509(fstr, NULL, NULL, NULL); fclose(fstr); readlink(filename, filename, sizeof(filename)); if (cert == NULL) { fprintf(stderr, "Cert \n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; } else { nid = OBJ_obj2nid( cert->cert_info->signature->algorithm); scheme = OBJ_nid2sn(nid); fprintf(stderr, "Using scheme %s from %s\n", scheme, filename); break; } } scheme = "RSA-MD5"; } if (pkey != NULL && rval == 0 && !iffsw) { ectx = EVP_get_digestbyname(scheme); if (ectx == NULL) { fprintf(stderr, "Invalid digest/signature combination %s\n", scheme); rval = -1; } else { x509(pkey, ectx, grpkey, exten); } } /* * Write the IFF client parameters and keys as a DSA private key * encoded in PEM. Note the private key is obscured. */ if (pkey_iff != NULL && rval == 0 && iffsw) { DSA *dsa; char *sptr; char *tld; sptr = strrchr(filename, '.'); tld = malloc(strlen(sptr)); /* we have an extra byte ... */ strcpy(tld, 1+sptr); /* ... see? */ sprintf(filename, "ntpkey_IFFkey_%s.%s", trustname, tld); free(tld); fprintf(stderr, "Writing new IFF key %s\n", filename); fprintf(stdout, "# %s\n# %s", filename, ctime(&epoch)); dsa = pkey_iff->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, passwd2 ? EVP_des_cbc() : NULL, NULL, 0, NULL, passwd2); fclose(stdout); if (debug) DSA_print_fp(stdout, dsa, 0); } /* * Return the marbles. */ if (grpkey != NULL) OPENSSL_free(grpkey); if (pkey_host != NULL) EVP_PKEY_free(pkey_host); if (pkey_sign != NULL) EVP_PKEY_free(pkey_sign); if (pkey_iff != NULL) EVP_PKEY_free(pkey_iff); if (pkey_gq != NULL) EVP_PKEY_free(pkey_gq); if (pkey_mv != NULL) EVP_PKEY_free(pkey_mv);#endif /* OPENSSL */ return (rval);}#if 0/* * Generate random MD5 key with password. */intgen_md5( char *id /* file name id */ ){ BIGNUM *key; BIGNUM *keyid; FILE *str; u_char bin[16]; fprintf(stderr, "Generating MD5 keys...\n"); str = fheader("MD5key", hostname); keyid = BN_new(); key = BN_new(); BN_rand(keyid, 16, -1, 0); BN_rand(key, 128, -1, 0); BN_bn2bin(key, bin); PEM_write_fp(str, MD5, NULL, bin); fclose(str); fslink(id, hostname); return (1);}#else/* * Generate semi-random MD5 keys compatible with NTPv3 and NTPv4 */intgen_md5( char *id /* file name id */ ){ u_char md5key[16]; /* MD5 key */ FILE *str; u_int temp = 0; /* Initialize to prevent warnings during compile */ int i, j; fprintf(stderr, "Generating MD5 keys...\n"); str = fheader("MD5key", hostname); ntp_srandom(epoch); for (i = 1; i <= MD5KEYS; i++) { for (j = 0; j < 16; j++) { while (1) { temp = ntp_random() & 0xff; if (temp == '#') continue; if (temp > 0x20 && temp < 0x7f) break; } md5key[j] = (u_char)temp; } md5key[15] = '\0'; fprintf(str, "%2d MD5 %16s # MD5 key\n", i, md5key); } fclose(str); fslink(id, hostname); return (1);}#endif /* OPENSSL */#ifdef OPENSSL/* * Generate RSA public/private key pair */EVP_PKEY * /* public/private key pair */gen_rsa( char *id /* file name id */ ){ EVP_PKEY *pkey; /* private key */ RSA *rsa; /* RSA parameters and key pair */ FILE *str; fprintf(stderr, "Generating RSA keys (%d bits)...\n", modulus); rsa = RSA_generate_key(modulus, 3, cb, "RSA"); fprintf(stderr, "\n"); if (rsa == NULL) { fprintf(stderr, "RSA generate keys fails\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; return (NULL); } /* * For signature encryption it is not necessary that the RSA * parameters be strictly groomed and once in a while the * modulus turns out to be non-prime. Just for grins, we check * the primality. */ if (!RSA_check_key(rsa)) { fprintf(stderr, "Invalid RSA key\n%s\n", ERR_error_string(ERR_get_error(), NULL)); RSA_free(rsa); rval = -1; return (NULL); } /* * Write the RSA parameters and keys as a RSA private key * encoded in PEM. */ str = fheader("RSAkey", hostname); pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, NULL, 0, NULL, passwd2); fclose(str); if (debug) RSA_print_fp(stdout, rsa, 0); fslink(id, hostname); return (pkey);} /* * Generate DSA public/private key pair */EVP_PKEY * /* public/private key pair */gen_dsa( char *id /* file name id */ ){ EVP_PKEY *pkey; /* private key */ DSA *dsa; /* DSA parameters */ u_char seed[20]; /* seed for parameters */ FILE *str; /* * Generate DSA parameters. */ fprintf(stderr, "Generating DSA parameters (%d bits)...\n", modulus); RAND_bytes(seed, sizeof(seed)); dsa = DSA_generate_parameters(modulus, seed, sizeof(seed), NULL, NULL, cb, "DSA"); fprintf(stderr, "\n"); if (dsa == NULL) { fprintf(stderr, "DSA generate parameters fails\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; return (NULL); } /* * Generate DSA keys. */ fprintf(stderr, "Generating DSA keys (%d bits)...\n", modulus); if (!DSA_generate_key(dsa)) { fprintf(stderr, "DSA generate keys fails\n%s\n", ERR_error_string(ERR_get_error(), NULL)); DSA_free(dsa); rval = -1; return (NULL); } /* * Write the DSA parameters and keys as a DSA private key * encoded in PEM. */ str = fheader("DSAkey", hostname); pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsa); PEM_write_PrivateKey(str, pkey, passwd2 ? EVP_des_cbc() : NULL, NULL, 0, NULL, passwd2); fclose(str); if (debug) DSA_print_fp(stdout, dsa, 0); fslink(id, hostname); return (pkey);}/* * Generate Schnorr (IFF) parameters and keys * * The Schnorr (IFF)identity scheme is intended for use when * certificates are generated by some other trusted certificate * authority and the parameters cannot be conveyed in the certificate * itself. For this purpose, new generations of IFF values must be * securely transmitted to all members of the group before use. There * are two kinds of files: server/client files that include private and * public parameters and client files that include only public * parameters. The scheme is self contained and independent of new * generations of host keys, sign keys and certificates. * * The IFF values hide in a DSA cuckoo structure which uses the same * parameters. The values are used by an identity scheme based on DSA * cryptography and described in Stimson p. 285. The p is a 512-bit * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1 * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a * private random group key b (0 < b < q), then computes public * v = g^(q - a). All values except the group key are known to all group * members; the group key is known to the group servers, but not the * group clients. Alice challenges Bob to confirm identity using the * protocol described below. */EVP_PKEY * /* DSA cuckoo nest */gen_iff( char *id /* file name id */ ){ EVP_PKEY *pkey; /* private key */ DSA *dsa; /* DSA parameters */ u_char seed[20]; /* seed for parameters */ BN_CTX *ctx; /* BN working space */ BIGNUM *b, *r, *k, *u, *v, *w; /* BN temp */ FILE *str; u_int temp; /* * Generate DSA parameters for use as IFF parameters. */ fprintf(stderr, "Generating IFF parameters (%d bits)...\n", modulus); RAND_bytes(seed, sizeof(seed)); dsa = DSA_generate_parameters(modulus, seed, sizeof(seed), NULL, NULL, cb, "IFF"); fprintf(stderr, "\n"); if (dsa == NULL) { fprintf(stderr, "DSA generate parameters fails\n%s\n", ERR_error_string(ERR_get_error(), NULL)); rval = -1; return (NULL);; } /* * Generate the private and public keys. The DSA parameters and * these keys are distributed to all members of the group. */ fprintf(stderr, "Generating IFF keys (%d bits)...\n", modulus); b = BN_new(); r = BN_new(); k = BN_new(); u = BN_new(); v = BN_new(); w = BN_new(); ctx = BN_CTX_new(); 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); temp = BN_is_one(u); fprintf(stderr, "Confirm g^(q - b) g^b = 1 mod p: %s\n", temp == 1 ? "yes" : "no"); if (!temp) { BN_free(b); BN_free(r); BN_free(k); BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx); rval = -1; return (NULL); } dsa->priv_key = BN_dup(b); /* private key */ dsa->pub_key = BN_dup(v); /* public key */ /* * Here is a trial round of the protocol. First, Alice rolls * random r (0 < r < q) and sends it to Bob. She needs only * modulus q. */ BN_rand(r, BN_num_bits(dsa->q), -1, 0); /* r */ BN_mod(r, r, dsa->q, ctx); /* * Bob rolls random k (0 < k < q), computes y = k + b r mod q * and x = g^k mod p, then sends (y, x) to Alice. He needs * moduli p, q and the group key b. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -