/* $NetBSD: ntp_genkeys.c,v 1.1.1.1 2000/04/22 14:54:31 simonb Exp $ */ /* * Program to generate MD5 and RSA keys for NTP clients and servers */ #include #include #include #include #include "ntpd.h" #include "ntp_stdlib.h" #include "ntp_string.h" #include "ntp_crypto.h" /* * Cryptodefines */ #define MAXKEYLEN 1024 /* maximum encoded key length */ #define MODULUSLEN 512 /* length of RSA modulus */ #define PRIMELEN 512 /* length of D_H prime, generator */ #define GENLEN 256 /* length of D-H key and subprime */ /* * This program generates four files: ntp.keys containing the DES/MD5 * private keys, ntpkey containing the RSA private key, ntpkey_host * containing the RSA public key, where host is the DNS name of the * generating machine, and ntpkey_dh containing the parameters for the * Diffie-Hellman key-agreement algorithm. The files contain * cryptographic values generated by the algorithms of the rsaref20 * package and are in printable ASCII format. Since the algorythms are * seeded by the system clock, each run of this program will produce a * different outcome. There are no options or frills of any sort, * although a number of options would seem to be appropriate. Waving * this program in the breeze will no doubt bring a cast of thousands to * wiggle the options this way and that for various useful purposes. * * The ntp.keys file contains 16 MD5 keys. Each key consists of 16 * characters randomized over the ASCII 95-character printing subset. * The file is read by the daemon at the location specified by the keys * configuration file command and made visible only to root. An * additional key consisting of a easily remembered password should be * added by hand for use with the ntpdc program. The file must be * distributed by secure means to other servers and clients sharing the * same security compartment. * * The key identifiers for MD5 and DES keys must be less than 65536, * although this program uses only the identifiers from 1 to 16. The key * identifier for each association is specified as the key argument in * the server or peer configuration file command. * * The ntpkey file contains the RSA private key. It is read by the * daemon at the location specified by the private argument of the * crypto configuration file command and made visible only to root. This * file is useful only to the machine that generated it and never shared * with any other daemon or application program. * * The ntpkey_host file contains the RSA public key, where host is the * DNS name of the host that generated it. The file is read by the * daemon at the location specified by the public argument to the server * or peer configuration file command. This file can be widely * distributed and stored without using secure means, since the data are * public values. * * The ntp_dh file contains two Diffie-Hellman parameters, the prime * modulus and the generator. The file is read by the daemon at the * location specified by the dhparams argument of the crypto * configuration file command. This file can be widely distributed and * stored without using secure means, since the data are public values. * * The file formats all begin with two lines, the first containing the * generating system DNS name and the second the datestamp. Lines * beginning with # are considered comments and ignored by the daemon. * In the ntp.keys file, the next 16 lines contain the MD5 keys in * order. In the ntpkey and ntpkey_host files, the next line contains * the modulus length in bits followed by the key as a PEM encoded * string. In the ntpkey_dh file, the next line contains the prime * length in bytes followed by the prime as a PEM encoded string, and * the next and final line contains the generator length in bytes * followed by the generator as a PEM encoded string. * * Note: See the file ./source/rsaref.h in the rsaref20 package for * explanation of return values, if necessary. */ int main( int argc, char *argv[] ) { R_RSA_PRIVATE_KEY rsaref_private; /* RSA private key */ R_RSA_PUBLIC_KEY rsaref_public; /* RSA public key */ R_RSA_PROTO_KEY protokey; /* RSA prototype key */ R_DH_PARAMS dh_params; /* Diffie-Hellman parameters */ R_RANDOM_STRUCT randomstr; /* random structure */ u_char encoded_key[MAXKEYLEN]; /* encoded PEM string buffer */ u_int modulus; /* modulus length */ struct timeval tv; /* initialization vector */ u_char hostname[256]; /* DNS host name */ u_char filename[256]; /* public key file name */ u_char md5key[17]; /* generated MD5 key */ FILE *str; /* file handle */ int rval; /* return value */ u_int temp, len; int i, j; /* * Generate the file "ntp.keys" containing 16 random MD5 keys in * the format expected at daemon run time. */ gethostname(&hostname, sizeof hostname); printf("Generating MD5 keys...\n"); str = fopen("ntp.keys", "w"); if (str == NULL) { perror("MD5/DES key file"); return (-1); } gettimeofday(&tv, 0); srandom((u_int)tv.tv_sec); fprintf(str, "# MD5/DES key file generated by %s\n# %s", hostname, ctime(&tv.tv_sec)); for (i = 1; i <= 16; i++) { for (j = 0; j < 16; j++) { while (1) { temp = random() & 0xff; if (temp > 0x20 && temp < 0x7f) break; } md5key[j] = (u_char)temp; } md5key[16] = 0; fprintf(str, "%2d M %16s # MD5 key\n", i, md5key); } fclose(str); /* * Roll a RSA public/private key pair. */ printf("Generating RSA public/private key pair %d bits...\n", MODULUSLEN); protokey.bits = MODULUSLEN; protokey.useFermat4 = 1; R_RandomInit(&randomstr); R_GetRandomBytesNeeded(&len, &randomstr); for (i = 0; i < len; i++) { temp = random(); R_RandomUpdate(&randomstr, (u_char *)&temp, 1); } rval = R_GeneratePEMKeys(&rsaref_public, &rsaref_private, &protokey, &randomstr); if (rval) { printf("R_GeneratePEMKeys error %x\n", rval); return (-1); } /* * Generate the file "ntpkey" containing the RSA private key in * printable ASCII format. */ str = fopen("ntpkey", "w"); if (str == NULL) { perror("RSA private key file"); return (-1); } len = sizeof(rsaref_private) - sizeof(rsaref_private.bits); modulus = (u_int32)rsaref_private.bits; fprintf(str, "# RSA private key file generated by %s\n# %s", hostname, ctime(&tv.tv_sec)); R_EncodePEMBlock(encoded_key, &temp, (u_char *)&rsaref_private.modulus, len); encoded_key[temp] = '\0'; fprintf(str, "%d %s\n", modulus, encoded_key); fclose(str); /* * Generate the file "ntpkey_host" containing the RSA public key * in printable ASCII format. */ snprintf(filename, sizeof filename, "ntpkey_%s", hostname); str = fopen(filename, "w"); if (str == NULL) { perror("RSA public key file"); return (-1); } len = sizeof(rsaref_public) - sizeof(rsaref_public.bits); modulus = (u_int32)rsaref_public.bits; fprintf(str, "# RSA public key file generated by %s\n# %s", hostname, ctime(&tv.tv_sec)); R_EncodePEMBlock(encoded_key, &temp, (u_char *)&rsaref_public.modulus, len); encoded_key[temp] = '\0'; fprintf(str, "%d %s\n", modulus, encoded_key); fclose(str); /* * Roll the prime and generator for the Diffie-Hellman key * agreement algorithm. */ printf("Generating Diffie-Hellman parameters %d bits...\n", PRIMELEN); str = fopen("ntpkey_dh", "w"); if (str == NULL) { perror("Diffie-Hellman parameters file"); return (-1); } R_RandomInit(&randomstr); R_GetRandomBytesNeeded(&len, &randomstr); for (i = 0; i < len; i++) { temp = random(); R_RandomUpdate(&randomstr, (u_char *)&temp, 1); } /* * Generate the file "ntpkey_dh" containing the Diffie-Hellman * prime and generator in printable ASCII format. */ len = DH_PRIME_LEN(PRIMELEN); dh_params.prime = (u_char *)malloc(len); dh_params.generator = (u_char *)malloc(len); rval = R_GenerateDHParams(&dh_params, PRIMELEN, GENLEN, &randomstr); if (rval) { printf("R_GenerateDHParams error %x\n", rval); return (-1); } fprintf(str, "# Diffie-Hellman parameter file generated by %s\n# %s", hostname, ctime(&tv.tv_sec)); R_EncodePEMBlock(encoded_key, &temp, (u_char *)dh_params.prime, dh_params.primeLen); encoded_key[temp] = '\0'; fprintf(str, "%d %s\n", dh_params.primeLen, encoded_key); R_EncodePEMBlock(encoded_key, &temp, (u_char *)dh_params.generator, dh_params.generatorLen); encoded_key[temp] = '\0'; fprintf(str, "%d %s\n", dh_params.generatorLen, encoded_key); fclose(str); return (0); }