NetBSD/dist/ntp/util/ntp_genkeys.c
2000-04-22 14:51:59 +00:00

241 lines
8.3 KiB
C

/* $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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#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);
}