241 lines
8.3 KiB
C
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);
|
||
|
}
|