ntp_crypto.c revision 132451
182498Sroberto/*
282498Sroberto * ntp_crypto.c - NTP version 4 public key routines
382498Sroberto */
482498Sroberto#ifdef HAVE_CONFIG_H
582498Sroberto#include <config.h>
682498Sroberto#endif
782498Sroberto
8132451Sroberto#ifdef OPENSSL
982498Sroberto#include <stdio.h>
1082498Sroberto#include <sys/types.h>
11132451Sroberto#include <sys/param.h>
1282498Sroberto#include <unistd.h>
1382498Sroberto#include <fcntl.h>
1482498Sroberto
1582498Sroberto#include "ntpd.h"
1682498Sroberto#include "ntp_stdlib.h"
17132451Sroberto#include "ntp_unixtime.h"
1882498Sroberto#include "ntp_string.h"
1982498Sroberto
20132451Sroberto#include "openssl/asn1_mac.h"
21132451Sroberto#include "openssl/bn.h"
22132451Sroberto#include "openssl/err.h"
23132451Sroberto#include "openssl/evp.h"
24132451Sroberto#include "openssl/pem.h"
25132451Sroberto#include "openssl/rand.h"
26132451Sroberto#include "openssl/x509v3.h"
27132451Sroberto
2882498Sroberto#ifdef KERNEL_PLL
2982498Sroberto#include "ntp_syscall.h"
3082498Sroberto#endif /* KERNEL_PLL */
3182498Sroberto
3282498Sroberto/*
33132451Sroberto * Extension field message format
3482498Sroberto *
35132451Sroberto * These are always signed and saved before sending in network byte
36132451Sroberto * order. They must be converted to and from host byte order for
37132451Sroberto * processing.
3882498Sroberto *
39132451Sroberto * +-------+-------+
40132451Sroberto * |   op  |  len  | <- extension pointer
41132451Sroberto * +-------+-------+
42132451Sroberto * |    assocID    |
43132451Sroberto * +---------------+
44132451Sroberto * |   timestamp   | <- value pointer
45132451Sroberto * +---------------+
46132451Sroberto * |   filestamp   |
47132451Sroberto * +---------------+
48132451Sroberto * |   value len   |
49132451Sroberto * +---------------+
50132451Sroberto * |               |
51132451Sroberto * =     value     =
52132451Sroberto * |               |
53132451Sroberto * +---------------+
54132451Sroberto * | signature len |
55132451Sroberto * +---------------+
56132451Sroberto * |               |
57132451Sroberto * =   signature   =
58132451Sroberto * |               |
59132451Sroberto * +---------------+
6082498Sroberto *
61132451Sroberto * The CRYPTO_RESP bit is set to 0 for requests, 1 for responses.
62132451Sroberto * Requests carry the association ID of the receiver; responses carry
63132451Sroberto * the association ID of the sender. Some messages include only the
64132451Sroberto * operation/length and association ID words and so have length 8
65132451Sroberto * octets. Ohers include the value structure and associated value and
66132451Sroberto * signature fields. These messages include the timestamp, filestamp,
67132451Sroberto * value and signature words and so have length at least 24 octets. The
68132451Sroberto * signature and/or value fields can be empty, in which case the
69132451Sroberto * respective length words are zero. An empty value with nonempty
70132451Sroberto * signature is syntactically valid, but semantically questionable.
71132451Sroberto *
72132451Sroberto * The filestamp represents the time when a cryptographic data file such
73132451Sroberto * as a public/private key pair is created. It follows every reference
74132451Sroberto * depending on that file and serves as a means to obsolete earlier data
75132451Sroberto * of the same type. The timestamp represents the time when the
76132451Sroberto * cryptographic data of the message were last signed. Creation of a
77132451Sroberto * cryptographic data file or signing a message can occur only when the
78132451Sroberto * creator or signor is synchronized to an authoritative source and
79132451Sroberto * proventicated to a trusted authority.
80132451Sroberto *
81132451Sroberto * Note there are four conditions required for server trust. First, the
82132451Sroberto * public key on the certificate must be verified, which involves a
83132451Sroberto * number of format, content and consistency checks. Next, the server
84132451Sroberto * identity must be confirmed by one of four schemes: private
85132451Sroberto * certificate, IFF scheme, GQ scheme or certificate trail hike to a
86132451Sroberto * self signed trusted certificate. Finally, the server signature must
87132451Sroberto * be verified.
8882498Sroberto */
8982498Sroberto/*
90132451Sroberto * Cryptodefines
9182498Sroberto */
92132451Sroberto#define TAI_1972	10	/* initial TAI offset (s) */
93132451Sroberto#define MAX_LEAP	100	/* max UTC leapseconds (s) */
94132451Sroberto#define VALUE_LEN	(6 * 4) /* min response field length */
95132451Sroberto#define YEAR		(60 * 60 * 24 * 365) /* seconds in year */
9682498Sroberto
9782498Sroberto/*
98132451Sroberto * Global cryptodata in host byte order
9982498Sroberto */
100132451Srobertou_int32	crypto_flags = 0x0;	/* status word */
10182498Srobertou_int	sys_tai;		/* current UTC offset from TAI */
10282498Sroberto
10382498Sroberto/*
104132451Sroberto * Global cryptodata in network byte order
10582498Sroberto */
106132451Srobertostruct cert_info *cinfo = NULL;	/* certificate info/value */
107132451Srobertostruct value hostval;		/* host value */
108132451Srobertostruct value pubkey;		/* public key */
109132451Srobertostruct value tai_leap;		/* leapseconds table */
11082498Sroberto
11182498Sroberto/*
112132451Sroberto * Private cryptodata in host byte order
11382498Sroberto */
114132451Srobertostatic char *passwd = NULL;	/* private key password */
115132451Srobertostatic EVP_PKEY *host_pkey = NULL; /* host key */
116132451Srobertostatic EVP_PKEY *sign_pkey = NULL; /* sign key */
117132451Srobertostatic EVP_PKEY *iffpar_pkey = NULL; /* IFF parameters */
118132451Srobertostatic EVP_PKEY	*gqpar_pkey = NULL; /* GQ parameters */
119132451Srobertostatic EVP_PKEY	*mvpar_pkey = NULL; /* MV parameters */
120132451Srobertostatic const EVP_MD *sign_digest = NULL; /* sign digest */
121132451Srobertostatic u_int sign_siglen;	/* sign key length */
122132451Srobertostatic char *rand_file = NULL;	/* random seed file */
123132451Srobertostatic char *host_file = NULL;	/* host key file */
124132451Srobertostatic char *sign_file = NULL;	/* sign key file */
125132451Srobertostatic char *iffpar_file = NULL; /* IFF parameters file */
126132451Srobertostatic char *gqpar_file = NULL;	/* GQ parameters file */
127132451Srobertostatic char *mvpar_file = NULL;	/* MV parameters file */
128132451Srobertostatic char *cert_file = NULL;	/* certificate file */
129132451Srobertostatic char *leap_file = NULL;	/* leapseconds file */
130132451Srobertostatic tstamp_t if_fstamp = 0;	/* IFF file stamp */
131132451Srobertostatic tstamp_t gq_fstamp = 0;	/* GQ file stamp */
132132451Srobertostatic tstamp_t mv_fstamp = 0;	/* MV file stamp */
13382498Sroberto
13482498Sroberto/*
13582498Sroberto * Cryptotypes
13682498Sroberto */
137132451Srobertostatic	int	crypto_verify	P((struct exten *, struct value *,
138132451Sroberto				    struct peer *));
139132451Srobertostatic	int	crypto_encrypt	P((struct exten *, struct value *,
140132451Sroberto				    keyid_t *));
141132451Srobertostatic	int	crypto_alice	P((struct peer *, struct value *));
142132451Srobertostatic	int	crypto_alice2	P((struct peer *, struct value *));
143132451Srobertostatic	int	crypto_alice3	P((struct peer *, struct value *));
144132451Srobertostatic	int	crypto_bob	P((struct exten *, struct value *));
145132451Srobertostatic	int	crypto_bob2	P((struct exten *, struct value *));
146132451Srobertostatic	int	crypto_bob3	P((struct exten *, struct value *));
147132451Srobertostatic	int	crypto_iff	P((struct exten *, struct peer *));
148132451Srobertostatic	int	crypto_gq	P((struct exten *, struct peer *));
149132451Srobertostatic	int	crypto_mv	P((struct exten *, struct peer *));
150132451Srobertostatic	u_int	crypto_send	P((struct exten *, struct value *));
151132451Srobertostatic	tstamp_t crypto_time	P((void));
152132451Srobertostatic	u_long	asn2ntp		P((ASN1_TIME *));
153132451Srobertostatic	struct cert_info *cert_parse P((u_char *, u_int, tstamp_t));
154132451Srobertostatic	int	cert_sign	P((struct exten *, struct value *));
155132451Srobertostatic	int	cert_valid	P((struct cert_info *, EVP_PKEY *));
156132451Srobertostatic	int	cert_install	P((struct exten *, struct peer *));
157132451Srobertostatic	void	cert_free	P((struct cert_info *));
158132451Srobertostatic	EVP_PKEY *crypto_key	P((char *, tstamp_t *));
159132451Srobertostatic	int	bighash		P((BIGNUM *, BIGNUM *));
160132451Srobertostatic	struct cert_info *crypto_cert P((char *));
16182498Srobertostatic	void	crypto_tai	P((char *));
16282498Sroberto
163132451Sroberto#ifdef SYS_WINNT
164132451Srobertoint
165132451Srobertoreadlink(char * link, char * file, int len) {
166132451Sroberto	return (-1);
167132451Sroberto}
168132451Sroberto#endif
16982498Sroberto
17082498Sroberto/*
17182498Sroberto * session_key - generate session key
17282498Sroberto *
17382498Sroberto * This routine generates a session key from the source address,
17482498Sroberto * destination address, key ID and private value. The value of the
17582498Sroberto * session key is the MD5 hash of these values, while the next key ID is
17682498Sroberto * the first four octets of the hash.
177132451Sroberto *
178132451Sroberto * Returns the next key ID
17982498Sroberto */
180132451Srobertokeyid_t
18182498Srobertosession_key(
182132451Sroberto	struct sockaddr_storage *srcadr, /* source address */
183132451Sroberto	struct sockaddr_storage *dstadr, /* destination address */
184132451Sroberto	keyid_t	keyno,		/* key ID */
185132451Sroberto	keyid_t	private,	/* private value */
186132451Sroberto	u_long	lifetime 	/* key lifetime */
18782498Sroberto	)
18882498Sroberto{
189132451Sroberto	EVP_MD_CTX ctx;		/* message digest context */
190132451Sroberto	u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
191132451Sroberto	keyid_t	keyid;		/* key identifer */
192132451Sroberto	u_int32	header[10];	/* data in network byte order */
193132451Sroberto	u_int	hdlen, len;
19482498Sroberto
19582498Sroberto	/*
19682498Sroberto	 * Generate the session key and key ID. If the lifetime is
19782498Sroberto	 * greater than zero, install the key and call it trusted.
19882498Sroberto	 */
199132451Sroberto	hdlen = 0;
200132451Sroberto	switch(srcadr->ss_family) {
201132451Sroberto	case AF_INET:
202132451Sroberto		header[0] = ((struct sockaddr_in *)srcadr)->sin_addr.s_addr;
203132451Sroberto		header[1] = ((struct sockaddr_in *)dstadr)->sin_addr.s_addr;
204132451Sroberto		header[2] = htonl(keyno);
205132451Sroberto		header[3] = htonl(private);
206132451Sroberto		hdlen = 4 * sizeof(u_int32);
207132451Sroberto		break;
208132451Sroberto	case AF_INET6:
209132451Sroberto		memcpy(&header[0], &GET_INADDR6(*srcadr),
210132451Sroberto		    sizeof(struct in6_addr));
211132451Sroberto		memcpy(&header[4], &GET_INADDR6(*dstadr),
212132451Sroberto		    sizeof(struct in6_addr));
213132451Sroberto		header[8] = htonl(keyno);
214132451Sroberto		header[9] = htonl(private);
215132451Sroberto		hdlen = 10 * sizeof(u_int32);
216132451Sroberto		break;
217132451Sroberto	}
218132451Sroberto	EVP_DigestInit(&ctx, EVP_md5());
219132451Sroberto	EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
220132451Sroberto	EVP_DigestFinal(&ctx, dgst, &len);
221132451Sroberto	memcpy(&keyid, dgst, 4);
22282498Sroberto	keyid = ntohl(keyid);
22382498Sroberto	if (lifetime != 0) {
224132451Sroberto		MD5auth_setkey(keyno, dgst, len);
22582498Sroberto		authtrust(keyno, lifetime);
22682498Sroberto	}
22782498Sroberto#ifdef DEBUG
22882498Sroberto	if (debug > 1)
22982498Sroberto		printf(
23082498Sroberto		    "session_key: %s > %s %08x %08x hash %08x life %lu\n",
231132451Sroberto		    stoa(srcadr), stoa(dstadr), keyno,
23282498Sroberto		    private, keyid, lifetime);
23382498Sroberto#endif
23482498Sroberto	return (keyid);
23582498Sroberto}
23682498Sroberto
23782498Sroberto
23882498Sroberto/*
23982498Sroberto * make_keylist - generate key list
24082498Sroberto *
24182498Sroberto * This routine constructs a pseudo-random sequence by repeatedly
24282498Sroberto * hashing the session key starting from a given source address,
24382498Sroberto * destination address, private value and the next key ID of the
24482498Sroberto * preceeding session key. The last entry on the list is saved along
24582498Sroberto * with its sequence number and public signature.
24682498Sroberto */
24782498Srobertovoid
24882498Srobertomake_keylist(
24982498Sroberto	struct peer *peer,	/* peer structure pointer */
25082498Sroberto	struct interface *dstadr /* interface */
25182498Sroberto	)
25282498Sroberto{
253132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
254132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
25582498Sroberto	struct autokey *ap;	/* autokey pointer */
256132451Sroberto	struct value *vp;	/* value pointer */
257132451Sroberto	keyid_t	keyid = 0;	/* next key ID */
258132451Sroberto	keyid_t	cookie;		/* private value */
259132451Sroberto	u_long	lifetime;
260132451Sroberto	u_int	len;
261132451Sroberto	int	i;
26282498Sroberto
26382498Sroberto	/*
26482498Sroberto	 * Allocate the key list if necessary.
26582498Sroberto	 */
266132451Sroberto	tstamp = crypto_time();
26782498Sroberto	if (peer->keylist == NULL)
268132451Sroberto		peer->keylist = emalloc(sizeof(keyid_t) *
26982498Sroberto		    NTP_MAXSESSION);
27082498Sroberto
27182498Sroberto	/*
27282498Sroberto	 * Generate an initial key ID which is unique and greater than
27382498Sroberto	 * NTP_MAXKEY.
27482498Sroberto	 */
27582498Sroberto	while (1) {
27682498Sroberto		keyid = (u_long)RANDOM & 0xffffffff;
27782498Sroberto		if (keyid <= NTP_MAXKEY)
27882498Sroberto			continue;
27982498Sroberto		if (authhavekey(keyid))
28082498Sroberto			continue;
28182498Sroberto		break;
28282498Sroberto	}
28382498Sroberto
28482498Sroberto	/*
28582498Sroberto	 * Generate up to NTP_MAXSESSION session keys. Stop if the
28682498Sroberto	 * next one would not be unique or not a session key ID or if
28782498Sroberto	 * it would expire before the next poll. The private value
28882498Sroberto	 * included in the hash is zero if broadcast mode, the peer
28982498Sroberto	 * cookie if client mode or the host cookie if symmetric modes.
29082498Sroberto	 */
291132451Sroberto	lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION * (1 <<(peer->kpoll)));
29282498Sroberto	if (peer->hmode == MODE_BROADCAST)
29382498Sroberto		cookie = 0;
29482498Sroberto	else
295132451Sroberto		cookie = peer->pcookie;
29682498Sroberto	for (i = 0; i < NTP_MAXSESSION; i++) {
29782498Sroberto		peer->keylist[i] = keyid;
29882498Sroberto		peer->keynumber = i;
29982498Sroberto		keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
300132451Sroberto		    cookie, lifetime);
301132451Sroberto		lifetime -= 1 << peer->kpoll;
30282498Sroberto		if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
303132451Sroberto		    lifetime <= (unsigned long)(1 << (peer->kpoll)))
30482498Sroberto			break;
30582498Sroberto	}
30682498Sroberto
30782498Sroberto	/*
30882498Sroberto	 * Save the last session key ID, sequence number and timestamp,
30982498Sroberto	 * then sign these values for later retrieval by the clients. Be
310132451Sroberto	 * careful not to use invalid key media. Use the public values
311132451Sroberto	 * timestamp as filestamp.
31282498Sroberto	 */
313132451Sroberto	vp = &peer->sndval;
314132451Sroberto	if (vp->ptr == NULL)
315132451Sroberto		vp->ptr = emalloc(sizeof(struct autokey));
316132451Sroberto	ap = (struct autokey *)vp->ptr;
31782498Sroberto	ap->seq = htonl(peer->keynumber);
31882498Sroberto	ap->key = htonl(keyid);
319132451Sroberto	vp->tstamp = htonl(tstamp);
320132451Sroberto	vp->fstamp = hostval.tstamp;
321132451Sroberto	vp->vallen = htonl(sizeof(struct autokey));
322132451Sroberto	vp->siglen = 0;
323132451Sroberto	if (vp->tstamp != 0) {
324132451Sroberto		if (vp->sig == NULL)
325132451Sroberto			vp->sig = emalloc(sign_siglen);
326132451Sroberto		EVP_SignInit(&ctx, sign_digest);
327132451Sroberto		EVP_SignUpdate(&ctx, (u_char *)vp, 12);
328132451Sroberto		EVP_SignUpdate(&ctx, vp->ptr, sizeof(struct autokey));
329132451Sroberto		if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
330132451Sroberto			vp->siglen = htonl(len);
331132451Sroberto		else
332132451Sroberto			msyslog(LOG_ERR, "make_keys %s\n",
333132451Sroberto			    ERR_error_string(ERR_get_error(), NULL));
334132451Sroberto		peer->flags |= FLAG_ASSOC;
335132451Sroberto	}
336132451Sroberto#ifdef DEBUG
33782498Sroberto	if (debug)
338132451Sroberto		printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
33982498Sroberto		    ntohl(ap->seq), ntohl(ap->key), cookie,
340132451Sroberto		    ntohl(vp->tstamp), ntohl(vp->fstamp), peer->kpoll);
34182498Sroberto#endif
34282498Sroberto}
34382498Sroberto
34482498Sroberto
34582498Sroberto/*
34682498Sroberto * crypto_recv - parse extension fields
34782498Sroberto *
34882498Sroberto * This routine is called when the packet has been matched to an
34982498Sroberto * association and passed sanity, format and MAC checks. We believe the
35082498Sroberto * extension field values only if the field has proper format and
35182498Sroberto * length, the timestamp and filestamp are valid and the signature has
35282498Sroberto * valid length and is verified. There are a few cases where some values
353132451Sroberto * are believed even if the signature fails, but only if the proventic
35482498Sroberto * bit is not set.
35582498Sroberto */
356132451Srobertoint
35782498Srobertocrypto_recv(
35882498Sroberto	struct peer *peer,	/* peer structure pointer */
35982498Sroberto	struct recvbuf *rbufp	/* packet buffer pointer */
36082498Sroberto	)
36182498Sroberto{
362132451Sroberto	const EVP_MD *dp;	/* message digest algorithm */
363132451Sroberto	u_int32	*pkt;		/* receive packet pointer */
364132451Sroberto	struct autokey *ap, *bp; /* autokey pointer */
365132451Sroberto	struct exten *ep, *fp;	/* extension pointers */
366132451Sroberto	int	has_mac;	/* length of MAC field */
367132451Sroberto	int	authlen;	/* offset of MAC field */
368132451Sroberto	associd_t associd;	/* association ID */
369132451Sroberto	tstamp_t tstamp = 0;	/* timestamp */
370132451Sroberto	tstamp_t fstamp = 0;	/* filestamp */
371132451Sroberto	u_int	len;		/* extension field length */
372132451Sroberto	u_int	code;		/* extension field opcode */
373132451Sroberto	u_int	vallen = 0;	/* value length */
374132451Sroberto	X509	*cert;		/* X509 certificate */
375132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
376132451Sroberto	keyid_t	cookie;		/* crumbles */
377132451Sroberto	int	rval = XEVNT_OK;
378132451Sroberto	u_char	*ptr;
379132451Sroberto	u_int32 temp32;
38082498Sroberto#ifdef KERNEL_PLL
38182498Sroberto#if NTP_API > 3
38282498Sroberto	struct timex ntv;	/* kernel interface structure */
38382498Sroberto#endif /* NTP_API */
38482498Sroberto#endif /* KERNEL_PLL */
38582498Sroberto
38682498Sroberto	/*
38782498Sroberto	 * Initialize. Note that the packet has already been checked for
388132451Sroberto	 * valid format and extension field lengths. First extract the
389132451Sroberto	 * field length, command code and association ID in host byte
390132451Sroberto	 * order. These are used with all commands and modes. Then check
391132451Sroberto	 * the version number, which must be 2, and length, which must
392132451Sroberto	 * be at least 8 for requests and VALUE_LEN (24) for responses.
393132451Sroberto	 * Packets that fail either test sink without a trace. The
394132451Sroberto	 * association ID is saved only if nonzero.
39582498Sroberto	 */
39682498Sroberto	authlen = LEN_PKT_NOMAC;
39782498Sroberto	while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
398132451Sroberto		pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
399132451Sroberto		ep = (struct exten *)pkt;
400132451Sroberto		code = ntohl(ep->opcode) & 0xffff0000;
401132451Sroberto		len = ntohl(ep->opcode) & 0x0000ffff;
402132451Sroberto		associd = (associd_t) ntohl(pkt[1]);
403132451Sroberto		rval = XEVNT_OK;
40482498Sroberto#ifdef DEBUG
40582498Sroberto		if (debug)
40682498Sroberto			printf(
407132451Sroberto			    "crypto_recv: flags 0x%x ext offset %d len %u code %x assocID %d\n",
408132451Sroberto			    peer->crypto, authlen, len, code >> 16,
409132451Sroberto			    associd);
41082498Sroberto#endif
411132451Sroberto
412132451Sroberto		/*
413132451Sroberto		 * Check version number and field length. If bad,
414132451Sroberto		 * quietly ignore the packet.
415132451Sroberto		 */
416132451Sroberto		if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8 ||
417132451Sroberto		    (len < VALUE_LEN && (code & CRYPTO_RESP))) {
418132451Sroberto			sys_unknownversion++;
419132451Sroberto			code |= CRYPTO_ERROR;
420132451Sroberto		}
421132451Sroberto
422132451Sroberto		/*
423132451Sroberto		 * Little vulnerability bandage here. If a perp tosses a
424132451Sroberto		 * fake association ID over the fence, we better toss it
425132451Sroberto		 * out. Only the first one counts.
426132451Sroberto		 */
427132451Sroberto		if (code & CRYPTO_RESP) {
428132451Sroberto			if (peer->assoc == 0)
429132451Sroberto				peer->assoc = associd;
430132451Sroberto			else if (peer->assoc != associd)
431132451Sroberto				code |= CRYPTO_ERROR;
432132451Sroberto		}
433132451Sroberto		if (len >= VALUE_LEN) {
434132451Sroberto			tstamp = ntohl(ep->tstamp);
435132451Sroberto			fstamp = ntohl(ep->fstamp);
436132451Sroberto			vallen = ntohl(ep->vallen);
437132451Sroberto		}
43882498Sroberto		switch (code) {
43982498Sroberto
44082498Sroberto		/*
441132451Sroberto		 * Install status word, host name, signature scheme and
442132451Sroberto		 * association ID. In OpenSSL the signature algorithm is
443132451Sroberto		 * bound to the digest algorithm, so the NID completely
444132451Sroberto		 * defines the signature scheme. Note the request and
445132451Sroberto		 * response are identical, but neither is validated by
446132451Sroberto		 * signature. The request is processed here only in
447132451Sroberto		 * symmetric modes. The server name field would be
448132451Sroberto		 * useful to implement access controls in future.
44982498Sroberto		 */
450132451Sroberto		case CRYPTO_ASSOC:
451132451Sroberto
452132451Sroberto			/*
453132451Sroberto			 * Pass the extension field to the transmit
454132451Sroberto			 * side.
455132451Sroberto			 */
456132451Sroberto			fp = emalloc(len);
457132451Sroberto			memcpy(fp, ep, len);
458132451Sroberto			temp32 = CRYPTO_RESP;
459132451Sroberto			fp->opcode |= htonl(temp32);
460132451Sroberto			peer->cmmd = fp;
461132451Sroberto			/* fall through */
462132451Sroberto
46382498Sroberto		case CRYPTO_ASSOC | CRYPTO_RESP:
464132451Sroberto
465132451Sroberto			/*
466132451Sroberto			 * Discard the message if it has already been
467132451Sroberto			 * stored or the server is not synchronized.
468132451Sroberto			 */
469132451Sroberto			if (peer->crypto || !fstamp)
470132451Sroberto				break;
471132451Sroberto
472132451Sroberto			if (len < VALUE_LEN + vallen) {
473132451Sroberto				rval = XEVNT_LEN;
474132451Sroberto				break;
47582498Sroberto			}
476132451Sroberto
477132451Sroberto			/*
478132451Sroberto			 * Check the identity schemes are compatible. If
479132451Sroberto			 * the client has PC, the server must have PC,
480132451Sroberto			 * in which case the server public key and
481132451Sroberto			 * identity are presumed valid, so we skip the
482132451Sroberto			 * certificate and identity exchanges and move
483132451Sroberto			 * immediately to the cookie exchange which
484132451Sroberto			 * confirms the server signature. If the client
485132451Sroberto			 * has IFF or GC or both, the server must have
486132451Sroberto			 * the same one or both. Otherwise, the default
487132451Sroberto			 * TC scheme is used.
488132451Sroberto			 */
489132451Sroberto			if (crypto_flags & CRYPTO_FLAG_PRIV) {
490132451Sroberto				if (!(fstamp & CRYPTO_FLAG_PRIV))
491132451Sroberto					rval = XEVNT_KEY;
492132451Sroberto				else
493132451Sroberto					fstamp |= CRYPTO_FLAG_VALID |
494132451Sroberto					    CRYPTO_FLAG_VRFY;
495132451Sroberto			} else if (crypto_flags & CRYPTO_FLAG_MASK &&
496132451Sroberto			    !(crypto_flags & fstamp &
497132451Sroberto			    CRYPTO_FLAG_MASK)) {
498132451Sroberto				rval = XEVNT_KEY;
499132451Sroberto			}
500132451Sroberto
501132451Sroberto			/*
502132451Sroberto			 * Discard the message if identity error.
503132451Sroberto			 */
504132451Sroberto			if (rval != XEVNT_OK)
505132451Sroberto				break;
506132451Sroberto
507132451Sroberto			/*
508132451Sroberto			 * Discard the message if the host name length
509132451Sroberto			 * is unreasonable or the signature digest NID
510132451Sroberto			 * is not supported.
511132451Sroberto			 */
512132451Sroberto			temp32 = (fstamp >> 16) & 0xffff;
513132451Sroberto			dp =
514132451Sroberto			    (const EVP_MD *)EVP_get_digestbynid(temp32);
515132451Sroberto			if (vallen == 0 || vallen > MAXHOSTNAME)
516132451Sroberto				rval = XEVNT_LEN;
517132451Sroberto			else if (dp == NULL)
518132451Sroberto				rval = XEVNT_MD;
519132451Sroberto			if (rval != XEVNT_OK)
520132451Sroberto				break;
521132451Sroberto
522132451Sroberto			/*
523132451Sroberto			 * Save status word, host name and message
524132451Sroberto			 * digest/signature type. If PC identity, be
525132451Sroberto			 * sure not to sign the certificate.
526132451Sroberto			 */
527132451Sroberto			if (crypto_flags & CRYPTO_FLAG_PRIV)
528132451Sroberto				fstamp |= CRYPTO_FLAG_SIGN;
529132451Sroberto			peer->crypto = fstamp;
530132451Sroberto			peer->digest = dp;
531132451Sroberto			peer->subject = emalloc(vallen + 1);
532132451Sroberto			memcpy(peer->subject, ep->pkt, vallen);
533132451Sroberto			peer->subject[vallen] = '\0';
534132451Sroberto			peer->issuer = emalloc(vallen + 1);
535132451Sroberto			strcpy(peer->issuer, peer->subject);
536132451Sroberto			temp32 = (fstamp >> 16) & 0xffff;
537132451Sroberto			sprintf(statstr,
538132451Sroberto			    "flags 0x%x host %s signature %s", fstamp,
539132451Sroberto			    peer->subject, OBJ_nid2ln(temp32));
540132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
54182498Sroberto#ifdef DEBUG
54282498Sroberto			if (debug)
543132451Sroberto				printf("crypto_recv: %s\n", statstr);
54482498Sroberto#endif
54582498Sroberto			break;
54682498Sroberto
54782498Sroberto		/*
548132451Sroberto		 * Decode X509 certificate in ASN.1 format and extract
549132451Sroberto		 * the data containing, among other things, subject
550132451Sroberto		 * name and public key. In the default identification
551132451Sroberto		 * scheme, the certificate trail is followed to a self
552132451Sroberto		 * signed trusted certificate.
55382498Sroberto		 */
554132451Sroberto		case CRYPTO_CERT | CRYPTO_RESP:
555132451Sroberto
556132451Sroberto			/*
557132451Sroberto			 * Discard the message if invalid or identity
558132451Sroberto			 * already confirmed.
559132451Sroberto			 */
560132451Sroberto			if (peer->crypto & CRYPTO_FLAG_VRFY)
561132451Sroberto				break;
562132451Sroberto
563132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
564132451Sroberto			    XEVNT_OK)
565132451Sroberto				break;
566132451Sroberto
567132451Sroberto			/*
568132451Sroberto			 * Scan the certificate list to delete old
569132451Sroberto			 * versions and link the newest version first on
570132451Sroberto			 * the list.
571132451Sroberto			 */
572132451Sroberto			if ((rval = cert_install(ep, peer)) != XEVNT_OK)
573132451Sroberto				break;
574132451Sroberto
575132451Sroberto			/*
576132451Sroberto			 * If we snatch the certificate before the
577132451Sroberto			 * server certificate has been signed by its
578132451Sroberto			 * server, it will be self signed. When it is,
579132451Sroberto			 * we chase the certificate issuer, which the
580132451Sroberto			 * server has, and keep going until a self
581132451Sroberto			 * signed trusted certificate is found. Be sure
582132451Sroberto			 * to update the issuer field, since it may
583132451Sroberto			 * change.
584132451Sroberto			 */
585132451Sroberto			if (peer->issuer != NULL)
586132451Sroberto				free(peer->issuer);
587132451Sroberto			peer->issuer = emalloc(strlen(cinfo->issuer) +
588132451Sroberto			    1);
589132451Sroberto			strcpy(peer->issuer, cinfo->issuer);
590132451Sroberto
591132451Sroberto			/*
592132451Sroberto			 * We plug in the public key and group key in
593132451Sroberto			 * the first certificate received. However, note
594132451Sroberto			 * that this certificate might not be signed by
595132451Sroberto			 * the server, so we can't check the
596132451Sroberto			 * signature/digest NID.
597132451Sroberto			 */
598132451Sroberto			if (peer->pkey == NULL) {
599132451Sroberto				ptr = (u_char *)cinfo->cert.ptr;
600132451Sroberto				cert = d2i_X509(NULL, &ptr,
601132451Sroberto				    ntohl(cinfo->cert.vallen));
602132451Sroberto				peer->pkey = X509_get_pubkey(cert);
603132451Sroberto				X509_free(cert);
60482498Sroberto			}
605132451Sroberto			peer->flash &= ~TEST10;
606132451Sroberto			temp32 = cinfo->nid;
607132451Sroberto			sprintf(statstr, "cert %s 0x%x %s (%u) fs %u",
608132451Sroberto			    cinfo->subject, cinfo->flags,
609132451Sroberto			    OBJ_nid2ln(temp32), temp32,
610132451Sroberto			    ntohl(ep->fstamp));
611132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
61282498Sroberto#ifdef DEBUG
61382498Sroberto			if (debug)
614132451Sroberto				printf("crypto_recv: %s\n", statstr);
61582498Sroberto#endif
61682498Sroberto			break;
61782498Sroberto
61882498Sroberto		/*
619132451Sroberto		 * Schnorr (IFF)identity scheme. This scheme is designed
620132451Sroberto		 * for use with shared secret group keys and where the
621132451Sroberto		 * certificate may be generated by a third party. The
622132451Sroberto		 * client sends a challenge to the server, which
623132451Sroberto		 * performs a calculation and returns the result. A
624132451Sroberto		 * positive result is possible only if both client and
625132451Sroberto		 * server contain the same secret group key.
62682498Sroberto		 */
627132451Sroberto		case CRYPTO_IFF | CRYPTO_RESP:
62882498Sroberto
629132451Sroberto			/*
630132451Sroberto			 * Discard the message if invalid or identity
631132451Sroberto			 * already confirmed.
632132451Sroberto			 */
633132451Sroberto			if (peer->crypto & CRYPTO_FLAG_VRFY)
634132451Sroberto				break;
63582498Sroberto
636132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
637132451Sroberto			    XEVNT_OK)
638132451Sroberto				break;
639132451Sroberto
64082498Sroberto			/*
641132451Sroberto			 * If the the challenge matches the response,
642132451Sroberto			 * the certificate public key, as well as the
643132451Sroberto			 * server public key, signatyre and identity are
644132451Sroberto			 * all verified at the same time. The server is
645132451Sroberto			 * declared trusted, so we skip further
646132451Sroberto			 * certificate stages and move immediately to
647132451Sroberto			 * the cookie stage.
64882498Sroberto			 */
649132451Sroberto			if ((rval = crypto_iff(ep, peer)) != XEVNT_OK)
650132451Sroberto				break;
651132451Sroberto
652132451Sroberto			peer->crypto |= CRYPTO_FLAG_VRFY |
653132451Sroberto			    CRYPTO_FLAG_PROV;
654132451Sroberto			peer->flash &= ~TEST10;
655132451Sroberto			sprintf(statstr, "iff fs %u",
656132451Sroberto			    ntohl(ep->fstamp));
657132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
65882498Sroberto#ifdef DEBUG
65982498Sroberto			if (debug)
660132451Sroberto				printf("crypto_recv: %s\n", statstr);
66182498Sroberto#endif
66282498Sroberto			break;
66382498Sroberto
66482498Sroberto		/*
665132451Sroberto		 * Guillou-Quisquater (GQ) identity scheme. This scheme
666132451Sroberto		 * is designed for use with public certificates carrying
667132451Sroberto		 * the GQ public key in an extension field. The client
668132451Sroberto		 * sends a challenge to the server, which performs a
669132451Sroberto		 * calculation and returns the result. A positive result
670132451Sroberto		 * is possible only if both client and server contain
671132451Sroberto		 * the same group key and the server has the matching GQ
672132451Sroberto		 * private key.
67382498Sroberto		 */
674132451Sroberto		case CRYPTO_GQ | CRYPTO_RESP:
675132451Sroberto
676132451Sroberto			/*
677132451Sroberto			 * Discard the message if invalid or identity
678132451Sroberto			 * already confirmed.
679132451Sroberto			 */
680132451Sroberto			if (peer->crypto & CRYPTO_FLAG_VRFY)
68182498Sroberto				break;
682132451Sroberto
683132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
684132451Sroberto			    XEVNT_OK)
685132451Sroberto				break;
686132451Sroberto
687132451Sroberto			/*
688132451Sroberto			 * If the the challenge matches the response,
689132451Sroberto			 * the certificate public key, as well as the
690132451Sroberto			 * server public key, signatyre and identity are
691132451Sroberto			 * all verified at the same time. The server is
692132451Sroberto			 * declared trusted, so we skip further
693132451Sroberto			 * certificate stages and move immediately to
694132451Sroberto			 * the cookie stage.
695132451Sroberto			 */
696132451Sroberto			if ((rval = crypto_gq(ep, peer)) != XEVNT_OK)
697132451Sroberto				break;
698132451Sroberto
699132451Sroberto			peer->crypto |= CRYPTO_FLAG_VRFY |
700132451Sroberto			    CRYPTO_FLAG_PROV;
701132451Sroberto			peer->flash &= ~TEST10;
702132451Sroberto			sprintf(statstr, "gq fs %u",
703132451Sroberto			    ntohl(ep->fstamp));
704132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
70582498Sroberto#ifdef DEBUG
70682498Sroberto			if (debug)
707132451Sroberto				printf("crypto_recv: %s\n", statstr);
70882498Sroberto#endif
70982498Sroberto			break;
71082498Sroberto
71182498Sroberto		/*
712132451Sroberto		 * MV
71382498Sroberto		 */
714132451Sroberto		case CRYPTO_MV | CRYPTO_RESP:
715132451Sroberto
716132451Sroberto			/*
717132451Sroberto			 * Discard the message if invalid or identity
718132451Sroberto			 * already confirmed.
719132451Sroberto			 */
720132451Sroberto			if (peer->crypto & CRYPTO_FLAG_VRFY)
72182498Sroberto				break;
722132451Sroberto
723132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
724132451Sroberto			    XEVNT_OK)
725132451Sroberto				break;
726132451Sroberto
727132451Sroberto			/*
728132451Sroberto			 * If the the challenge matches the response,
729132451Sroberto			 * the certificate public key, as well as the
730132451Sroberto			 * server public key, signatyre and identity are
731132451Sroberto			 * all verified at the same time. The server is
732132451Sroberto			 * declared trusted, so we skip further
733132451Sroberto			 * certificate stages and move immediately to
734132451Sroberto			 * the cookie stage.
735132451Sroberto			 */
736132451Sroberto			if ((rval = crypto_mv(ep, peer)) != XEVNT_OK)
737132451Sroberto				break;
738132451Sroberto
739132451Sroberto			peer->crypto |= CRYPTO_FLAG_VRFY |
740132451Sroberto			    CRYPTO_FLAG_PROV;
741132451Sroberto			peer->flash &= ~TEST10;
742132451Sroberto			sprintf(statstr, "mv fs %u",
743132451Sroberto			    ntohl(ep->fstamp));
744132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
74582498Sroberto#ifdef DEBUG
74682498Sroberto			if (debug)
747132451Sroberto				printf("crypto_recv: %s\n", statstr);
74882498Sroberto#endif
749132451Sroberto			break;
750132451Sroberto
751132451Sroberto		/*
752132451Sroberto		 * X509 certificate sign response. Validate the
753132451Sroberto		 * certificate signed by the server and install. Later
754132451Sroberto		 * this can be provided to clients of this server in
755132451Sroberto		 * lieu of the self signed certificate in order to
756132451Sroberto		 * validate the public key.
757132451Sroberto		 */
758132451Sroberto		case CRYPTO_SIGN | CRYPTO_RESP:
75982498Sroberto
76082498Sroberto			/*
761132451Sroberto			 * Discard the message if invalid or identity
762132451Sroberto			 * not confirmed.
76382498Sroberto			 */
764132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
76582498Sroberto				break;
76682498Sroberto
767132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
768132451Sroberto			    XEVNT_OK)
769132451Sroberto				break;
770132451Sroberto
77182498Sroberto			/*
772132451Sroberto			 * Scan the certificate list to delete old
773132451Sroberto			 * versions and link the newest version first on
774132451Sroberto			 * the list.
77582498Sroberto			 */
776132451Sroberto			if ((rval = cert_install(ep, peer)) != XEVNT_OK) 				break;
777132451Sroberto
778132451Sroberto			peer->crypto |= CRYPTO_FLAG_SIGN;
779132451Sroberto			peer->flash &= ~TEST10;
780132451Sroberto			temp32 = cinfo->nid;
781132451Sroberto			sprintf(statstr, "sign %s 0x%x %s (%u) fs %u",
782132451Sroberto			    cinfo->issuer, cinfo->flags,
783132451Sroberto			    OBJ_nid2ln(temp32), temp32,
784132451Sroberto			    ntohl(ep->fstamp));
785132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
786132451Sroberto#ifdef DEBUG
787132451Sroberto			if (debug)
788132451Sroberto				printf("crypto_recv: %s\n", statstr);
789132451Sroberto#endif
79082498Sroberto			break;
79182498Sroberto
79282498Sroberto		/*
793132451Sroberto		 * Cookie request in symmetric modes. Roll a random
794132451Sroberto		 * cookie and install in symmetric mode. Encrypt for the
795132451Sroberto		 * response, which is transmitted later.
79682498Sroberto		 */
797132451Sroberto		case CRYPTO_COOK:
798132451Sroberto
799132451Sroberto			/*
800132451Sroberto			 * Discard the message if invalid or identity
801132451Sroberto			 * not confirmed.
802132451Sroberto			 */
803132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
80482498Sroberto				break;
805132451Sroberto
806132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
807132451Sroberto			    XEVNT_OK)
808132451Sroberto				break;
809132451Sroberto
810132451Sroberto			/*
811132451Sroberto			 * Pass the extension field to the transmit
812132451Sroberto			 * side. If already agreed, walk away.
813132451Sroberto			 */
814132451Sroberto			fp = emalloc(len);
815132451Sroberto			memcpy(fp, ep, len);
816132451Sroberto			temp32 = CRYPTO_RESP;
817132451Sroberto			fp->opcode |= htonl(temp32);
818132451Sroberto			peer->cmmd = fp;
819132451Sroberto			if (peer->crypto & CRYPTO_FLAG_AGREE) {
820132451Sroberto				peer->flash &= ~TEST10;
821132451Sroberto				break;
82282498Sroberto			}
823132451Sroberto
824132451Sroberto			/*
825132451Sroberto			 * Install cookie values and light the cookie
826132451Sroberto			 * bit. The transmit side will pick up and
827132451Sroberto			 * encrypt it for the response.
828132451Sroberto			 */
829132451Sroberto			key_expire(peer);
830132451Sroberto			peer->cookval.tstamp = ep->tstamp;
831132451Sroberto			peer->cookval.fstamp = ep->fstamp;
832132451Sroberto			RAND_bytes((u_char *)&peer->pcookie, 4);
833132451Sroberto			peer->crypto &= ~CRYPTO_FLAG_AUTO;
834132451Sroberto			peer->crypto |= CRYPTO_FLAG_AGREE;
835132451Sroberto			peer->flash &= ~TEST10;
836132451Sroberto			sprintf(statstr, "cook %x ts %u fs %u",
837132451Sroberto			    peer->pcookie, ntohl(ep->tstamp),
838132451Sroberto			    ntohl(ep->fstamp));
839132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
84082498Sroberto#ifdef DEBUG
84182498Sroberto			if (debug)
842132451Sroberto				printf("crypto_recv: %s\n", statstr);
84382498Sroberto#endif
844132451Sroberto			break;
84582498Sroberto
846132451Sroberto		/*
847132451Sroberto		 * Cookie response in client and symmetric modes. If the
848132451Sroberto		 * cookie bit is set, the working cookie is the EXOR of
849132451Sroberto		 * the current and new values.
850132451Sroberto		 */
851132451Sroberto		case CRYPTO_COOK | CRYPTO_RESP:
852132451Sroberto
85382498Sroberto			/*
854132451Sroberto			 * Discard the message if invalid or identity
855132451Sroberto			 * not confirmed or signature not verified with
856132451Sroberto			 * respect to the cookie values.
85782498Sroberto			 */
858132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
85982498Sroberto				break;
86082498Sroberto
861132451Sroberto			if ((rval = crypto_verify(ep, &peer->cookval,
862132451Sroberto			    peer)) != XEVNT_OK)
863132451Sroberto				break;
864132451Sroberto
86582498Sroberto			/*
866132451Sroberto			 * Decrypt the cookie, hunting all the time for
867132451Sroberto			 * errors.
86882498Sroberto			 */
869132451Sroberto			if (vallen == (u_int) EVP_PKEY_size(host_pkey)) {
870132451Sroberto				RSA_private_decrypt(vallen,
871132451Sroberto				    (u_char *)ep->pkt,
872132451Sroberto				    (u_char *)&temp32,
873132451Sroberto				    host_pkey->pkey.rsa,
874132451Sroberto				    RSA_PKCS1_OAEP_PADDING);
875132451Sroberto				cookie = ntohl(temp32);
876132451Sroberto			} else {
877132451Sroberto				rval = XEVNT_CKY;
878132451Sroberto				break;
879132451Sroberto			}
88082498Sroberto
88182498Sroberto			/*
882132451Sroberto			 * Install cookie values and light the cookie
883132451Sroberto			 * bit. If this is not broadcast client mode, we
884132451Sroberto			 * are done here.
88582498Sroberto			 */
886132451Sroberto			key_expire(peer);
887132451Sroberto			peer->cookval.tstamp = ep->tstamp;
888132451Sroberto			peer->cookval.fstamp = ep->fstamp;
889132451Sroberto			if (peer->crypto & CRYPTO_FLAG_AGREE)
890132451Sroberto				peer->pcookie ^= cookie;
891132451Sroberto			else
892132451Sroberto				peer->pcookie = cookie;
893132451Sroberto			if (peer->hmode == MODE_CLIENT &&
894132451Sroberto			    !(peer->cast_flags & MDF_BCLNT))
895132451Sroberto				peer->crypto |= CRYPTO_FLAG_AUTO;
896132451Sroberto			else
897132451Sroberto				peer->crypto &= ~CRYPTO_FLAG_AUTO;
898132451Sroberto			peer->crypto |= CRYPTO_FLAG_AGREE;
899132451Sroberto			peer->flash &= ~TEST10;
900132451Sroberto			sprintf(statstr, "cook %x ts %u fs %u",
901132451Sroberto			    peer->pcookie, ntohl(ep->tstamp),
902132451Sroberto			    ntohl(ep->fstamp));
903132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
904132451Sroberto#ifdef DEBUG
905132451Sroberto			if (debug)
906132451Sroberto				printf("crypto_recv: %s\n", statstr);
907132451Sroberto#endif
90882498Sroberto			break;
90982498Sroberto
91082498Sroberto		/*
911132451Sroberto		 * Install autokey values in broadcast client and
912132451Sroberto		 * symmetric modes. We have to do this every time the
913132451Sroberto		 * sever/peer cookie changes or a new keylist is
914132451Sroberto		 * rolled. Ordinarily, this is automatic as this message
915132451Sroberto		 * is piggybacked on the first NTP packet sent upon
916132451Sroberto		 * either of these events. Note that a broadcast client
917132451Sroberto		 * or symmetric peer can receive this response without a
918132451Sroberto		 * matching request.
91982498Sroberto		 */
920132451Sroberto		case CRYPTO_AUTO | CRYPTO_RESP:
92182498Sroberto
922132451Sroberto			/*
923132451Sroberto			 * Discard the message if invalid or identity
924132451Sroberto			 * not confirmed or signature not verified with
925132451Sroberto			 * respect to the receive autokey values.
926132451Sroberto			 */
927132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
92882498Sroberto				break;
92982498Sroberto
930132451Sroberto			if ((rval = crypto_verify(ep, &peer->recval,
931132451Sroberto			    peer)) != XEVNT_OK)
932132451Sroberto				break;
933132451Sroberto
93482498Sroberto			/*
935132451Sroberto			 * Install autokey values and light the
936132451Sroberto			 * autokey bit. This is not hard.
93782498Sroberto			 */
938132451Sroberto			if (peer->recval.ptr == NULL)
939132451Sroberto				peer->recval.ptr =
940132451Sroberto				    emalloc(sizeof(struct autokey));
941132451Sroberto			bp = (struct autokey *)peer->recval.ptr;
942132451Sroberto			peer->recval.tstamp = ep->tstamp;
943132451Sroberto			peer->recval.fstamp = ep->fstamp;
944132451Sroberto			ap = (struct autokey *)ep->pkt;
945132451Sroberto			bp->seq = ntohl(ap->seq);
946132451Sroberto			bp->key = ntohl(ap->key);
947132451Sroberto			peer->pkeyid = bp->key;
948132451Sroberto			peer->crypto |= CRYPTO_FLAG_AUTO;
949132451Sroberto			peer->flash &= ~TEST10;
950132451Sroberto			sprintf(statstr,
951132451Sroberto			    "auto seq %d key %x ts %u fs %u", bp->seq,
952132451Sroberto			    bp->key, ntohl(ep->tstamp),
953132451Sroberto			    ntohl(ep->fstamp));
954132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
95582498Sroberto#ifdef DEBUG
95682498Sroberto			if (debug)
957132451Sroberto				printf("crypto_recv: %s\n", statstr);
95882498Sroberto#endif
95982498Sroberto			break;
96082498Sroberto
96182498Sroberto		/*
962132451Sroberto		 * Install leapseconds table in symmetric modes. This
963132451Sroberto		 * table is proventicated to the NIST primary servers,
964132451Sroberto		 * either by copying the file containing the table from
965132451Sroberto		 * a NIST server to a trusted server or directly using
966132451Sroberto		 * this protocol. While the entire table is installed at
967132451Sroberto		 * the server, presently only the current TAI offset is
968132451Sroberto		 * provided via the kernel to other applications.
96982498Sroberto		 */
970132451Sroberto		case CRYPTO_TAI:
971132451Sroberto
972132451Sroberto			/*
973132451Sroberto			 * Discard the message if invalid or identity
974132451Sroberto			 * not confirmed.
975132451Sroberto			 */
976132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
97782498Sroberto				break;
978132451Sroberto
979132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
980132451Sroberto			    XEVNT_OK)
981132451Sroberto				break;
982132451Sroberto
983132451Sroberto			/*
984132451Sroberto			 * Pass the extension field to the transmit
985132451Sroberto			 * side. Continue below if a leapseconds table
986132451Sroberto			 * accompanies the message.
987132451Sroberto			 */
988132451Sroberto			fp = emalloc(len);
989132451Sroberto			memcpy(fp, ep, len);
990132451Sroberto			temp32 = CRYPTO_RESP;
991132451Sroberto			fp->opcode |= htonl(temp32);
992132451Sroberto			peer->cmmd = fp;
993132451Sroberto			if (len <= VALUE_LEN) {
994132451Sroberto				peer->flash &= ~TEST10;
995132451Sroberto				break;
99682498Sroberto			}
997132451Sroberto			/* fall through */
99882498Sroberto
999132451Sroberto		case CRYPTO_TAI | CRYPTO_RESP:
1000132451Sroberto
100182498Sroberto			/*
1002132451Sroberto			 * Discard the message if invalid or identity
1003132451Sroberto			 * not confirmed or signature not verified with
1004132451Sroberto			 * respect to the leapsecond table values.
100582498Sroberto			 */
1006132451Sroberto			if (!(peer->crypto & CRYPTO_FLAG_VRFY))
100782498Sroberto				break;
1008132451Sroberto
1009132451Sroberto			if ((rval = crypto_verify(ep, &peer->tai_leap,
1010132451Sroberto			    peer)) != XEVNT_OK)
1011132451Sroberto				break;
1012132451Sroberto
1013132451Sroberto			/*
1014132451Sroberto			 * Initialize peer variables, leapseconds
1015132451Sroberto			 * structure and extension field in network byte
1016132451Sroberto			 * order. Since a filestamp may have changed,
1017132451Sroberto			 * recompute the signatures.
1018132451Sroberto			 */
1019132451Sroberto			peer->tai_leap.tstamp = ep->tstamp;
1020132451Sroberto			peer->tai_leap.fstamp = ep->fstamp;
1021132451Sroberto			peer->tai_leap.vallen = ep->vallen;
1022132451Sroberto
1023132451Sroberto			/*
1024132451Sroberto			 * Install the new table if there is no stored
1025132451Sroberto			 * table or the new table is more recent than
1026132451Sroberto			 * the stored table. Since a filestamp may have
1027132451Sroberto			 * changed, recompute the signatures.
1028132451Sroberto			 */
1029132451Sroberto			if (ntohl(peer->tai_leap.fstamp) >
1030132451Sroberto			    ntohl(tai_leap.fstamp)) {
1031132451Sroberto				tai_leap.fstamp = ep->fstamp;
1032132451Sroberto				tai_leap.vallen = ep->vallen;
1033132451Sroberto				if (tai_leap.ptr != NULL)
1034132451Sroberto					free(tai_leap.ptr);
1035132451Sroberto				tai_leap.ptr = emalloc(vallen);
1036132451Sroberto				memcpy(tai_leap.ptr, ep->pkt, vallen);
1037132451Sroberto				crypto_update();
1038132451Sroberto				sys_tai = vallen / 4 + TAI_1972 - 1;
103982498Sroberto			}
1040132451Sroberto			crypto_flags |= CRYPTO_FLAG_TAI;
1041132451Sroberto			peer->crypto |= CRYPTO_FLAG_LEAP;
104282498Sroberto			peer->flash &= ~TEST10;
104382498Sroberto#ifdef KERNEL_PLL
104482498Sroberto#if NTP_API > 3
1045132451Sroberto			/*
1046132451Sroberto			 * If the kernel cooperates, initialize the
1047132451Sroberto			 * current TAI offset.
1048132451Sroberto			 */
104982498Sroberto			ntv.modes = MOD_TAI;
105082498Sroberto			ntv.constant = sys_tai;
1051106163Sroberto			(void)ntp_adjtime(&ntv);
105282498Sroberto#endif /* NTP_API */
105382498Sroberto#endif /* KERNEL_PLL */
1054132451Sroberto			sprintf(statstr, "leap %u ts %u fs %u",
1055132451Sroberto			    vallen, ntohl(ep->tstamp),
1056132451Sroberto			    ntohl(ep->fstamp));
1057132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
1058132451Sroberto#ifdef DEBUG
1059132451Sroberto			if (debug)
1060132451Sroberto				printf("crypto_recv: %s\n", statstr);
1061132451Sroberto#endif
106282498Sroberto			break;
106382498Sroberto
106482498Sroberto		/*
1065132451Sroberto		 * We come here in symmetric modes for miscellaneous
1066132451Sroberto		 * commands that have value fields but are processed on
1067132451Sroberto		 * the transmit side. All we need do here is check for
1068132451Sroberto		 * valid field length. Remaining checks are below and on
1069132451Sroberto		 * the transmit side.
107082498Sroberto		 */
1071132451Sroberto		case CRYPTO_IFF:
1072132451Sroberto		case CRYPTO_GQ:
1073132451Sroberto		case CRYPTO_MV:
1074132451Sroberto		case CRYPTO_SIGN:
1075132451Sroberto			if (len < VALUE_LEN) {
1076132451Sroberto				rval = XEVNT_LEN;
107782498Sroberto				break;
1078132451Sroberto			}
107982498Sroberto
1080132451Sroberto			/* fall through */
1081132451Sroberto
1082132451Sroberto		/*
1083132451Sroberto		 * We come here for miscellaneous requests and unknown
1084132451Sroberto		 * requests and responses. If an unknown response or
1085132451Sroberto		 * error, forget it. If a request, save the extension
1086132451Sroberto		 * field for later. Unknown requests will be caught on
1087132451Sroberto		 * the transmit side.
1088132451Sroberto		 */
1089132451Sroberto		default:
1090132451Sroberto			if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {
1091132451Sroberto				rval = XEVNT_LEN;
1092132451Sroberto			} else if ((rval = crypto_verify(ep, NULL,
1093132451Sroberto			    peer)) == XEVNT_OK) {
1094132451Sroberto				fp = emalloc(len);
1095132451Sroberto				memcpy(fp, ep, len);
1096132451Sroberto				temp32 = CRYPTO_RESP;
1097132451Sroberto				fp->opcode |= htonl(temp32);
1098132451Sroberto				peer->cmmd = fp;
1099132451Sroberto			}
110082498Sroberto		}
1101132451Sroberto
1102132451Sroberto		/*
1103132451Sroberto		 * We log everything except length/format errors and
1104132451Sroberto		 * duplicates, which are log clogging vulnerabilities.
1105132451Sroberto		 * The first error found terminates the extension field
1106132451Sroberto		 * scan and we return the laundry to the caller.
1107132451Sroberto		 */
1108132451Sroberto		if (rval != XEVNT_OK) {
1109132451Sroberto			sprintf(statstr,
1110132451Sroberto			    "error %x opcode %x ts %u fs %u", rval,
1111132451Sroberto			    code, tstamp, fstamp);
1112132451Sroberto			if (rval > XEVNT_TSP)
1113132451Sroberto				record_crypto_stats(&peer->srcadr,
1114132451Sroberto				    statstr);
1115132451Sroberto			report_event(rval, peer);
1116132451Sroberto#ifdef DEBUG
1117132451Sroberto			if (debug)
1118132451Sroberto				printf("crypto_recv: %s\n", statstr);
1119132451Sroberto#endif
1120132451Sroberto			break;
1121132451Sroberto		}
112282498Sroberto		authlen += len;
112382498Sroberto	}
1124132451Sroberto	return (rval);
112582498Sroberto}
112682498Sroberto
112782498Sroberto
112882498Sroberto/*
112982498Sroberto * crypto_xmit - construct extension fields
113082498Sroberto *
113182498Sroberto * This routine is called both when an association is configured and
1132132451Sroberto * when one is not. The only case where this matters is to retrieve the
1133132451Sroberto * autokey information, in which case the caller has to provide the
113482498Sroberto * association ID to match the association.
1135132451Sroberto *
1136132451Sroberto * Returns length of extension field.
113782498Sroberto */
1138132451Srobertoint
113982498Srobertocrypto_xmit(
1140132451Sroberto	struct pkt *xpkt,	/* transmit packet pointer */
1141132451Sroberto	struct sockaddr_storage *srcadr_sin,	/* active runway */
1142132451Sroberto	int	start,		/* offset to extension field */
1143132451Sroberto	struct exten *ep,	/* extension pointer */
1144132451Sroberto	keyid_t cookie		/* session cookie */
114582498Sroberto	)
114682498Sroberto{
1147132451Sroberto	u_int32	*pkt;		/* packet pointer */
114882498Sroberto	struct peer *peer;	/* peer structure pointer */
1149132451Sroberto	u_int	opcode;		/* extension field opcode */
1150132451Sroberto	struct exten *fp;	/* extension pointers */
1151132451Sroberto	struct cert_info *cp;	/* certificate info/value pointer */
1152132451Sroberto	char	certname[MAXHOSTNAME + 1]; /* subject name buffer */
1153132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
1154132451Sroberto	u_int	vallen;
1155132451Sroberto	u_int	len;
1156132451Sroberto	struct value vtemp;
1157132451Sroberto	associd_t associd;
1158132451Sroberto	int	rval;
1159132451Sroberto	keyid_t tcookie;
116082498Sroberto
116182498Sroberto	/*
116282498Sroberto	 * Generate the requested extension field request code, length
1163132451Sroberto	 * and association ID. If this is a response and the host is not
1164132451Sroberto	 * synchronized, light the error bit and go home.
116582498Sroberto	 */
1166132451Sroberto	pkt = (u_int32 *)xpkt + start / 4;
1167132451Sroberto	fp = (struct exten *)pkt;
1168132451Sroberto	opcode = ntohl(ep->opcode);
1169132451Sroberto	associd = (associd_t) ntohl(ep->associd);
1170132451Sroberto	fp->associd = htonl(associd);
117182498Sroberto	len = 8;
1172132451Sroberto	rval = XEVNT_OK;
1173132451Sroberto	switch (opcode & 0xffff0000) {
117482498Sroberto
117582498Sroberto	/*
1176132451Sroberto	 * Send association request and response with status word and
1177132451Sroberto	 * host name. Note, this message is not signed and the filestamp
1178132451Sroberto	 * contains only the status word. We check at this point whether
1179132451Sroberto	 * the identity schemes are compatible to save tears later on.
118082498Sroberto	 */
118182498Sroberto	case CRYPTO_ASSOC | CRYPTO_RESP:
1182132451Sroberto	case CRYPTO_ASSOC:
1183132451Sroberto		len += crypto_send(fp, &hostval);
1184132451Sroberto		if (crypto_time() == 0)
1185132451Sroberto			fp->fstamp = 0;
1186132451Sroberto		else
1187132451Sroberto			fp->fstamp = htonl(crypto_flags);
118882498Sroberto		break;
118982498Sroberto
119082498Sroberto	/*
1191132451Sroberto	 * Send certificate request. Use the values from the extension
1192132451Sroberto	 * field.
119382498Sroberto	 */
1194132451Sroberto	case CRYPTO_CERT:
1195132451Sroberto		memset(&vtemp, 0, sizeof(vtemp));
1196132451Sroberto		vtemp.tstamp = ep->tstamp;
1197132451Sroberto		vtemp.fstamp = ep->fstamp;
1198132451Sroberto		vtemp.vallen = ep->vallen;
1199132451Sroberto		vtemp.ptr = (unsigned char *)ep->pkt;
1200132451Sroberto		len += crypto_send(fp, &vtemp);
1201132451Sroberto		break;
1202132451Sroberto
1203132451Sroberto	/*
1204132451Sroberto	 * Send certificate response or sign request. Use the values
1205132451Sroberto	 * from the certificate. If the request contains no subject
1206132451Sroberto	 * name, assume the name of this host. This is for backwards
1207132451Sroberto	 * compatibility.  Light the error bit if no certificate with
1208132451Sroberto	 * the given subject name is found. Of course, private
1209132451Sroberto	 * certificates are never sent.
1210132451Sroberto	 */
1211132451Sroberto	case CRYPTO_SIGN:
1212132451Sroberto	case CRYPTO_CERT | CRYPTO_RESP:
1213132451Sroberto		vallen = ntohl(ep->vallen);
1214132451Sroberto		if (vallen == 8) {
1215132451Sroberto			strcpy(certname, sys_hostname);
1216132451Sroberto		} else if (vallen == 0 || vallen > MAXHOSTNAME) {
121782498Sroberto			opcode |= CRYPTO_ERROR;
121882498Sroberto			break;
1219132451Sroberto
1220132451Sroberto		} else {
1221132451Sroberto			memcpy(certname, ep->pkt, vallen);
1222132451Sroberto			certname[vallen] = '\0';
122382498Sroberto		}
1224132451Sroberto		for (cp = cinfo; cp != NULL; cp = cp->link) {
1225132451Sroberto			if (cp->flags & CERT_PRIV)
1226132451Sroberto				continue;
1227132451Sroberto			if (strcmp(certname, cp->subject) == 0) {
1228132451Sroberto				len += crypto_send(fp, &cp->cert);
1229132451Sroberto				break;
1230132451Sroberto			}
1231132451Sroberto		}
1232132451Sroberto		if (cp == NULL)
1233132451Sroberto			opcode |= CRYPTO_ERROR;
123482498Sroberto		break;
123582498Sroberto
123682498Sroberto	/*
1237132451Sroberto	 * Send challenge in Schnorr (IFF) identity scheme.
123882498Sroberto	 */
1239132451Sroberto	case CRYPTO_IFF:
1240132451Sroberto		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
1241132451Sroberto			opcode |= CRYPTO_ERROR;
124282498Sroberto			break;
124382498Sroberto		}
1244132451Sroberto		if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK)
1245132451Sroberto			len += crypto_send(fp, &vtemp);
1246132451Sroberto		value_free(&vtemp);
124782498Sroberto		break;
124882498Sroberto
124982498Sroberto	/*
1250132451Sroberto	 * Send response in Schnorr (IFF) identity scheme.
125182498Sroberto	 */
1252132451Sroberto	case CRYPTO_IFF | CRYPTO_RESP:
1253132451Sroberto		if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK)
1254132451Sroberto			len += crypto_send(fp, &vtemp);
1255132451Sroberto		value_free(&vtemp);
1256132451Sroberto		break;
1257132451Sroberto
125882498Sroberto	/*
1259132451Sroberto	 * Send challenge in Guillou-Quisquater (GQ) identity scheme.
126082498Sroberto	 */
1261132451Sroberto	case CRYPTO_GQ:
1262132451Sroberto		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
126382498Sroberto			opcode |= CRYPTO_ERROR;
126482498Sroberto			break;
126582498Sroberto		}
1266132451Sroberto		if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK)
1267132451Sroberto			len += crypto_send(fp, &vtemp);
1268132451Sroberto		value_free(&vtemp);
126982498Sroberto		break;
127082498Sroberto
127182498Sroberto	/*
1272132451Sroberto	 * Send response in Guillou-Quisquater (GQ) identity scheme.
127382498Sroberto	 */
1274132451Sroberto	case CRYPTO_GQ | CRYPTO_RESP:
1275132451Sroberto		if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK)
1276132451Sroberto			len += crypto_send(fp, &vtemp);
1277132451Sroberto		value_free(&vtemp);
1278132451Sroberto		break;
1279132451Sroberto
1280132451Sroberto	/*
1281132451Sroberto	 * Send challenge in MV identity scheme.
1282132451Sroberto	 */
1283132451Sroberto	case CRYPTO_MV:
1284132451Sroberto		if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
128582498Sroberto			opcode |= CRYPTO_ERROR;
128682498Sroberto			break;
128782498Sroberto		}
1288132451Sroberto		if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK)
1289132451Sroberto			len += crypto_send(fp, &vtemp);
1290132451Sroberto		value_free(&vtemp);
129182498Sroberto		break;
129282498Sroberto
129382498Sroberto	/*
1294132451Sroberto	 * Send response in MV identity scheme.
129582498Sroberto	 */
1296132451Sroberto	case CRYPTO_MV | CRYPTO_RESP:
1297132451Sroberto		if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK)
1298132451Sroberto			len += crypto_send(fp, &vtemp);
1299132451Sroberto		value_free(&vtemp);
1300132451Sroberto		break;
1301132451Sroberto
1302132451Sroberto	/*
1303132451Sroberto	 * Send certificate sign response. The integrity of the request
1304132451Sroberto	 * certificate has already been verified on the receive side.
1305132451Sroberto	 * Sign the response using the local server key. Use the
1306132451Sroberto	 * filestamp from the request and use the timestamp as the
1307132451Sroberto	 * current time. Light the error bit if the certificate is
1308132451Sroberto	 * invalid or contains an unverified signature.
1309132451Sroberto	 */
1310132451Sroberto	case CRYPTO_SIGN | CRYPTO_RESP:
1311132451Sroberto		if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)
1312132451Sroberto			len += crypto_send(fp, &vtemp);
1313132451Sroberto		value_free(&vtemp);
1314132451Sroberto		break;
1315132451Sroberto
1316132451Sroberto	/*
1317132451Sroberto	 * Send public key and signature. Use the values from the public
1318132451Sroberto	 * key.
1319132451Sroberto	 */
1320132451Sroberto	case CRYPTO_COOK:
1321132451Sroberto		len += crypto_send(fp, &pubkey);
1322132451Sroberto		break;
1323132451Sroberto
1324132451Sroberto	/*
1325132451Sroberto	 * Encrypt and send cookie and signature. Light the error bit if
1326132451Sroberto	 * anything goes wrong.
1327132451Sroberto	 */
1328132451Sroberto	case CRYPTO_COOK | CRYPTO_RESP:
1329132451Sroberto		if ((opcode & 0xffff) < VALUE_LEN) {
133082498Sroberto			opcode |= CRYPTO_ERROR;
133182498Sroberto			break;
133282498Sroberto		}
1333132451Sroberto		if (PKT_MODE(xpkt->li_vn_mode) == MODE_SERVER) {
1334132451Sroberto			tcookie = cookie;
1335132451Sroberto		} else {
1336132451Sroberto			if ((peer = findpeerbyassoc(associd)) == NULL) {
1337132451Sroberto				opcode |= CRYPTO_ERROR;
1338132451Sroberto				break;
1339132451Sroberto			}
1340132451Sroberto			tcookie = peer->pcookie;
1341132451Sroberto		}
1342132451Sroberto		if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) ==
1343132451Sroberto		    XEVNT_OK)
1344132451Sroberto			len += crypto_send(fp, &vtemp);
1345132451Sroberto		value_free(&vtemp);
134682498Sroberto		break;
134782498Sroberto
134882498Sroberto	/*
1349132451Sroberto	 * Find peer and send autokey data and signature in broadcast
1350132451Sroberto	 * server and symmetric modes. Use the values in the autokey
1351132451Sroberto	 * structure. If no association is found, either the server has
1352132451Sroberto	 * restarted with new associations or some perp has replayed an
1353132451Sroberto	 * old message, in which case light the error bit.
135482498Sroberto	 */
1355132451Sroberto	case CRYPTO_AUTO | CRYPTO_RESP:
1356132451Sroberto		if ((peer = findpeerbyassoc(associd)) == NULL) {
135782498Sroberto			opcode |= CRYPTO_ERROR;
135882498Sroberto			break;
135982498Sroberto		}
1360132451Sroberto		peer->flags &= ~FLAG_ASSOC;
1361132451Sroberto		len += crypto_send(fp, &peer->sndval);
136282498Sroberto		break;
136382498Sroberto
136482498Sroberto	/*
1365132451Sroberto	 * Send leapseconds table and signature. Use the values from the
1366132451Sroberto	 * tai structure. If no table has been loaded, just send a
1367132451Sroberto	 * request.
136882498Sroberto	 */
1369132451Sroberto	case CRYPTO_TAI:
137082498Sroberto	case CRYPTO_TAI | CRYPTO_RESP:
1371132451Sroberto		if (crypto_flags & CRYPTO_FLAG_TAI)
1372132451Sroberto			len += crypto_send(fp, &tai_leap);
137382498Sroberto		break;
137482498Sroberto
137582498Sroberto	/*
137682498Sroberto	 * Default - Fall through for requests; for unknown responses,
137782498Sroberto	 * flag as error.
137882498Sroberto	 */
137982498Sroberto	default:
138082498Sroberto		if (opcode & CRYPTO_RESP)
138182498Sroberto			opcode |= CRYPTO_ERROR;
138282498Sroberto	}
138382498Sroberto
138482498Sroberto	/*
1385132451Sroberto	 * We ignore length/format errors and duplicates. Other errors
1386132451Sroberto	 * are reported to the log and deny further service. To really
1387132451Sroberto	 * persistent rascals we toss back a kiss-of-death grenade.
1388132451Sroberto	 */
1389132451Sroberto	if (rval > XEVNT_TSP) {
1390132451Sroberto		opcode |= CRYPTO_ERROR;
1391132451Sroberto		sprintf(statstr, "error %x opcode %x", rval, opcode);
1392132451Sroberto		record_crypto_stats(srcadr_sin, statstr);
1393132451Sroberto#ifdef DEBUG
1394132451Sroberto		if (debug)
1395132451Sroberto			printf("crypto_xmit: %s\n", statstr);
1396132451Sroberto#endif
1397132451Sroberto	}
1398132451Sroberto
1399132451Sroberto	/*
1400132451Sroberto	 * Round up the field length to a multiple of 8 bytes and save
140182498Sroberto	 * the request code and length.
140282498Sroberto	 */
140382498Sroberto	len = ((len + 7) / 8) * 8;
1404132451Sroberto	fp->opcode = htonl((opcode & 0xffff0000) | len);
140582498Sroberto#ifdef DEBUG
1406132451Sroberto	if (debug)
1407132451Sroberto		printf(
1408132451Sroberto		    "crypto_xmit: ext offset %d len %u code %x assocID %d\n",
1409132451Sroberto		    start, len, opcode>> 16, associd);
141082498Sroberto#endif
141182498Sroberto	return (len);
141282498Sroberto}
141382498Sroberto
1414132451Sroberto
141582498Sroberto/*
1416132451Sroberto * crypto_verify - parse and verify the extension field and value
1417132451Sroberto *
1418132451Sroberto * Returns
1419132451Sroberto * XEVNT_OK	success
1420132451Sroberto * XEVNT_LEN	bad field format or length
1421132451Sroberto * XEVNT_TSP	bad timestamp
1422132451Sroberto * XEVNT_FSP	bad filestamp
1423132451Sroberto * XEVNT_PUB	bad or missing public key
1424132451Sroberto * XEVNT_SGL	bad signature length
1425132451Sroberto * XEVNT_SIG	signature not verified
142682498Sroberto */
1427132451Srobertostatic int
1428132451Srobertocrypto_verify(
1429132451Sroberto	struct exten *ep,	/* extension pointer */
1430132451Sroberto	struct value *vp,	/* value pointer */
1431132451Sroberto	struct peer *peer	/* peer structure pointer */
1432132451Sroberto	)
143382498Sroberto{
1434132451Sroberto	EVP_PKEY *pkey;		/* server public key */
1435132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
1436132451Sroberto	tstamp_t tstamp;	/* timestamp */
1437132451Sroberto	tstamp_t fstamp;	/* filestamp */
1438132451Sroberto	u_int	vallen;		/* value length */
1439132451Sroberto	u_int	siglen;		/* signature length */
1440132451Sroberto	u_int	opcode, len;
1441132451Sroberto	int	rval;
1442132451Sroberto	int	i;
144382498Sroberto
144482498Sroberto	/*
1445132451Sroberto	 * We require valid opcode and field length, timestamp,
1446132451Sroberto	 * filestamp, public key, digest, signature length and
1447132451Sroberto	 * signature, where relevant. Note that preliminary length
1448132451Sroberto	 * checks are done in the main loop.
144982498Sroberto	 */
1450132451Sroberto	len = ntohl(ep->opcode) & 0x0000ffff;
1451132451Sroberto	opcode = ntohl(ep->opcode) & 0xffff0000;
145282498Sroberto
145382498Sroberto	/*
1454132451Sroberto	 * Check for valid operation code and protocol. The opcode must
1455132451Sroberto	 * not have the error bit set. If a response, it must have a
1456132451Sroberto	 * value header. If a request and does not contain a value
1457132451Sroberto	 * header, no need for further checking.
145882498Sroberto	 */
1459132451Sroberto	if (opcode & CRYPTO_ERROR)
1460132451Sroberto		return (XEVNT_LEN);
1461132451Sroberto 	if (opcode & CRYPTO_RESP) {
1462132451Sroberto 		if (len < VALUE_LEN)
1463132451Sroberto			return (XEVNT_LEN);
1464132451Sroberto	} else {
1465132451Sroberto 		if (len < VALUE_LEN)
1466132451Sroberto			return (XEVNT_OK);
1467132451Sroberto	}
1468132451Sroberto	/*
1469132451Sroberto	 * We have a value header. Check for valid field lengths. The
1470132451Sroberto	 * field length must be long enough to contain the value header,
1471132451Sroberto	 * value and signature. If a request and a previous request of
1472132451Sroberto	 * the same type is pending, discard the previous request. If a
1473132451Sroberto	 * request but no signature, there is no need for further
1474132451Sroberto	 * checking.
1475132451Sroberto	 */
1476132451Sroberto	vallen = ntohl(ep->vallen);
1477132451Sroberto	if (len < ((VALUE_LEN + vallen + 3) / 4) * 4)
1478132451Sroberto		return (XEVNT_LEN);
147982498Sroberto
1480132451Sroberto	i = (vallen + 3) / 4;
1481132451Sroberto	siglen = ntohl(ep->pkt[i++]);
1482132451Sroberto	if (len < VALUE_LEN + vallen + siglen)
1483132451Sroberto		return (XEVNT_LEN);
1484132451Sroberto
1485132451Sroberto	if (!(opcode & CRYPTO_RESP)) {
1486132451Sroberto		if (peer->cmmd != NULL) {
1487132451Sroberto			if ((opcode | CRYPTO_RESP) ==
1488132451Sroberto			    (ntohl(peer->cmmd->opcode) & 0xffff0000)) {
1489132451Sroberto				free(peer->cmmd);
1490132451Sroberto				peer->cmmd = NULL;
1491132451Sroberto			} else {
1492132451Sroberto				return (XEVNT_LEN);
1493132451Sroberto			}
1494132451Sroberto		}
1495132451Sroberto		if (siglen == 0)
1496132451Sroberto			return (XEVNT_OK);
1497132451Sroberto	}
1498132451Sroberto
149982498Sroberto	/*
1500132451Sroberto	 * We have a signature. Check for valid timestamp and filestamp.
1501132451Sroberto	 * The timestamp must not precede the filestamp. The timestamp
1502132451Sroberto	 * and filestamp must not precede the corresponding values in
1503132451Sroberto	 * the value structure. Once the autokey values have been
1504132451Sroberto	 * installed, the timestamp must always be later than the
1505132451Sroberto	 * corresponding value in the value structure. Duplicate
1506132451Sroberto	 * timestamps are illegal once the cookie has been validated.
150782498Sroberto	 */
1508132451Sroberto	rval = XEVNT_OK;
1509132451Sroberto	if (crypto_flags & peer->crypto & CRYPTO_FLAG_PRIV)
1510132451Sroberto		pkey = sign_pkey;
1511132451Sroberto	else
1512132451Sroberto		pkey = peer->pkey;
1513132451Sroberto	tstamp = ntohl(ep->tstamp);
1514132451Sroberto	fstamp = ntohl(ep->fstamp);
1515132451Sroberto	if (tstamp == 0 || tstamp < fstamp) {
1516132451Sroberto		rval = XEVNT_TSP;
1517132451Sroberto	} else if (vp != NULL && (tstamp < ntohl(vp->tstamp) ||
1518132451Sroberto	    (tstamp == ntohl(vp->tstamp) && (peer->crypto &
1519132451Sroberto	    CRYPTO_FLAG_AUTO)))) {
1520132451Sroberto		rval = XEVNT_TSP;
1521132451Sroberto	} else if (vp != NULL && (tstamp < ntohl(vp->fstamp) || fstamp <
1522132451Sroberto	    ntohl(vp->fstamp))) {
1523132451Sroberto		rval = XEVNT_FSP;
1524132451Sroberto
1525132451Sroberto	/*
1526132451Sroberto	 * If a public key and digest is present, and if valid key
1527132451Sroberto	 * length, check for valid signature. Note that the first valid
1528132451Sroberto	 * signature lights the proventic bit.
1529132451Sroberto	 */
1530132451Sroberto	} else if (pkey == NULL || peer->digest == NULL) {
1531132451Sroberto		/* fall through */
1532132451Sroberto	} else if (siglen != (u_int) EVP_PKEY_size(pkey)) {
1533132451Sroberto		rval = XEVNT_SGL;
1534132451Sroberto	} else {
1535132451Sroberto		EVP_VerifyInit(&ctx, peer->digest);
1536132451Sroberto		EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen +
1537132451Sroberto		    12);
1538132451Sroberto		if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen,
1539132451Sroberto		    pkey)) {
1540132451Sroberto			if (peer->crypto & CRYPTO_FLAG_VRFY)
1541132451Sroberto				peer->crypto |= CRYPTO_FLAG_PROV;
1542132451Sroberto		} else {
1543132451Sroberto			rval = XEVNT_SIG;
1544132451Sroberto		}
154582498Sroberto	}
1546132451Sroberto#ifdef DEBUG
1547132451Sroberto	if (debug > 1)
1548132451Sroberto		printf(
1549132451Sroberto		    "crypto_recv: verify %x vallen %u siglen %u ts %u fs %u\n",
1550132451Sroberto		    rval, vallen, siglen, tstamp, fstamp);
1551132451Sroberto#endif
1552132451Sroberto	return (rval);
1553132451Sroberto}
1554132451Sroberto
1555132451Sroberto
1556132451Sroberto/*
1557132451Sroberto * crypto_encrypt - construct encrypted cookie and signature from
1558132451Sroberto * extension field and cookie
1559132451Sroberto *
1560132451Sroberto * Returns
1561132451Sroberto * XEVNT_OK	success
1562132451Sroberto * XEVNT_PUB	bad or missing public key
1563132451Sroberto * XEVNT_CKY	bad or missing cookie
1564132451Sroberto */
1565132451Srobertostatic int
1566132451Srobertocrypto_encrypt(
1567132451Sroberto	struct exten *ep,	/* extension pointer */
1568132451Sroberto	struct value *vp,	/* value pointer */
1569132451Sroberto	keyid_t	*cookie		/* server cookie */
1570132451Sroberto	)
1571132451Sroberto{
1572132451Sroberto	EVP_PKEY *pkey;		/* public key */
1573132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
1574132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
1575132451Sroberto	u_int32	temp32;
1576132451Sroberto	u_int	len;
1577132451Sroberto	u_char	*ptr;
1578132451Sroberto
1579132451Sroberto	/*
1580132451Sroberto	 * Extract the public key from the request.
1581132451Sroberto	 */
1582132451Sroberto	len = ntohl(ep->vallen);
1583132451Sroberto	ptr = (u_char *)ep->pkt;
1584132451Sroberto	pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len);
1585132451Sroberto	if (pkey == NULL) {
1586132451Sroberto		msyslog(LOG_ERR, "crypto_encrypt %s\n",
1587132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
1588132451Sroberto		return (XEVNT_PUB);
158982498Sroberto	}
159082498Sroberto
159182498Sroberto	/*
1592132451Sroberto	 * Encrypt the cookie, encode in ASN.1 and sign.
159382498Sroberto	 */
1594132451Sroberto	tstamp = crypto_time();
1595132451Sroberto	memset(vp, 0, sizeof(struct value));
1596132451Sroberto	vp->tstamp = htonl(tstamp);
1597132451Sroberto	vp->fstamp = hostval.tstamp;
1598132451Sroberto	len = EVP_PKEY_size(pkey);
1599132451Sroberto	vp->vallen = htonl(len);
1600132451Sroberto	vp->ptr = emalloc(len);
1601132451Sroberto	temp32 = htonl(*cookie);
1602132451Sroberto	if (!RSA_public_encrypt(4, (u_char *)&temp32, vp->ptr,
1603132451Sroberto	    pkey->pkey.rsa, RSA_PKCS1_OAEP_PADDING)) {
1604132451Sroberto		msyslog(LOG_ERR, "crypto_encrypt %s\n",
1605132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
1606132451Sroberto		EVP_PKEY_free(pkey);
1607132451Sroberto		return (XEVNT_CKY);
1608132451Sroberto	}
1609132451Sroberto	EVP_PKEY_free(pkey);
1610132451Sroberto	vp->siglen = 0;
1611132451Sroberto	if (tstamp == 0)
1612132451Sroberto		return (XEVNT_OK);
1613132451Sroberto	vp->sig = emalloc(sign_siglen);
1614132451Sroberto	EVP_SignInit(&ctx, sign_digest);
1615132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
1616132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
1617132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
1618132451Sroberto		vp->siglen = htonl(len);
1619132451Sroberto	return (XEVNT_OK);
1620132451Sroberto}
162182498Sroberto
1622132451Sroberto
1623132451Sroberto/*
1624132451Sroberto * crypto_ident - construct extension field for identity scheme
1625132451Sroberto *
1626132451Sroberto * This routine determines which identity scheme is in use and
1627132451Sroberto * constructs an extension field for that scheme.
1628132451Sroberto */
1629132451Srobertou_int
1630132451Srobertocrypto_ident(
1631132451Sroberto	struct peer *peer	/* peer structure pointer */
1632132451Sroberto	)
1633132451Sroberto{
1634132451Sroberto	char	filename[MAXFILENAME + 1];
1635132451Sroberto
163682498Sroberto	/*
1637132451Sroberto	 * If the server identity has already been verified, no further
1638132451Sroberto	 * action is necessary. Otherwise, try to load the identity file
1639132451Sroberto	 * of the certificate issuer. If the issuer file is not found,
1640132451Sroberto	 * try the host file. If nothing found, declare a cryptobust.
1641132451Sroberto	 * Note we can't get here unless the trusted certificate has
1642132451Sroberto	 * been found and the CRYPTO_FLAG_VALID bit is set, so the
1643132451Sroberto	 * certificate issuer is valid.
164482498Sroberto	 */
1645132451Sroberto	if (peer->crypto & CRYPTO_FLAG_VRFY)
1646132451Sroberto		return (0);
1647132451Sroberto
1648132451Sroberto	if (peer->ident_pkey != NULL)
1649132451Sroberto		EVP_PKEY_free(peer->ident_pkey);
1650132451Sroberto	if (peer->crypto & CRYPTO_FLAG_GQ) {
1651132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
1652132451Sroberto		    peer->issuer);
1653132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1654132451Sroberto		if (peer->ident_pkey != NULL)
1655132451Sroberto			return (CRYPTO_GQ);
1656132451Sroberto
1657132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
165882498Sroberto		    sys_hostname);
1659132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1660132451Sroberto		if (peer->ident_pkey != NULL)
1661132451Sroberto			return (CRYPTO_GQ);
1662132451Sroberto	}
1663132451Sroberto	if (peer->crypto & CRYPTO_FLAG_IFF) {
1664132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
1665132451Sroberto		    peer->issuer);
1666132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1667132451Sroberto		if (peer->ident_pkey != NULL)
1668132451Sroberto			return (CRYPTO_IFF);
166982498Sroberto
1670132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
1671132451Sroberto		    sys_hostname);
1672132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1673132451Sroberto		if (peer->ident_pkey != NULL)
1674132451Sroberto			return (CRYPTO_IFF);
1675132451Sroberto	}
1676132451Sroberto	if (peer->crypto & CRYPTO_FLAG_MV) {
1677132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
1678132451Sroberto		    peer->issuer);
1679132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1680132451Sroberto		if (peer->ident_pkey != NULL)
1681132451Sroberto			return (CRYPTO_MV);
1682132451Sroberto
1683132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
1684132451Sroberto		    sys_hostname);
1685132451Sroberto		peer->ident_pkey = crypto_key(filename, &peer->fstamp);
1686132451Sroberto		if (peer->ident_pkey != NULL)
1687132451Sroberto			return (CRYPTO_MV);
1688132451Sroberto	}
1689132451Sroberto
169082498Sroberto	/*
1691132451Sroberto	 * No compatible identity scheme is available. Use the default
1692132451Sroberto	 * TC scheme.
169382498Sroberto	 */
1694132451Sroberto	msyslog(LOG_INFO,
1695132451Sroberto	    "crypto_ident: no compatible identity scheme found");
1696132451Sroberto	return (0);
1697132451Sroberto}
169882498Sroberto
1699132451Sroberto
1700132451Sroberto/*
1701132451Sroberto * crypto_args - construct extension field from arguments
1702132451Sroberto *
1703132451Sroberto * This routine creates an extension field with current timestamps and
1704132451Sroberto * specified opcode, association ID and optional string. Note that the
1705132451Sroberto * extension field is created here, but freed after the crypto_xmit()
1706132451Sroberto * call in the protocol module.
1707132451Sroberto *
1708132451Sroberto * Returns extension field pointer (no errors).
1709132451Sroberto */
1710132451Srobertostruct exten *
1711132451Srobertocrypto_args(
1712132451Sroberto	struct peer *peer,	/* peer structure pointer */
1713132451Sroberto	u_int	opcode,		/* operation code */
1714132451Sroberto	char	*str		/* argument string */
1715132451Sroberto	)
1716132451Sroberto{
1717132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
1718132451Sroberto	struct exten *ep;	/* extension field pointer */
1719132451Sroberto	u_int	len;		/* extension field length */
1720132451Sroberto
1721132451Sroberto	tstamp = crypto_time();
1722132451Sroberto	len = sizeof(struct exten);
1723132451Sroberto	if (str != NULL)
1724132451Sroberto		len += strlen(str);
1725132451Sroberto	ep = emalloc(len);
1726132451Sroberto	memset(ep, 0, len);
1727132451Sroberto	ep->opcode = htonl(opcode + len);
1728132451Sroberto
172982498Sroberto	/*
1730132451Sroberto	 * If a response, send our ID; if a request, send the
1731132451Sroberto	 * responder's ID.
173282498Sroberto	 */
1733132451Sroberto	if (opcode & CRYPTO_RESP)
1734132451Sroberto		ep->associd = htonl(peer->associd);
1735132451Sroberto	else
1736132451Sroberto		ep->associd = htonl(peer->assoc);
1737132451Sroberto	ep->tstamp = htonl(tstamp);
1738132451Sroberto	ep->fstamp = hostval.tstamp;
1739132451Sroberto	ep->vallen = 0;
1740132451Sroberto	if (str != NULL) {
1741132451Sroberto		ep->vallen = htonl(strlen(str));
1742132451Sroberto		memcpy((char *)ep->pkt, str, strlen(str));
1743132451Sroberto	} else {
1744132451Sroberto		ep->pkt[0] = peer->associd;
1745132451Sroberto	}
1746132451Sroberto	return (ep);
174782498Sroberto}
174882498Sroberto
174982498Sroberto
175082498Sroberto/*
1751132451Sroberto * crypto_send - construct extension field from value components
1752132451Sroberto *
1753132451Sroberto * Returns extension field length. Note: it is not polite to send a
1754132451Sroberto * nonempty signature with zero timestamp or a nonzero timestamp with
1755132451Sroberto * empty signature, but these rules are not enforced here.
175682498Sroberto */
1757132451Srobertou_int
1758132451Srobertocrypto_send(
1759132451Sroberto	struct exten *ep,	/* extension field pointer */
1760132451Sroberto	struct value *vp	/* value pointer */
1761132451Sroberto	)
176282498Sroberto{
1763132451Sroberto	u_int	len, temp32;
1764132451Sroberto	int	i;
176582498Sroberto
176682498Sroberto	/*
1767132451Sroberto	 * Copy data. If the data field is empty or zero length, encode
1768132451Sroberto	 * an empty value with length zero.
176982498Sroberto	 */
1770132451Sroberto	ep->tstamp = vp->tstamp;
1771132451Sroberto	ep->fstamp = vp->fstamp;
1772132451Sroberto	ep->vallen = vp->vallen;
1773132451Sroberto	len = 12;
1774132451Sroberto	temp32 = ntohl(vp->vallen);
1775132451Sroberto	if (temp32 > 0 && vp->ptr != NULL)
1776132451Sroberto		memcpy(ep->pkt, vp->ptr, temp32);
1777132451Sroberto
1778132451Sroberto	/*
1779132451Sroberto	 * Copy signature. If the signature field is empty or zero
1780132451Sroberto	 * length, encode an empty signature with length zero.
1781132451Sroberto	 */
1782132451Sroberto	i = (temp32 + 3) / 4;
1783132451Sroberto	len += i * 4 + 4;
1784132451Sroberto	ep->pkt[i++] = vp->siglen;
1785132451Sroberto	temp32 = ntohl(vp->siglen);
1786132451Sroberto	if (temp32 > 0 && vp->sig != NULL)
1787132451Sroberto		memcpy(&ep->pkt[i], vp->sig, temp32);
1788132451Sroberto	len += temp32;
1789132451Sroberto	return (len);
1790132451Sroberto}
1791132451Sroberto
1792132451Sroberto
1793132451Sroberto/*
1794132451Sroberto * crypto_update - compute new public value and sign extension fields
1795132451Sroberto *
1796132451Sroberto * This routine runs periodically, like once a day, and when something
1797132451Sroberto * changes. It updates the timestamps on three value structures and one
1798132451Sroberto * value structure list, then signs all the structures:
1799132451Sroberto *
1800132451Sroberto * hostval	host name (not signed)
1801132451Sroberto * pubkey	public key
1802132451Sroberto * cinfo	certificate info/value list
1803132451Sroberto * tai_leap	leapseconds file
1804132451Sroberto *
1805132451Sroberto * Filestamps are proventicated data, so this routine is run only when
1806132451Sroberto * the host has been synchronized to a proventicated source. Thus, the
1807132451Sroberto * timestamp is proventicated, too, and can be used to deflect
1808132451Sroberto * clogging attacks and even cook breakfast.
1809132451Sroberto *
1810132451Sroberto * Returns void (no errors)
1811132451Sroberto */
1812132451Srobertovoid
1813132451Srobertocrypto_update(void)
1814132451Sroberto{
1815132451Sroberto	EVP_MD_CTX ctx;		/* message digest context */
1816132451Sroberto	struct cert_info *cp, *cpn, **zp; /* certificate info/value */
1817132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
1818132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
1819132451Sroberto	u_int	len;
1820132451Sroberto
1821132451Sroberto	if ((tstamp = crypto_time()) == 0)
182282498Sroberto		return;
1823132451Sroberto	hostval.tstamp = htonl(tstamp);
182482498Sroberto
182582498Sroberto	/*
1826132451Sroberto	 * Sign public key and timestamps. The filestamp is derived from
1827132451Sroberto	 * the host key file extension from wherever the file was
1828132451Sroberto	 * generated.
182982498Sroberto	 */
1830132451Sroberto	if (pubkey.vallen != 0) {
1831132451Sroberto		pubkey.tstamp = hostval.tstamp;
1832132451Sroberto		pubkey.siglen = 0;
1833132451Sroberto		if (pubkey.sig == NULL)
1834132451Sroberto			pubkey.sig = emalloc(sign_siglen);
1835132451Sroberto		EVP_SignInit(&ctx, sign_digest);
1836132451Sroberto		EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12);
1837132451Sroberto		EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen));
1838132451Sroberto		if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey))
1839132451Sroberto			pubkey.siglen = htonl(len);
184082498Sroberto	}
184182498Sroberto
184282498Sroberto	/*
1843132451Sroberto	 * Sign certificates and timestamps. The filestamp is derived
1844132451Sroberto	 * from the certificate file extension from wherever the file
1845132451Sroberto	 * was generated. At the same time expired certificates are
1846132451Sroberto	 * expunged.
184782498Sroberto	 */
1848132451Sroberto	zp = &cinfo;
1849132451Sroberto	for (cp = cinfo; cp != NULL; cp = cpn) {
1850132451Sroberto		cpn = cp->link;
1851132451Sroberto		if (tstamp > cp->last) {
1852132451Sroberto			*zp = cpn;
1853132451Sroberto			cert_free(cp);
1854132451Sroberto		} else {
1855132451Sroberto			cp->cert.tstamp = hostval.tstamp;
1856132451Sroberto			cp->cert.siglen = 0;
1857132451Sroberto			if (cp->cert.sig == NULL)
1858132451Sroberto				cp->cert.sig = emalloc(sign_siglen);
1859132451Sroberto			EVP_SignInit(&ctx, sign_digest);
1860132451Sroberto			EVP_SignUpdate(&ctx, (u_char *)&cp->cert, 12);
1861132451Sroberto			EVP_SignUpdate(&ctx, cp->cert.ptr,
1862132451Sroberto			    ntohl(cp->cert.vallen));
1863132451Sroberto			if (EVP_SignFinal(&ctx, cp->cert.sig, &len,
1864132451Sroberto			    sign_pkey))
1865132451Sroberto				cp->cert.siglen = htonl(len);
1866132451Sroberto			zp = &cp->link;
186782498Sroberto		}
186882498Sroberto	}
186982498Sroberto
187082498Sroberto	/*
1871132451Sroberto	 * Sign leapseconds table and timestamps. The filestamp is
1872132451Sroberto	 * derived from the leapsecond file extension from wherever the
1873132451Sroberto	 * file was generated.
187482498Sroberto	 */
187582498Sroberto	if (tai_leap.vallen != 0) {
1876132451Sroberto		tai_leap.tstamp = hostval.tstamp;
1877132451Sroberto		tai_leap.siglen = 0;
1878132451Sroberto		if (tai_leap.sig == NULL)
1879132451Sroberto			tai_leap.sig = emalloc(sign_siglen);
1880132451Sroberto		EVP_SignInit(&ctx, sign_digest);
188182498Sroberto		EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
188282498Sroberto		EVP_SignUpdate(&ctx, tai_leap.ptr,
188382498Sroberto		    ntohl(tai_leap.vallen));
1884132451Sroberto		if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
1885132451Sroberto			tai_leap.siglen = htonl(len);
188682498Sroberto	}
1887132451Sroberto	sprintf(statstr, "update ts %u", ntohl(hostval.tstamp));
1888132451Sroberto	record_crypto_stats(NULL, statstr);
188982498Sroberto#ifdef DEBUG
189082498Sroberto	if (debug)
1891132451Sroberto		printf("crypto_update: %s\n", statstr);
189282498Sroberto#endif
189382498Sroberto}
189482498Sroberto
189582498Sroberto
189682498Sroberto/*
1897132451Sroberto * value_free - free value structure components.
1898132451Sroberto *
1899132451Sroberto * Returns void (no errors)
190082498Sroberto */
1901132451Srobertovoid
1902132451Srobertovalue_free(
1903132451Sroberto	struct value *vp	/* value structure */
190482498Sroberto	)
190582498Sroberto{
1906132451Sroberto	if (vp->ptr != NULL)
1907132451Sroberto		free(vp->ptr);
1908132451Sroberto	if (vp->sig != NULL)
1909132451Sroberto		free(vp->sig);
1910132451Sroberto	memset(vp, 0, sizeof(struct value));
1911132451Sroberto}
191282498Sroberto
1913132451Sroberto
1914132451Sroberto/*
1915132451Sroberto * crypto_time - returns current NTP time in seconds.
1916132451Sroberto */
1917132451Srobertotstamp_t
1918132451Srobertocrypto_time()
1919132451Sroberto{
1920132451Sroberto	l_fp	tstamp;		/* NTP time */	L_CLR(&tstamp);
1921132451Sroberto
1922132451Sroberto	L_CLR(&tstamp);
1923132451Sroberto	if (sys_leap != LEAP_NOTINSYNC)
1924132451Sroberto		get_systime(&tstamp);
1925132451Sroberto	return (tstamp.l_ui);
1926132451Sroberto}
1927132451Sroberto
1928132451Sroberto
1929132451Sroberto/*
1930132451Sroberto * asn2ntp - convert ASN1_TIME time structure to NTP time in seconds.
1931132451Sroberto */
1932132451Srobertou_long
1933132451Srobertoasn2ntp	(
1934132451Sroberto	ASN1_TIME *asn1time	/* pointer to ASN1_TIME structure */
1935132451Sroberto	)
1936132451Sroberto{
1937132451Sroberto	char	*v;		/* pointer to ASN1_TIME string */
1938132451Sroberto	struct	tm tm;		/* used to convert to NTP time */
1939132451Sroberto
194082498Sroberto	/*
1941132451Sroberto	 * Extract time string YYMMDDHHMMSSZ from ASN1 time structure.
1942132451Sroberto	 * Note that the YY, MM, DD fields start with one, the HH, MM,
1943132451Sroberto	 * SS fiels start with zero and the Z character should be 'Z'
1944132451Sroberto	 * for UTC. Also note that years less than 50 map to years
1945132451Sroberto	 * greater than 100. Dontcha love ASN.1? Better than MIL-188.
194682498Sroberto	 */
1947132451Sroberto	if (asn1time->length > 13)
1948132451Sroberto		return ((u_long)(~0));	/* We can't use -1 here. It's invalid */
1949132451Sroberto	v = (char *)asn1time->data;
1950132451Sroberto	tm.tm_year = (v[0] - '0') * 10 + v[1] - '0';
1951132451Sroberto	if (tm.tm_year < 50)
1952132451Sroberto		tm.tm_year += 100;
1953132451Sroberto	tm.tm_mon = (v[2] - '0') * 10 + v[3] - '0' - 1;
1954132451Sroberto	tm.tm_mday = (v[4] - '0') * 10 + v[5] - '0';
1955132451Sroberto	tm.tm_hour = (v[6] - '0') * 10 + v[7] - '0';
1956132451Sroberto	tm.tm_min = (v[8] - '0') * 10 + v[9] - '0';
1957132451Sroberto	tm.tm_sec = (v[10] - '0') * 10 + v[11] - '0';
1958132451Sroberto	tm.tm_wday = 0;
1959132451Sroberto	tm.tm_yday = 0;
1960132451Sroberto	tm.tm_isdst = 0;
1961132451Sroberto	return (timegm(&tm) + JAN_1970);
1962132451Sroberto}
1963132451Sroberto
1964132451Sroberto
1965132451Sroberto/*
1966132451Sroberto * bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number.
1967132451Sroberto */
1968132451Srobertostatic int
1969132451Srobertobighash(
1970132451Sroberto	BIGNUM	*bn,		/* BIGNUM * from */
1971132451Sroberto	BIGNUM	*bk		/* BIGNUM * to */
1972132451Sroberto	)
1973132451Sroberto{
1974132451Sroberto	EVP_MD_CTX ctx;		/* message digest context */
1975132451Sroberto	u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
1976132451Sroberto	u_char	*ptr;		/* a BIGNUM as binary string */
1977132451Sroberto	u_int	len;
1978132451Sroberto
1979132451Sroberto	len = BN_num_bytes(bn);
1980132451Sroberto	ptr = emalloc(len);
1981132451Sroberto	BN_bn2bin(bn, ptr);
1982132451Sroberto	EVP_DigestInit(&ctx, EVP_md5());
1983132451Sroberto	EVP_DigestUpdate(&ctx, ptr, len);
1984132451Sroberto	EVP_DigestFinal(&ctx, dgst, &len);
1985132451Sroberto	BN_bin2bn(dgst, len, bk);
1986132451Sroberto	return (1);
1987132451Sroberto}
1988132451Sroberto
1989132451Sroberto
1990132451Sroberto/*
1991132451Sroberto ***********************************************************************
1992132451Sroberto *								       *
1993132451Sroberto * The following routines implement the Schnorr (IFF) identity scheme  *
1994132451Sroberto *								       *
1995132451Sroberto ***********************************************************************
1996132451Sroberto *
1997132451Sroberto * The Schnorr (IFF) identity scheme is intended for use when
1998132451Sroberto * the ntp-genkeys program does not generate the certificates used in
1999132451Sroberto * the protocol and the group key cannot be conveyed in the certificate
2000132451Sroberto * itself. For this purpose, new generations of IFF values must be
2001132451Sroberto * securely transmitted to all members of the group before use. The
2002132451Sroberto * scheme is self contained and independent of new generations of host
2003132451Sroberto * keys, sign keys and certificates.
2004132451Sroberto *
2005132451Sroberto * The IFF identity scheme is based on DSA cryptography and algorithms
2006132451Sroberto * described in Stinson p. 285. The IFF values hide in a DSA cuckoo
2007132451Sroberto * structure, but only the primes and generator are used. The p is a
2008132451Sroberto * 512-bit prime, q a 160-bit prime that divides p - 1 and is a qth root
2009132451Sroberto * of 1 mod p; that is, g^q = 1 mod p. The TA rolls primvate random
2010132451Sroberto * group key b disguised as a DSA structure member, then computes public
2011132451Sroberto * key g^(q - b). These values are shared only among group members and
2012132451Sroberto * never revealed in messages. Alice challenges Bob to confirm identity
2013132451Sroberto * using the protocol described below.
2014132451Sroberto *
2015132451Sroberto * How it works
2016132451Sroberto *
2017132451Sroberto * The scheme goes like this. Both Alice and Bob have the public primes
2018132451Sroberto * p, q and generator g. The TA gives private key b to Bob and public
2019132451Sroberto * key v = g^(q - a) mod p to Alice.
2020132451Sroberto *
2021132451Sroberto * Alice rolls new random challenge r and sends to Bob in the IFF
2022132451Sroberto * request message. Bob rolls new random k, then computes y = k + b r
2023132451Sroberto * mod q and x = g^k mod p and sends (y, hash(x)) to Alice in the
2024132451Sroberto * response message. Besides making the response shorter, the hash makes
2025132451Sroberto * it effectivey impossible for an intruder to solve for b by observing
2026132451Sroberto * a number of these messages.
2027132451Sroberto *
2028132451Sroberto * Alice receives the response and computes g^y v^r mod p. After a bit
2029132451Sroberto * of algebra, this simplifies to g^k. If the hash of this result
2030132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed
2031132451Sroberto * response binds this knowledge to Bob's private key and the public key
2032132451Sroberto * previously received in his certificate.
2033132451Sroberto *
2034132451Sroberto * crypto_alice - construct Alice's challenge in IFF scheme
2035132451Sroberto *
2036132451Sroberto * Returns
2037132451Sroberto * XEVNT_OK	success
2038132451Sroberto * XEVNT_PUB	bad or missing public key
2039132451Sroberto * XEVNT_ID	bad or missing identity parameters
2040132451Sroberto */
2041132451Srobertostatic int
2042132451Srobertocrypto_alice(
2043132451Sroberto	struct peer *peer,	/* peer pointer */
2044132451Sroberto	struct value *vp	/* value pointer */
2045132451Sroberto	)
2046132451Sroberto{
2047132451Sroberto	DSA	*dsa;		/* IFF parameters */
2048132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2049132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2050132451Sroberto	tstamp_t tstamp;
2051132451Sroberto	u_int	len;
2052132451Sroberto
2053132451Sroberto	/*
2054132451Sroberto	 * The identity parameters must have correct format and content.
2055132451Sroberto	 */
2056132451Sroberto	if (peer->ident_pkey == NULL)
2057132451Sroberto		return (XEVNT_ID);
2058132451Sroberto	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
2059132451Sroberto		msyslog(LOG_INFO, "crypto_alice: defective key");
2060132451Sroberto		return (XEVNT_PUB);
2061132451Sroberto	}
2062132451Sroberto
2063132451Sroberto	/*
2064132451Sroberto	 * Roll new random r (0 < r < q). The OpenSSL library has a bug
2065132451Sroberto	 * omitting BN_rand_range, so we have to do it the hard way.
2066132451Sroberto	 */
2067132451Sroberto	bctx = BN_CTX_new();
2068132451Sroberto	len = BN_num_bytes(dsa->q);
2069132451Sroberto	if (peer->iffval != NULL)
2070132451Sroberto		BN_free(peer->iffval);
2071132451Sroberto	peer->iffval = BN_new();
2072132451Sroberto	BN_rand(peer->iffval, len * 8, -1, 1);	/* r */
2073132451Sroberto	BN_mod(peer->iffval, peer->iffval, dsa->q, bctx);
2074132451Sroberto	BN_CTX_free(bctx);
2075132451Sroberto
2076132451Sroberto	/*
2077132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2078132451Sroberto	 */
2079132451Sroberto	tstamp = crypto_time();
2080132451Sroberto	memset(vp, 0, sizeof(struct value));
2081132451Sroberto	vp->tstamp = htonl(tstamp);
2082132451Sroberto	vp->fstamp = htonl(peer->fstamp);
2083132451Sroberto	vp->vallen = htonl(len);
2084132451Sroberto	vp->ptr = emalloc(len);
2085132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2086132451Sroberto	vp->siglen = 0;
2087132451Sroberto	if (tstamp == 0)
2088132451Sroberto		return (XEVNT_OK);
2089132451Sroberto	vp->sig = emalloc(sign_siglen);
2090132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2091132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2092132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2093132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2094132451Sroberto		vp->siglen = htonl(len);
2095132451Sroberto	return (XEVNT_OK);
2096132451Sroberto}
2097132451Sroberto
2098132451Sroberto
2099132451Sroberto/*
2100132451Sroberto * crypto_bob - construct Bob's response to Alice's challenge
2101132451Sroberto *
2102132451Sroberto * Returns
2103132451Sroberto * XEVNT_OK	success
2104132451Sroberto * XEVNT_PUB	bad or missing public key
2105132451Sroberto */
2106132451Srobertostatic int
2107132451Srobertocrypto_bob(
2108132451Sroberto	struct exten *ep,	/* extension pointer */
2109132451Sroberto	struct value *vp	/* value pointer */
2110132451Sroberto	)
2111132451Sroberto{
2112132451Sroberto	DSA	*dsa;		/* IFF parameters */
2113132451Sroberto	DSA_SIG	*sdsa;		/* DSA signature context fake */
2114132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2115132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2116132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2117132451Sroberto	BIGNUM	*bn, *bk, *r;
2118132451Sroberto	u_char	*ptr;
2119132451Sroberto	u_int	len;
2120132451Sroberto
2121132451Sroberto	/*
2122132451Sroberto	 * If the IFF parameters are not valid, something awful
2123132451Sroberto	 * happened or we are being tormented.
2124132451Sroberto	 */
2125132451Sroberto	if (!(crypto_flags & CRYPTO_FLAG_IFF)) {
2126132451Sroberto		msyslog(LOG_INFO, "crypto_bob: scheme unavailable");
2127132451Sroberto		return (XEVNT_PUB);
2128132451Sroberto	}
2129132451Sroberto	dsa = iffpar_pkey->pkey.dsa;
2130132451Sroberto
2131132451Sroberto	/*
2132132451Sroberto	 * Extract r from the challenge.
2133132451Sroberto	 */
2134132451Sroberto	len = ntohl(ep->vallen);
2135132451Sroberto	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2136132451Sroberto		msyslog(LOG_ERR, "crypto_bob %s\n",
2137132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2138132451Sroberto		return (XEVNT_PUB);
2139132451Sroberto	}
2140132451Sroberto
2141132451Sroberto	/*
2142132451Sroberto	 * Bob rolls random k (0 < k < q), computes y = k + b r mod q
2143132451Sroberto	 * and x = g^k mod p, then sends (y, hash(x)) to Alice.
2144132451Sroberto	 */
2145132451Sroberto	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
2146132451Sroberto	sdsa = DSA_SIG_new();
2147132451Sroberto	BN_rand(bk, len * 8, -1, 1);		/* k */
2148132451Sroberto	BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */
2149132451Sroberto	BN_add(bn, bn, bk);
2150132451Sroberto	BN_mod(bn, bn, dsa->q, bctx);		/* k + b r mod q */
2151132451Sroberto	sdsa->r = BN_dup(bn);
2152132451Sroberto	BN_mod_exp(bk, dsa->g, bk, dsa->p, bctx); /* g^k mod p */
2153132451Sroberto	bighash(bk, bk);
2154132451Sroberto	sdsa->s = BN_dup(bk);
2155132451Sroberto	BN_CTX_free(bctx);
2156132451Sroberto	BN_free(r); BN_free(bn); BN_free(bk);
2157132451Sroberto
2158132451Sroberto	/*
2159132451Sroberto	 * Encode the values in ASN.1 and sign.
2160132451Sroberto	 */
2161132451Sroberto	tstamp = crypto_time();
2162132451Sroberto	memset(vp, 0, sizeof(struct value));
2163132451Sroberto	vp->tstamp = htonl(tstamp);
2164132451Sroberto	vp->fstamp = htonl(if_fstamp);
2165132451Sroberto	len = i2d_DSA_SIG(sdsa, NULL);
2166132451Sroberto	if (len <= 0) {
2167132451Sroberto		msyslog(LOG_ERR, "crypto_bob %s\n",
2168132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2169132451Sroberto		DSA_SIG_free(sdsa);
2170132451Sroberto		return (XEVNT_PUB);
2171132451Sroberto	}
2172132451Sroberto	vp->vallen = htonl(len);
2173132451Sroberto	ptr = emalloc(len);
2174132451Sroberto	vp->ptr = ptr;
2175132451Sroberto	i2d_DSA_SIG(sdsa, &ptr);
2176132451Sroberto	DSA_SIG_free(sdsa);
2177132451Sroberto	vp->siglen = 0;
2178132451Sroberto	if (tstamp == 0)
2179132451Sroberto		return (XEVNT_OK);
2180132451Sroberto	vp->sig = emalloc(sign_siglen);
2181132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2182132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2183132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2184132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2185132451Sroberto		vp->siglen = htonl(len);
2186132451Sroberto	return (XEVNT_OK);
2187132451Sroberto}
2188132451Sroberto
2189132451Sroberto
2190132451Sroberto/*
2191132451Sroberto * crypto_iff - verify Bob's response to Alice's challenge
2192132451Sroberto *
2193132451Sroberto * Returns
2194132451Sroberto * XEVNT_OK	success
2195132451Sroberto * XEVNT_PUB	bad or missing public key
2196132451Sroberto * XEVNT_FSP	bad filestamp
2197132451Sroberto * XEVNT_ID	bad or missing identity parameters
2198132451Sroberto */
2199132451Srobertoint
2200132451Srobertocrypto_iff(
2201132451Sroberto	struct exten *ep,	/* extension pointer */
2202132451Sroberto	struct peer *peer	/* peer structure pointer */
2203132451Sroberto	)
2204132451Sroberto{
2205132451Sroberto	DSA	*dsa;		/* IFF parameters */
2206132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2207132451Sroberto	DSA_SIG	*sdsa;		/* DSA parameters */
2208132451Sroberto	BIGNUM	*bn, *bk;
2209132451Sroberto	u_int	len;
2210132451Sroberto	const u_char	*ptr;
2211132451Sroberto	int	temp;
2212132451Sroberto
2213132451Sroberto	/*
2214132451Sroberto	 * If the IFF parameters are not valid or no challenge was sent,
2215132451Sroberto	 * something awful happened or we are being tormented.
2216132451Sroberto	 */
2217132451Sroberto	if (peer->ident_pkey == NULL) {
2218132451Sroberto		msyslog(LOG_INFO, "crypto_iff: scheme unavailable");
2219132451Sroberto		return (XEVNT_PUB);
2220132451Sroberto	}
2221132451Sroberto	if (ntohl(ep->fstamp) != peer->fstamp) {
2222132451Sroberto		msyslog(LOG_INFO, "crypto_iff: invalid filestamp %u",
2223132451Sroberto		    ntohl(ep->fstamp));
2224132451Sroberto		return (XEVNT_FSP);
2225132451Sroberto	}
2226132451Sroberto	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
2227132451Sroberto		msyslog(LOG_INFO, "crypto_iff: defective key");
2228132451Sroberto		return (XEVNT_PUB);
2229132451Sroberto	}
2230132451Sroberto	if (peer->iffval == NULL) {
2231132451Sroberto		msyslog(LOG_INFO, "crypto_iff: missing challenge");
2232132451Sroberto		return (XEVNT_PUB);
2233132451Sroberto	}
2234132451Sroberto
2235132451Sroberto	/*
2236132451Sroberto	 * Extract the k + b r and g^k values from the response.
2237132451Sroberto	 */
2238132451Sroberto	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
2239132451Sroberto	len = ntohl(ep->vallen);
2240132451Sroberto	ptr = (const u_char *)ep->pkt;
2241132451Sroberto	if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
2242132451Sroberto		msyslog(LOG_ERR, "crypto_iff %s\n",
2243132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2244132451Sroberto		return (XEVNT_PUB);
2245132451Sroberto	}
2246132451Sroberto
2247132451Sroberto	/*
2248132451Sroberto	 * Compute g^(k + b r) g^(q - b)r mod p.
2249132451Sroberto	 */
2250132451Sroberto	BN_mod_exp(bn, dsa->pub_key, peer->iffval, dsa->p, bctx);
2251132451Sroberto	BN_mod_exp(bk, dsa->g, sdsa->r, dsa->p, bctx);
2252132451Sroberto	BN_mod_mul(bn, bn, bk, dsa->p, bctx);
2253132451Sroberto
2254132451Sroberto	/*
2255132451Sroberto	 * Verify the hash of the result matches hash(x).
2256132451Sroberto	 */
2257132451Sroberto	bighash(bn, bn);
2258132451Sroberto	temp = BN_cmp(bn, sdsa->s);
2259132451Sroberto	BN_free(bn); BN_free(bk); BN_CTX_free(bctx);
2260132451Sroberto	BN_free(peer->iffval);
2261132451Sroberto	peer->iffval = NULL;
2262132451Sroberto	DSA_SIG_free(sdsa);
2263132451Sroberto	if (temp == 0)
2264132451Sroberto		return (XEVNT_OK);
226582498Sroberto	else
2266132451Sroberto		return (XEVNT_ID);
2267132451Sroberto}
2268132451Sroberto
2269132451Sroberto
2270132451Sroberto/*
2271132451Sroberto ***********************************************************************
2272132451Sroberto *								       *
2273132451Sroberto * The following routines implement the Guillou-Quisquater (GQ)        *
2274132451Sroberto * identity scheme                                                     *
2275132451Sroberto *								       *
2276132451Sroberto ***********************************************************************
2277132451Sroberto *
2278132451Sroberto * The Guillou-Quisquater (GQ) identity scheme is intended for use when
2279132451Sroberto * the ntp-genkeys program generates the certificates used in the
2280132451Sroberto * protocol and the group key can be conveyed in a certificate extension
2281132451Sroberto * field. The scheme is self contained and independent of new
2282132451Sroberto * generations of host keys, sign keys and certificates.
2283132451Sroberto *
2284132451Sroberto * The GQ identity scheme is based on RSA cryptography and algorithms
2285132451Sroberto * described in Stinson p. 300 (with errors). The GQ values hide in a
2286132451Sroberto * RSA cuckoo structure, but only the modulus is used. The 512-bit
2287132451Sroberto * public modulus is n = p q, where p and q are secret large primes. The
2288132451Sroberto * TA rolls random group key b disguised as a RSA structure member.
2289132451Sroberto * Except for the public key, these values are shared only among group
2290132451Sroberto * members and never revealed in messages.
2291132451Sroberto *
2292132451Sroberto * When rolling new certificates, Bob recomputes the private and
2293132451Sroberto * public keys. The private key u is a random roll, while the public key
2294132451Sroberto * is the inverse obscured by the group key v = (u^-1)^b. These values
2295132451Sroberto * replace the private and public keys normally generated by the RSA
2296132451Sroberto * scheme. Alice challenges Bob to confirm identity using the protocol
2297132451Sroberto * described below.
2298132451Sroberto *
2299132451Sroberto * How it works
2300132451Sroberto *
2301132451Sroberto * The scheme goes like this. Both Alice and Bob have the same modulus n
2302132451Sroberto * and some random b as the group key. These values are computed and
2303132451Sroberto * distributed in advance via secret means, although only the group key
2304132451Sroberto * b is truly secret. Each has a private random private key u and public
2305132451Sroberto * key (u^-1)^b, although not necessarily the same ones. Bob and Alice
2306132451Sroberto * can regenerate the key pair from time to time without affecting
2307132451Sroberto * operations. The public key is conveyed on the certificate in an
2308132451Sroberto * extension field; the private key is never revealed.
2309132451Sroberto *
2310132451Sroberto * Alice rolls new random challenge r and sends to Bob in the GQ
2311132451Sroberto * request message. Bob rolls new random k, then computes y = k u^r mod
2312132451Sroberto * n and x = k^b mod n and sends (y, hash(x)) to Alice in the response
2313132451Sroberto * message. Besides making the response shorter, the hash makes it
2314132451Sroberto * effectivey impossible for an intruder to solve for b by observing
2315132451Sroberto * a number of these messages.
2316132451Sroberto *
2317132451Sroberto * Alice receives the response and computes y^b v^r mod n. After a bit
2318132451Sroberto * of algebra, this simplifies to k^b. If the hash of this result
2319132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed
2320132451Sroberto * response binds this knowledge to Bob's private key and the public key
2321132451Sroberto * previously received in his certificate.
2322132451Sroberto *
2323132451Sroberto * crypto_alice2 - construct Alice's challenge in GQ scheme
2324132451Sroberto *
2325132451Sroberto * Returns
2326132451Sroberto * XEVNT_OK	success
2327132451Sroberto * XEVNT_PUB	bad or missing public key
2328132451Sroberto * XEVNT_ID	bad or missing identity parameters
2329132451Sroberto */
2330132451Srobertostatic int
2331132451Srobertocrypto_alice2(
2332132451Sroberto	struct peer *peer,	/* peer pointer */
2333132451Sroberto	struct value *vp	/* value pointer */
2334132451Sroberto	)
2335132451Sroberto{
2336132451Sroberto	RSA	*rsa;		/* GQ parameters */
2337132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2338132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2339132451Sroberto	tstamp_t tstamp;
2340132451Sroberto	u_int	len;
2341132451Sroberto
2342132451Sroberto	/*
2343132451Sroberto	 * The identity parameters must have correct format and content.
2344132451Sroberto	 */
2345132451Sroberto	if (peer->ident_pkey == NULL)
2346132451Sroberto		return (XEVNT_ID);
2347132451Sroberto	if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
2348132451Sroberto		msyslog(LOG_INFO, "crypto_alice2: defective key");
2349132451Sroberto		return (XEVNT_PUB);
235082498Sroberto	}
235182498Sroberto
235282498Sroberto	/*
2353132451Sroberto	 * Roll new random r (0 < r < n). The OpenSSL library has a bug
2354132451Sroberto	 * omitting BN_rand_range, so we have to do it the hard way.
235582498Sroberto	 */
2356132451Sroberto	bctx = BN_CTX_new();
2357132451Sroberto	len = BN_num_bytes(rsa->n);
2358132451Sroberto	if (peer->iffval != NULL)
2359132451Sroberto		BN_free(peer->iffval);
2360132451Sroberto	peer->iffval = BN_new();
2361132451Sroberto	BN_rand(peer->iffval, len * 8, -1, 1);	/* r mod n */
2362132451Sroberto	BN_mod(peer->iffval, peer->iffval, rsa->n, bctx);
2363132451Sroberto	BN_CTX_free(bctx);
2364132451Sroberto
2365132451Sroberto	/*
2366132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2367132451Sroberto	 */
2368132451Sroberto	tstamp = crypto_time();
2369132451Sroberto	memset(vp, 0, sizeof(struct value));
2370132451Sroberto	vp->tstamp = htonl(tstamp);
2371132451Sroberto	vp->fstamp = htonl(peer->fstamp);
2372132451Sroberto	vp->vallen = htonl(len);
2373132451Sroberto	vp->ptr = emalloc(len);
2374132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2375132451Sroberto	vp->siglen = 0;
2376132451Sroberto	if (tstamp == 0)
2377132451Sroberto		return (XEVNT_OK);
2378132451Sroberto	vp->sig = emalloc(sign_siglen);
2379132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2380132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2381132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2382132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2383132451Sroberto		vp->siglen = htonl(len);
2384132451Sroberto	return (XEVNT_OK);
2385132451Sroberto}
2386132451Sroberto
2387132451Sroberto
2388132451Sroberto/*
2389132451Sroberto * crypto_bob2 - construct Bob's response to Alice's challenge
2390132451Sroberto *
2391132451Sroberto * Returns
2392132451Sroberto * XEVNT_OK	success
2393132451Sroberto * XEVNT_PUB	bad or missing public key
2394132451Sroberto */
2395132451Srobertostatic int
2396132451Srobertocrypto_bob2(
2397132451Sroberto	struct exten *ep,	/* extension pointer */
2398132451Sroberto	struct value *vp	/* value pointer */
2399132451Sroberto	)
2400132451Sroberto{
2401132451Sroberto	RSA	*rsa;		/* GQ parameters */
2402132451Sroberto	DSA_SIG	*sdsa;		/* DSA parameters */
2403132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2404132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2405132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2406132451Sroberto	BIGNUM	*r, *k, *g, *y;
2407132451Sroberto	u_char	*ptr;
2408132451Sroberto	u_int	len;
2409132451Sroberto
2410132451Sroberto	/*
2411132451Sroberto	 * If the GQ parameters are not valid, something awful
2412132451Sroberto	 * happened or we are being tormented.
2413132451Sroberto	 */
2414132451Sroberto	if (!(crypto_flags & CRYPTO_FLAG_GQ)) {
2415132451Sroberto		msyslog(LOG_INFO, "crypto_bob2: scheme unavailable");
2416132451Sroberto		return (XEVNT_PUB);
241782498Sroberto	}
2418132451Sroberto	rsa = gqpar_pkey->pkey.rsa;
241982498Sroberto
242082498Sroberto	/*
2421132451Sroberto	 * Extract r from the challenge.
242282498Sroberto	 */
2423132451Sroberto	len = ntohl(ep->vallen);
2424132451Sroberto	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2425132451Sroberto		msyslog(LOG_ERR, "crypto_bob2 %s\n",
2426132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2427132451Sroberto		return (XEVNT_PUB);
2428132451Sroberto	}
2429132451Sroberto
2430132451Sroberto	/*
2431132451Sroberto	 * Bob rolls random k (0 < k < n), computes y = k u^r mod n and
2432132451Sroberto	 * x = k^b mod n, then sends (y, hash(x)) to Alice.
2433132451Sroberto	 */
2434132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); g = BN_new(); y = BN_new();
2435132451Sroberto	sdsa = DSA_SIG_new();
2436132451Sroberto	BN_rand(k, len * 8, -1, 1);		/* k */
2437132451Sroberto	BN_mod(k, k, rsa->n, bctx);
2438132451Sroberto	BN_mod_exp(y, rsa->p, r, rsa->n, bctx); /* u^r mod n */
2439132451Sroberto	BN_mod_mul(y, k, y, rsa->n, bctx);	/* k u^r mod n */
2440132451Sroberto	sdsa->r = BN_dup(y);
2441132451Sroberto	BN_mod_exp(g, k, rsa->e, rsa->n, bctx); /* k^b mod n */
2442132451Sroberto	bighash(g, g);
2443132451Sroberto	sdsa->s = BN_dup(g);
2444132451Sroberto	BN_CTX_free(bctx);
2445132451Sroberto	BN_free(r); BN_free(k); BN_free(g); BN_free(y);
2446132451Sroberto
2447132451Sroberto	/*
2448132451Sroberto	 * Encode the values in ASN.1 and sign.
2449132451Sroberto	 */
2450132451Sroberto	tstamp = crypto_time();
2451132451Sroberto	memset(vp, 0, sizeof(struct value));
2452132451Sroberto	vp->tstamp = htonl(tstamp);
2453132451Sroberto	vp->fstamp = htonl(gq_fstamp);
2454132451Sroberto	len = i2d_DSA_SIG(sdsa, NULL);
2455132451Sroberto	if (len <= 0) {
2456132451Sroberto		msyslog(LOG_ERR, "crypto_bob2 %s\n",
2457132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2458132451Sroberto		DSA_SIG_free(sdsa);
2459132451Sroberto		return (XEVNT_PUB);
2460132451Sroberto	}
2461132451Sroberto	vp->vallen = htonl(len);
2462132451Sroberto	ptr = emalloc(len);
2463132451Sroberto	vp->ptr = ptr;
2464132451Sroberto	i2d_DSA_SIG(sdsa, &ptr);
2465132451Sroberto	DSA_SIG_free(sdsa);
2466132451Sroberto	vp->siglen = 0;
2467132451Sroberto	if (tstamp == 0)
2468132451Sroberto		return (XEVNT_OK);
2469132451Sroberto	vp->sig = emalloc(sign_siglen);
2470132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2471132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2472132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2473132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2474132451Sroberto		vp->siglen = htonl(len);
2475132451Sroberto	return (XEVNT_OK);
2476132451Sroberto}
2477132451Sroberto
2478132451Sroberto
2479132451Sroberto/*
2480132451Sroberto * crypto_gq - verify Bob's response to Alice's challenge
2481132451Sroberto *
2482132451Sroberto * Returns
2483132451Sroberto * XEVNT_OK	success
2484132451Sroberto * XEVNT_PUB	bad or missing public key
2485132451Sroberto * XEVNT_FSP	bad filestamp
2486132451Sroberto * XEVNT_ID	bad or missing identity parameters
2487132451Sroberto */
2488132451Srobertoint
2489132451Srobertocrypto_gq(
2490132451Sroberto	struct exten *ep,	/* extension pointer */
2491132451Sroberto	struct peer *peer	/* peer structure pointer */
2492132451Sroberto	)
2493132451Sroberto{
2494132451Sroberto	RSA	*rsa;		/* GQ parameters */
2495132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2496132451Sroberto	DSA_SIG	*sdsa;		/* RSA signature context fake */
2497132451Sroberto	BIGNUM	*y, *v;
2498132451Sroberto	const u_char	*ptr;
2499132451Sroberto	u_int	len;
2500132451Sroberto	int	temp;
2501132451Sroberto
2502132451Sroberto	/*
2503132451Sroberto	 * If the GQ parameters are not valid or no challenge was sent,
2504132451Sroberto	 * something awful happened or we are being tormented.
2505132451Sroberto	 */
2506132451Sroberto	if (peer->ident_pkey == NULL) {
2507132451Sroberto		msyslog(LOG_INFO, "crypto_gq: scheme unavailable");
2508132451Sroberto		return (XEVNT_PUB);
2509132451Sroberto	}
2510132451Sroberto	if (ntohl(ep->fstamp) != peer->fstamp) {
2511132451Sroberto		msyslog(LOG_INFO, "crypto_gq: invalid filestamp %u",
2512132451Sroberto		    ntohl(ep->fstamp));
2513132451Sroberto		return (XEVNT_FSP);
2514132451Sroberto	}
2515132451Sroberto	if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
2516132451Sroberto		msyslog(LOG_INFO, "crypto_gq: defective key");
2517132451Sroberto		return (XEVNT_PUB);
2518132451Sroberto	}
2519132451Sroberto	if (peer->iffval == NULL) {
2520132451Sroberto		msyslog(LOG_INFO, "crypto_gq: missing challenge");
2521132451Sroberto		return (XEVNT_PUB);
2522132451Sroberto	}
2523132451Sroberto
2524132451Sroberto	/*
2525132451Sroberto	 * Extract the y = k u^r and hash(x = k^b) values from the
2526132451Sroberto	 * response.
2527132451Sroberto	 */
2528132451Sroberto	bctx = BN_CTX_new(); y = BN_new(); v = BN_new();
2529132451Sroberto	len = ntohl(ep->vallen);
2530132451Sroberto	ptr = (const u_char *)ep->pkt;
2531132451Sroberto	if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
2532132451Sroberto		msyslog(LOG_ERR, "crypto_gq %s\n",
2533132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2534132451Sroberto		return (XEVNT_PUB);
2535132451Sroberto	}
2536132451Sroberto
2537132451Sroberto	/*
2538132451Sroberto	 * Compute v^r y^b mod n.
2539132451Sroberto	 */
2540132451Sroberto	BN_mod_exp(v, peer->grpkey, peer->iffval, rsa->n, bctx);
2541132451Sroberto						/* v^r mod n */
2542132451Sroberto	BN_mod_exp(y, sdsa->r, rsa->e, rsa->n, bctx); /* y^b mod n */
2543132451Sroberto	BN_mod_mul(y, v, y, rsa->n, bctx);	/* v^r y^b mod n */
2544132451Sroberto
2545132451Sroberto	/*
2546132451Sroberto	 * Verify the hash of the result matches hash(x).
2547132451Sroberto	 */
2548132451Sroberto	bighash(y, y);
2549132451Sroberto	temp = BN_cmp(y, sdsa->s);
2550132451Sroberto	BN_CTX_free(bctx); BN_free(y); BN_free(v);
2551132451Sroberto	BN_free(peer->iffval);
2552132451Sroberto	peer->iffval = NULL;
2553132451Sroberto	DSA_SIG_free(sdsa);
2554132451Sroberto	if (temp == 0)
2555132451Sroberto		return (XEVNT_OK);
255682498Sroberto	else
2557132451Sroberto		return (XEVNT_ID);
2558132451Sroberto}
2559132451Sroberto
2560132451Sroberto
2561132451Sroberto/*
2562132451Sroberto ***********************************************************************
2563132451Sroberto *								       *
2564132451Sroberto * The following routines implement the Mu-Varadharajan (MV) identity  *
2565132451Sroberto * scheme                                                              *
2566132451Sroberto *								       *
2567132451Sroberto ***********************************************************************
2568132451Sroberto */
2569132451Sroberto/*
2570132451Sroberto * The Mu-Varadharajan (MV) cryptosystem was originally intended when
2571132451Sroberto * servers broadcast messages to clients, but clients never send
2572132451Sroberto * messages to servers. There is one encryption key for the server and a
2573132451Sroberto * separate decryption key for each client. It operated something like a
2574132451Sroberto * pay-per-view satellite broadcasting system where the session key is
2575132451Sroberto * encrypted by the broadcaster and the decryption keys are held in a
2576132451Sroberto * tamperproof set-top box.
2577132451Sroberto *
2578132451Sroberto * The MV parameters and private encryption key hide in a DSA cuckoo
2579132451Sroberto * structure which uses the same parameters, but generated in a
2580132451Sroberto * different way. The values are used in an encryption scheme similar to
2581132451Sroberto * El Gamal cryptography and a polynomial formed from the expansion of
2582132451Sroberto * product terms (x - x[j]), as described in Mu, Y., and V.
2583132451Sroberto * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001,
2584132451Sroberto * 223-231. The paper has significant errors and serious omissions.
2585132451Sroberto *
2586132451Sroberto * Let q be the product of n distinct primes s'[j] (j = 1...n), where
2587132451Sroberto * each s'[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
2588132451Sroberto * that q and each s'[j] divide p - 1 and p has M = n * m + 1
2589132451Sroberto * significant bits. The elements x mod q of Zq with the elements 2 and
2590132451Sroberto * the primes removed form a field Zq* valid for polynomial arithetic.
2591132451Sroberto * Let g be a generator of Zp; that is, gcd(g, p - 1) = 1 and g^q = 1
2592132451Sroberto * mod p. We expect M to be in the 500-bit range and n relatively small,
2593132451Sroberto * like 25, so the likelihood of a randomly generated element of x mod q
2594132451Sroberto * of Zq colliding with a factor of p - 1 is very small and can be
2595132451Sroberto * avoided. Associated with each s'[j] is an element s[j] such that s[j]
2596132451Sroberto * s'[j] = s'[j] mod q. We find s[j] as the quotient (q + s'[j]) /
2597132451Sroberto * s'[j]. These are the parameters of the scheme and they are expensive
2598132451Sroberto * to compute.
2599132451Sroberto *
2600132451Sroberto * We set up an instance of the scheme as follows. A set of random
2601132451Sroberto * values x[j] mod q (j = 1...n), are generated as the zeros of a
2602132451Sroberto * polynomial of order n. The product terms (x - x[j]) are expanded to
2603132451Sroberto * form coefficients a[i] mod q (i = 0...n) in powers of x. These are
2604132451Sroberto * used as exponents of the generator g mod p to generate the private
2605132451Sroberto * encryption key A. The pair (gbar, ghat) of public server keys and the
2606132451Sroberto * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used
2607132451Sroberto * to construct the decryption keys. The devil is in the details.
2608132451Sroberto *
2609132451Sroberto * The distinguishing characteristic of this scheme is the capability to
2610132451Sroberto * revoke keys. Included in the calculation of E, gbar and ghat is the
2611132451Sroberto * product s = prod(s'[j]) (j = 1...n) above. If the factor s'[j] is
2612132451Sroberto * subsequently removed from the product and E, gbar and ghat
2613132451Sroberto * recomputed, the jth client will no longer be able to compute E^-1 and
2614132451Sroberto * thus unable to decrypt the block.
2615132451Sroberto *
2616132451Sroberto * How it works
2617132451Sroberto *
2618132451Sroberto * The scheme goes like this. Bob has the server values (p, A, q, gbar,
2619132451Sroberto * ghat) and Alice the client values (p, xbar, xhat).
2620132451Sroberto *
2621132451Sroberto * Alice rolls new random challenge r (0 < r < p) and sends to Bob in
2622132451Sroberto * the MV request message. Bob rolls new random k (0 < k < q), encrypts
2623132451Sroberto * y = A^k mod p (a permutation) and sends (hash(y), gbar^k, ghat^k) to
2624132451Sroberto * Alice.
2625132451Sroberto *
2626132451Sroberto * Alice receives the response and computes the decryption key (the
2627132451Sroberto * inverse permutation) from previously obtained (xbar, xhat) and
2628132451Sroberto * (gbar^k, ghat^k) in the message. She computes the inverse, which is
2629132451Sroberto * unique by reasons explained in the ntp-keygen.c program sources. If
2630132451Sroberto * the hash of this result matches hash(y), Alice knows that Bob has the
2631132451Sroberto * group key b. The signed response binds this knowledge to Bob's
2632132451Sroberto * private key and the public key previously received in his
2633132451Sroberto * certificate.
2634132451Sroberto *
2635132451Sroberto * crypto_alice3 - construct Alice's challenge in MV scheme
2636132451Sroberto *
2637132451Sroberto * Returns
2638132451Sroberto * XEVNT_OK	success
2639132451Sroberto * XEVNT_PUB	bad or missing public key
2640132451Sroberto * XEVNT_ID	bad or missing identity parameters
2641132451Sroberto */
2642132451Srobertostatic int
2643132451Srobertocrypto_alice3(
2644132451Sroberto	struct peer *peer,	/* peer pointer */
2645132451Sroberto	struct value *vp	/* value pointer */
2646132451Sroberto	)
2647132451Sroberto{
2648132451Sroberto	DSA	*dsa;		/* MV parameters */
2649132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2650132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2651132451Sroberto	tstamp_t tstamp;
2652132451Sroberto	u_int	len;
2653132451Sroberto
2654132451Sroberto	/*
2655132451Sroberto	 * The identity parameters must have correct format and content.
2656132451Sroberto	 */
2657132451Sroberto	if (peer->ident_pkey == NULL)
2658132451Sroberto		return (XEVNT_ID);
2659132451Sroberto	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
2660132451Sroberto		msyslog(LOG_INFO, "crypto_alice3: defective key");
2661132451Sroberto		return (XEVNT_PUB);
266282498Sroberto	}
266382498Sroberto
266482498Sroberto	/*
2665132451Sroberto	 * Roll new random r (0 < r < q). The OpenSSL library has a bug
2666132451Sroberto	 * omitting BN_rand_range, so we have to do it the hard way.
266782498Sroberto	 */
2668132451Sroberto	bctx = BN_CTX_new();
2669132451Sroberto	len = BN_num_bytes(dsa->p);
2670132451Sroberto	if (peer->iffval != NULL)
2671132451Sroberto		BN_free(peer->iffval);
2672132451Sroberto	peer->iffval = BN_new();
2673132451Sroberto	BN_rand(peer->iffval, len * 8, -1, 1);	/* r */
2674132451Sroberto	BN_mod(peer->iffval, peer->iffval, dsa->p, bctx);
2675132451Sroberto	BN_CTX_free(bctx);
2676132451Sroberto
2677132451Sroberto	/*
2678132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2679132451Sroberto	 */
2680132451Sroberto	tstamp = crypto_time();
2681132451Sroberto	memset(vp, 0, sizeof(struct value));
2682132451Sroberto	vp->tstamp = htonl(tstamp);
2683132451Sroberto	vp->fstamp = htonl(peer->fstamp);
2684132451Sroberto	vp->vallen = htonl(len);
2685132451Sroberto	vp->ptr = emalloc(len);
2686132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2687132451Sroberto	vp->siglen = 0;
2688132451Sroberto	if (tstamp == 0)
2689132451Sroberto		return (XEVNT_OK);
2690132451Sroberto	vp->sig = emalloc(sign_siglen);
2691132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2692132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2693132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2694132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2695132451Sroberto		vp->siglen = htonl(len);
2696132451Sroberto	return (XEVNT_OK);
2697132451Sroberto}
2698132451Sroberto
2699132451Sroberto
2700132451Sroberto/*
2701132451Sroberto * crypto_bob3 - construct Bob's response to Alice's challenge
2702132451Sroberto *
2703132451Sroberto * Returns
2704132451Sroberto * XEVNT_OK	success
2705132451Sroberto * XEVNT_PUB	bad or missing public key
2706132451Sroberto */
2707132451Srobertostatic int
2708132451Srobertocrypto_bob3(
2709132451Sroberto	struct exten *ep,	/* extension pointer */
2710132451Sroberto	struct value *vp	/* value pointer */
2711132451Sroberto	)
2712132451Sroberto{
2713132451Sroberto	DSA	*dsa;		/* MV parameters */
2714132451Sroberto	DSA	*sdsa;		/* DSA signature context fake */
2715132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2716132451Sroberto	EVP_MD_CTX ctx;		/* signature context */
2717132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2718132451Sroberto	BIGNUM	*r, *k, *u;
2719132451Sroberto	u_char	*ptr;
2720132451Sroberto	u_int	len;
2721132451Sroberto
2722132451Sroberto	/*
2723132451Sroberto	 * If the MV parameters are not valid, something awful
2724132451Sroberto	 * happened or we are being tormented.
2725132451Sroberto	 */
2726132451Sroberto	if (!(crypto_flags & CRYPTO_FLAG_MV)) {
2727132451Sroberto		msyslog(LOG_INFO, "crypto_bob3: scheme unavailable");
2728132451Sroberto		return (XEVNT_PUB);
272982498Sroberto	}
2730132451Sroberto	dsa = mvpar_pkey->pkey.dsa;
2731132451Sroberto
2732132451Sroberto	/*
2733132451Sroberto	 * Extract r from the challenge.
2734132451Sroberto	 */
2735132451Sroberto	len = ntohl(ep->vallen);
2736132451Sroberto	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2737132451Sroberto		msyslog(LOG_ERR, "crypto_bob3 %s\n",
2738132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2739132451Sroberto		return (XEVNT_PUB);
2740132451Sroberto	}
2741132451Sroberto
2742132451Sroberto	/*
2743132451Sroberto	 * Bob rolls random k (0 < k < q), making sure it is not a
2744132451Sroberto	 * factor of q. He then computes y = A^k r and sends (hash(y),
2745132451Sroberto	 * gbar^k, ghat^k) to Alice.
2746132451Sroberto	 */
2747132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); u = BN_new();
2748132451Sroberto	sdsa = DSA_new();
2749132451Sroberto	sdsa->p = BN_new(); sdsa->q = BN_new(); sdsa->g = BN_new();
2750132451Sroberto	while (1) {
2751132451Sroberto		BN_rand(k, BN_num_bits(dsa->q), 0, 0);
2752132451Sroberto		BN_mod(k, k, dsa->q, bctx);
2753132451Sroberto		BN_gcd(u, k, dsa->q, bctx);
2754132451Sroberto		if (BN_is_one(u))
2755132451Sroberto			break;
2756132451Sroberto	}
2757132451Sroberto	BN_mod_exp(u, dsa->g, k, dsa->p, bctx); /* A r */
2758132451Sroberto	BN_mod_mul(u, u, r, dsa->p, bctx);
2759132451Sroberto	bighash(u, sdsa->p);
2760132451Sroberto	BN_mod_exp(sdsa->q, dsa->priv_key, k, dsa->p, bctx); /* gbar */
2761132451Sroberto	BN_mod_exp(sdsa->g, dsa->pub_key, k, dsa->p, bctx); /* ghat */
2762132451Sroberto	BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u);
2763132451Sroberto
2764132451Sroberto	/*
2765132451Sroberto	 * Encode the values in ASN.1 and sign.
2766132451Sroberto	 */
2767132451Sroberto	tstamp = crypto_time();
2768132451Sroberto	memset(vp, 0, sizeof(struct value));
2769132451Sroberto	vp->tstamp = htonl(tstamp);
2770132451Sroberto	vp->fstamp = htonl(mv_fstamp);
2771132451Sroberto	len = i2d_DSAparams(sdsa, NULL);
2772132451Sroberto	if (len <= 0) {
2773132451Sroberto		msyslog(LOG_ERR, "crypto_bob3 %s\n",
2774132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2775132451Sroberto		DSA_free(sdsa);
2776132451Sroberto		return (XEVNT_PUB);
2777132451Sroberto	}
2778132451Sroberto	vp->vallen = htonl(len);
2779132451Sroberto	ptr = emalloc(len);
2780132451Sroberto	vp->ptr = ptr;
2781132451Sroberto	i2d_DSAparams(sdsa, &ptr);
2782132451Sroberto	DSA_free(sdsa);
2783132451Sroberto	vp->siglen = 0;
2784132451Sroberto	if (tstamp == 0)
2785132451Sroberto		return (XEVNT_OK);
2786132451Sroberto	vp->sig = emalloc(sign_siglen);
2787132451Sroberto	EVP_SignInit(&ctx, sign_digest);
2788132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
2789132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
2790132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
2791132451Sroberto		vp->siglen = htonl(len);
2792132451Sroberto	return (XEVNT_OK);
2793132451Sroberto}
2794132451Sroberto
2795132451Sroberto
2796132451Sroberto/*
2797132451Sroberto * crypto_mv - verify Bob's response to Alice's challenge
2798132451Sroberto *
2799132451Sroberto * Returns
2800132451Sroberto * XEVNT_OK	success
2801132451Sroberto * XEVNT_PUB	bad or missing public key
2802132451Sroberto * XEVNT_FSP	bad filestamp
2803132451Sroberto * XEVNT_ID	bad or missing identity parameters
2804132451Sroberto */
2805132451Srobertoint
2806132451Srobertocrypto_mv(
2807132451Sroberto	struct exten *ep,	/* extension pointer */
2808132451Sroberto	struct peer *peer	/* peer structure pointer */
2809132451Sroberto	)
2810132451Sroberto{
2811132451Sroberto	DSA	*dsa;		/* MV parameters */
2812132451Sroberto	DSA	*sdsa;		/* DSA parameters */
2813132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2814132451Sroberto	BIGNUM	*k, *u, *v;
2815132451Sroberto	u_int	len;
2816132451Sroberto	const u_char	*ptr;
2817132451Sroberto	int	temp;
2818132451Sroberto
2819132451Sroberto	/*
2820132451Sroberto	 * If the MV parameters are not valid or no challenge was sent,
2821132451Sroberto	 * something awful happened or we are being tormented.
2822132451Sroberto	 */
2823132451Sroberto	if (peer->ident_pkey == NULL) {
2824132451Sroberto		msyslog(LOG_INFO, "crypto_mv: scheme unavailable");
2825132451Sroberto		return (XEVNT_PUB);
2826132451Sroberto	}
2827132451Sroberto	if (ntohl(ep->fstamp) != peer->fstamp) {
2828132451Sroberto		msyslog(LOG_INFO, "crypto_mv: invalid filestamp %u",
2829132451Sroberto		    ntohl(ep->fstamp));
2830132451Sroberto		return (XEVNT_FSP);
2831132451Sroberto	}
2832132451Sroberto	if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
2833132451Sroberto		msyslog(LOG_INFO, "crypto_mv: defective key");
2834132451Sroberto		return (XEVNT_PUB);
2835132451Sroberto	}
2836132451Sroberto	if (peer->iffval == NULL) {
2837132451Sroberto		msyslog(LOG_INFO, "crypto_mv: missing challenge");
2838132451Sroberto		return (XEVNT_PUB);
2839132451Sroberto	}
2840132451Sroberto
2841132451Sroberto	/*
2842132451Sroberto	 * Extract the (hash(y), gbar, ghat) values from the response.
2843132451Sroberto	 */
2844132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); v = BN_new();
2845132451Sroberto	len = ntohl(ep->vallen);
2846132451Sroberto	ptr = (const u_char *)ep->pkt;
2847132451Sroberto	if ((sdsa = d2i_DSAparams(NULL, &ptr, len)) == NULL) {
2848132451Sroberto		msyslog(LOG_ERR, "crypto_mv %s\n",
2849132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2850132451Sroberto		return (XEVNT_PUB);
2851132451Sroberto	}
2852132451Sroberto
2853132451Sroberto	/*
2854132451Sroberto	 * Compute (gbar^xhat ghat^xbar)^-1 mod p.
2855132451Sroberto	 */
2856132451Sroberto	BN_mod_exp(u, sdsa->q, dsa->pub_key, dsa->p, bctx);
2857132451Sroberto	BN_mod_exp(v, sdsa->g, dsa->priv_key, dsa->p, bctx);
2858132451Sroberto	BN_mod_mul(u, u, v, dsa->p, bctx);
2859132451Sroberto	BN_mod_inverse(u, u, dsa->p, bctx);
2860132451Sroberto	BN_mod_mul(v, u, peer->iffval, dsa->p, bctx);
2861132451Sroberto
2862132451Sroberto	/*
2863132451Sroberto	 * The result should match the hash of r mod p.
2864132451Sroberto	 */
2865132451Sroberto	bighash(v, v);
2866132451Sroberto	temp = BN_cmp(v, sdsa->p);
2867132451Sroberto	BN_CTX_free(bctx); BN_free(k); BN_free(u); BN_free(v);
2868132451Sroberto	BN_free(peer->iffval);
2869132451Sroberto	peer->iffval = NULL;
2870132451Sroberto	DSA_free(sdsa);
2871132451Sroberto	if (temp == 0)
2872132451Sroberto		return (XEVNT_OK);
287382498Sroberto	else
2874132451Sroberto		return (XEVNT_ID);
2875132451Sroberto}
2876132451Sroberto
2877132451Sroberto
2878132451Sroberto/*
2879132451Sroberto ***********************************************************************
2880132451Sroberto *								       *
2881132451Sroberto * The following routines are used to manipulate certificates          *
2882132451Sroberto *								       *
2883132451Sroberto ***********************************************************************
2884132451Sroberto */
2885132451Sroberto/*
2886132451Sroberto * cert_parse - parse x509 certificate and create info/value structures.
2887132451Sroberto *
2888132451Sroberto * The server certificate includes the version number, issuer name,
2889132451Sroberto * subject name, public key and valid date interval. If the issuer name
2890132451Sroberto * is the same as the subject name, the certificate is self signed and
2891132451Sroberto * valid only if the server is configured as trustable. If the names are
2892132451Sroberto * different, another issuer has signed the server certificate and
2893132451Sroberto * vouched for it. In this case the server certificate is valid if
2894132451Sroberto * verified by the issuer public key.
2895132451Sroberto *
2896132451Sroberto * Returns certificate info/value pointer if valid, NULL if not.
2897132451Sroberto */
2898132451Srobertostruct cert_info *		/* certificate information structure */
2899132451Srobertocert_parse(
2900132451Sroberto	u_char	*asn1cert,	/* X509 certificate */
2901132451Sroberto	u_int	len,		/* certificate length */
2902132451Sroberto	tstamp_t fstamp		/* filestamp */
2903132451Sroberto	)
2904132451Sroberto{
2905132451Sroberto	X509	*cert;		/* X509 certificate */
2906132451Sroberto	X509_EXTENSION *ext;	/* X509v3 extension */
2907132451Sroberto	struct cert_info *ret;	/* certificate info/value */
2908132451Sroberto	BIO	*bp;
2909132451Sroberto	X509V3_EXT_METHOD *method;
2910132451Sroberto	char	pathbuf[MAXFILENAME];
2911132451Sroberto	u_char	*uptr;
2912132451Sroberto	char	*ptr;
2913132451Sroberto	int	temp, cnt, i;
2914132451Sroberto
2915132451Sroberto	/*
2916132451Sroberto	 * Decode ASN.1 objects and construct certificate structure.
2917132451Sroberto	 */
2918132451Sroberto	uptr = asn1cert;
2919132451Sroberto	if ((cert = d2i_X509(NULL, &uptr, len)) == NULL) {
2920132451Sroberto		msyslog(LOG_ERR, "cert_parse %s\n",
2921132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2922132451Sroberto		return (NULL);
2923132451Sroberto	}
2924132451Sroberto
2925132451Sroberto	/*
2926132451Sroberto	 * Extract version, subject name and public key.
2927132451Sroberto	 */
2928132451Sroberto	ret = emalloc(sizeof(struct cert_info));
2929132451Sroberto	memset(ret, 0, sizeof(struct cert_info));
2930132451Sroberto	if ((ret->pkey = X509_get_pubkey(cert)) == NULL) {
2931132451Sroberto		msyslog(LOG_ERR, "cert_parse %s\n",
2932132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2933132451Sroberto		cert_free(ret);
2934132451Sroberto		X509_free(cert);
2935132451Sroberto		return (NULL);
2936132451Sroberto	}
2937132451Sroberto	ret->version = X509_get_version(cert);
2938132451Sroberto	X509_NAME_oneline(X509_get_subject_name(cert), pathbuf,
2939132451Sroberto	    MAXFILENAME - 1);
2940132451Sroberto	ptr = strstr(pathbuf, "CN=");
2941132451Sroberto	if (ptr == NULL) {
2942132451Sroberto		msyslog(LOG_INFO, "cert_parse: invalid subject %s",
2943132451Sroberto		    pathbuf);
2944132451Sroberto		cert_free(ret);
2945132451Sroberto		X509_free(cert);
2946132451Sroberto		return (NULL);
2947132451Sroberto	}
2948132451Sroberto	ret->subject = emalloc(strlen(ptr) + 1);
2949132451Sroberto	strcpy(ret->subject, ptr + 3);
2950132451Sroberto
2951132451Sroberto	/*
2952132451Sroberto	 * Extract remaining objects. Note that the NTP serial number is
2953132451Sroberto	 * the NTP seconds at the time of signing, but this might not be
2954132451Sroberto	 * the case for other authority. We don't bother to check the
2955132451Sroberto	 * objects at this time, since the real crunch can happen only
2956132451Sroberto	 * when the time is valid but not yet certificated.
2957132451Sroberto	 */
2958132451Sroberto	ret->nid = OBJ_obj2nid(cert->cert_info->signature->algorithm);
2959132451Sroberto	ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid);
2960132451Sroberto	ret->serial =
2961132451Sroberto	    (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert));
2962132451Sroberto	X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf,
2963132451Sroberto	    MAXFILENAME);
2964132451Sroberto	if ((ptr = strstr(pathbuf, "CN=")) == NULL) {
2965132451Sroberto		msyslog(LOG_INFO, "cert_parse: invalid issuer %s",
2966132451Sroberto		    pathbuf);
2967132451Sroberto		cert_free(ret);
2968132451Sroberto		X509_free(cert);
2969132451Sroberto		return (NULL);
2970132451Sroberto	}
2971132451Sroberto	ret->issuer = emalloc(strlen(ptr) + 1);
2972132451Sroberto	strcpy(ret->issuer, ptr + 3);
2973132451Sroberto	ret->first = asn2ntp(X509_get_notBefore(cert));
2974132451Sroberto	ret->last = asn2ntp(X509_get_notAfter(cert));
2975132451Sroberto
2976132451Sroberto	/*
2977132451Sroberto	 * Extract extension fields. These are ad hoc ripoffs of
2978132451Sroberto	 * currently assigned functions and will certainly be changed
2979132451Sroberto	 * before prime time.
2980132451Sroberto	 */
2981132451Sroberto	cnt = X509_get_ext_count(cert);
2982132451Sroberto	for (i = 0; i < cnt; i++) {
2983132451Sroberto		ext = X509_get_ext(cert, i);
2984132451Sroberto		method = X509V3_EXT_get(ext);
2985132451Sroberto		temp = OBJ_obj2nid(ext->object);
2986132451Sroberto		switch (temp) {
2987132451Sroberto
2988132451Sroberto		/*
2989132451Sroberto		 * If a key_usage field is present, we decode whether
2990132451Sroberto		 * this is a trusted or private certificate. This is
2991132451Sroberto		 * dorky; all we want is to compare NIDs, but OpenSSL
2992132451Sroberto		 * insists on BIO text strings.
2993132451Sroberto		 */
2994132451Sroberto		case NID_ext_key_usage:
2995132451Sroberto			bp = BIO_new(BIO_s_mem());
2996132451Sroberto			X509V3_EXT_print(bp, ext, 0, 0);
2997132451Sroberto			BIO_gets(bp, pathbuf, MAXFILENAME);
2998132451Sroberto			BIO_free(bp);
2999132451Sroberto#if DEBUG
3000132451Sroberto			if (debug)
3001132451Sroberto				printf("cert_parse: %s: %s\n",
3002132451Sroberto				    OBJ_nid2ln(temp), pathbuf);
3003132451Sroberto#endif
3004132451Sroberto			if (strcmp(pathbuf, "Trust Root") == 0)
3005132451Sroberto				ret->flags |= CERT_TRUST;
3006132451Sroberto			else if (strcmp(pathbuf, "Private") == 0)
3007132451Sroberto				ret->flags |= CERT_PRIV;
3008132451Sroberto			break;
3009132451Sroberto
3010132451Sroberto		/*
3011132451Sroberto		 * If a NID_subject_key_identifier field is present, it
3012132451Sroberto		 * contains the GQ public key.
3013132451Sroberto		 */
3014132451Sroberto		case NID_subject_key_identifier:
3015132451Sroberto			ret->grplen = ext->value->length - 2;
3016132451Sroberto			ret->grpkey = emalloc(ret->grplen);
3017132451Sroberto			memcpy(ret->grpkey, &ext->value->data[2],
3018132451Sroberto			    ret->grplen);
3019132451Sroberto			break;
3020132451Sroberto		}
3021132451Sroberto	}
3022132451Sroberto
3023132451Sroberto	/*
3024132451Sroberto	 * If certificate is self signed, verify signature.
3025132451Sroberto	 */
3026132451Sroberto	if (strcmp(ret->subject, ret->issuer) == 0) {
3027132451Sroberto		if (!X509_verify(cert, ret->pkey)) {
3028132451Sroberto			msyslog(LOG_INFO,
3029132451Sroberto			    "cert_parse: invalid signature not verified %s",
3030132451Sroberto			    pathbuf);
3031132451Sroberto			cert_free(ret);
3032132451Sroberto			X509_free(cert);
3033132451Sroberto			return (NULL);
3034132451Sroberto		}
3035132451Sroberto	}
3036132451Sroberto
3037132451Sroberto	/*
3038132451Sroberto	 * Verify certificate valid times. Note that certificates cannot
3039132451Sroberto	 * be retroactive.
3040132451Sroberto	 */
3041132451Sroberto	if (ret->first > ret->last || ret->first < fstamp) {
3042132451Sroberto		msyslog(LOG_INFO,
3043132451Sroberto		    "cert_parse: expired %s",
3044132451Sroberto		    ret->subject);
3045132451Sroberto		cert_free(ret);
3046132451Sroberto		X509_free(cert);
3047132451Sroberto		return (NULL);
3048132451Sroberto	}
3049132451Sroberto
3050132451Sroberto	/*
3051132451Sroberto	 * Build the value structure to sign and send later.
3052132451Sroberto	 */
3053132451Sroberto	ret->cert.fstamp = htonl(fstamp);
3054132451Sroberto	ret->cert.vallen = htonl(len);
3055132451Sroberto	ret->cert.ptr = emalloc(len);
3056132451Sroberto	memcpy(ret->cert.ptr, asn1cert, len);
305782498Sroberto#ifdef DEBUG
3058132451Sroberto	if (debug > 1)
3059132451Sroberto		X509_print_fp(stdout, cert);
306082498Sroberto#endif
3061132451Sroberto	X509_free(cert);
3062132451Sroberto	return (ret);
306382498Sroberto}
306482498Sroberto
306582498Sroberto
306682498Sroberto/*
3067132451Sroberto * cert_sign - sign x509 certificate and update value structure.
3068132451Sroberto *
3069132451Sroberto * The certificate request is a copy of the client certificate, which
3070132451Sroberto * includes the version number, subject name and public key of the
3071132451Sroberto * client. The resulting certificate includes these values plus the
3072132451Sroberto * serial number, issuer name and validity interval of the server. The
3073132451Sroberto * validity interval extends from the current time to the same time one
3074132451Sroberto * year hence. For NTP purposes, it is convenient to use the NTP seconds
3075132451Sroberto * of the current time as the serial number.
3076132451Sroberto *
3077132451Sroberto * Returns
3078132451Sroberto * XEVNT_OK	success
3079132451Sroberto * XEVNT_PUB	bad or missing public key
3080132451Sroberto * XEVNT_CRT	bad or missing certificate
3081132451Sroberto * XEVNT_VFY	certificate not verified
308282498Sroberto */
3083132451Srobertostatic int
3084132451Srobertocert_sign(
3085132451Sroberto	struct exten *ep,	/* extension field pointer */
3086132451Sroberto	struct value *vp	/* value pointer */
308782498Sroberto	)
308882498Sroberto{
3089132451Sroberto	X509	*req;		/* X509 certificate request */
3090132451Sroberto	X509	*cert;		/* X509 certificate */
3091132451Sroberto	X509_EXTENSION *ext;	/* certificate extension */
3092132451Sroberto	ASN1_INTEGER *serial;	/* serial number */
3093132451Sroberto	X509_NAME *subj;	/* distinguished (common) name */
3094132451Sroberto	EVP_PKEY *pkey;		/* public key */
3095132451Sroberto	EVP_MD_CTX ctx;		/* message digest context */
3096132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
3097132451Sroberto	u_int	len;
3098132451Sroberto	u_char	*ptr;
3099132451Sroberto	int	i, temp;
310082498Sroberto
310182498Sroberto	/*
3102132451Sroberto	 * Decode ASN.1 objects and construct certificate structure.
310382498Sroberto	 */
3104132451Sroberto	tstamp = crypto_time();
3105132451Sroberto	if (tstamp == 0)
3106132451Sroberto		return (XEVNT_TSP);
3107132451Sroberto
3108132451Sroberto	ptr = (u_char *)ep->pkt;
3109132451Sroberto	if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
3110132451Sroberto		msyslog(LOG_ERR, "cert_sign %s\n",
3111132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3112132451Sroberto		return (XEVNT_CRT);
311382498Sroberto	}
3114132451Sroberto	/*
3115132451Sroberto	 * Extract public key and check for errors.
3116132451Sroberto	 */
3117132451Sroberto	if ((pkey = X509_get_pubkey(req)) == NULL) {
3118132451Sroberto		msyslog(LOG_ERR, "cert_sign %s\n",
3119132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3120132451Sroberto		X509_free(req);
3121132451Sroberto		return (XEVNT_PUB);
3122132451Sroberto	}
312382498Sroberto
312482498Sroberto	/*
3125132451Sroberto	 * Generate X509 certificate signed by this server. For this
3126132451Sroberto	 * prupose the issuer name is the server name. Also copy any
3127132451Sroberto	 * extensions that might be present.
312882498Sroberto	 */
3129132451Sroberto	cert = X509_new();
3130132451Sroberto	X509_set_version(cert, X509_get_version(req));
3131132451Sroberto	serial = ASN1_INTEGER_new();
3132132451Sroberto	ASN1_INTEGER_set(serial, tstamp);
3133132451Sroberto	X509_set_serialNumber(cert, serial);
3134132451Sroberto	X509_gmtime_adj(X509_get_notBefore(cert), 0L);
3135132451Sroberto	X509_gmtime_adj(X509_get_notAfter(cert), YEAR);
3136132451Sroberto	subj = X509_get_issuer_name(cert);
3137132451Sroberto	X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
3138132451Sroberto	    (unsigned char *) sys_hostname, strlen(sys_hostname), -1, 0);
3139132451Sroberto	subj = X509_get_subject_name(req);
3140132451Sroberto	X509_set_subject_name(cert, subj);
3141132451Sroberto	X509_set_pubkey(cert, pkey);
3142132451Sroberto	ext = X509_get_ext(req, 0);
3143132451Sroberto	temp = X509_get_ext_count(req);
3144132451Sroberto	for (i = 0; i < temp; i++) {
3145132451Sroberto		ext = X509_get_ext(req, i);
3146132451Sroberto		X509_add_ext(cert, ext, -1);
314782498Sroberto	}
3148132451Sroberto	X509_free(req);
314982498Sroberto
315082498Sroberto	/*
3151132451Sroberto	 * Sign and verify the certificate.
315282498Sroberto	 */
3153132451Sroberto	X509_sign(cert, sign_pkey, sign_digest);
3154132451Sroberto	if (!X509_verify(cert, sign_pkey)) {
3155132451Sroberto		printf("cert_sign\n%s\n",
3156132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3157132451Sroberto		X509_free(cert);
3158132451Sroberto		return (XEVNT_VFY);
3159132451Sroberto	}
3160132451Sroberto	len = i2d_X509(cert, NULL);
316182498Sroberto
316282498Sroberto	/*
3163132451Sroberto	 * Build and sign the value structure. We have to sign it here,
3164132451Sroberto	 * since the response has to be returned right away. This is a
3165132451Sroberto	 * clogging hazard.
316682498Sroberto	 */
3167132451Sroberto	memset(vp, 0, sizeof(struct value));
3168132451Sroberto	vp->tstamp = htonl(tstamp);
3169132451Sroberto	vp->fstamp = ep->fstamp;
3170132451Sroberto	vp->vallen = htonl(len);
3171132451Sroberto	vp->ptr = emalloc(len);
3172132451Sroberto	ptr = vp->ptr;
3173132451Sroberto	i2d_X509(cert, &ptr);
3174132451Sroberto	vp->siglen = 0;
3175132451Sroberto	vp->sig = emalloc(sign_siglen);
3176132451Sroberto	EVP_SignInit(&ctx, sign_digest);
3177132451Sroberto	EVP_SignUpdate(&ctx, (u_char *)vp, 12);
3178132451Sroberto	EVP_SignUpdate(&ctx, vp->ptr, len);
3179132451Sroberto	if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
3180132451Sroberto		vp->siglen = htonl(len);
318182498Sroberto#ifdef DEBUG
3182132451Sroberto	if (debug > 1)
3183132451Sroberto		X509_print_fp(stdout, cert);
318482498Sroberto#endif
3185132451Sroberto	X509_free(cert);
3186132451Sroberto	return (XEVNT_OK);
318782498Sroberto}
318882498Sroberto
318982498Sroberto
319082498Sroberto/*
3191132451Sroberto * cert_valid - verify certificate with given public key
3192132451Sroberto *
3193132451Sroberto * This is pretty ugly, as the certificate has to be verified in the
3194132451Sroberto * OpenSSL X509 structure, not in the DER format in the info/value
3195132451Sroberto * structure.
3196132451Sroberto *
3197132451Sroberto * Returns
3198132451Sroberto * XEVNT_OK	success
3199132451Sroberto * XEVNT_VFY	certificate not verified
320082498Sroberto */
3201132451Srobertoint
3202132451Srobertocert_valid(
3203132451Sroberto	struct cert_info *cinf,	/* certificate information structure */
3204132451Sroberto	EVP_PKEY *pkey		/* public key */
320582498Sroberto	)
320682498Sroberto{
3207132451Sroberto	X509	*cert;		/* X509 certificate */
3208132451Sroberto	u_char	*ptr;
320982498Sroberto
3210132451Sroberto	if (cinf->flags & CERT_SIGN)
3211132451Sroberto		return (XEVNT_OK);
3212132451Sroberto	ptr = (u_char *)cinf->cert.ptr;
3213132451Sroberto	cert = d2i_X509(NULL, &ptr, ntohl(cinf->cert.vallen));
3214132451Sroberto	if (!X509_verify(cert, pkey))
3215132451Sroberto		return (XEVNT_VFY);
3216132451Sroberto	cinf->flags |= CERT_SIGN;
3217132451Sroberto	X509_free(cert);
3218132451Sroberto	return (XEVNT_OK);
3219132451Sroberto}
3220132451Sroberto
3221132451Sroberto
3222132451Sroberto/*
3223132451Sroberto * cert - install certificate in certificate list
3224132451Sroberto *
3225132451Sroberto * This routine encodes an extension field into a certificate info/value
3226132451Sroberto * structure. It searches the certificate list for duplicates and
3227132451Sroberto * expunges whichever is older. It then searches the list for other
3228132451Sroberto * certificates that might be verified by this latest one. Finally, it
3229132451Sroberto * inserts this certificate first on the list.
3230132451Sroberto *
3231132451Sroberto * Returns
3232132451Sroberto * XEVNT_OK	success
3233132451Sroberto * XEVNT_PER	certificate expired
3234132451Sroberto * XEVNT_CRT	bad or missing certificate
3235132451Sroberto */
3236132451Srobertoint
3237132451Srobertocert_install(
3238132451Sroberto	struct exten *ep,	/* cert info/value */
3239132451Sroberto	struct peer *peer	/* peer structure */
3240132451Sroberto	)
3241132451Sroberto{
3242132451Sroberto	struct cert_info *cp, *xp, *yp, **zp;
3243132451Sroberto	int	rval;
3244132451Sroberto	tstamp_t tstamp;
3245132451Sroberto
324682498Sroberto	/*
3247132451Sroberto	 * Parse and validate the signed certificate. If valid,
3248132451Sroberto	 * construct the info/value structure; otherwise, scamper home.
3249132451Sroberto	 * Note this allows a certificate not-before time to be in the
3250132451Sroberto	 * future, but not a not-after time to be in the past.
325182498Sroberto	 */
3252132451Sroberto	if ((cp = cert_parse((u_char *)ep->pkt, ntohl(ep->vallen),
3253132451Sroberto	    ntohl(ep->fstamp))) == NULL)
3254132451Sroberto		return (XEVNT_CRT);
3255132451Sroberto
3256132451Sroberto	tstamp = crypto_time();
3257132451Sroberto	if (tstamp > cp->last) {
3258132451Sroberto		cert_free(cp);
3259132451Sroberto		return (XEVNT_PER);
3260132451Sroberto	}
3261132451Sroberto
3262132451Sroberto	/*
3263132451Sroberto	 * Scan certificate list looking for another certificate with
3264132451Sroberto	 * the same subject and issuer. If another is found with the
3265132451Sroberto	 * same or older filestamp, unlink it and return the goodies to
3266132451Sroberto	 * the heap. If another is found with a later filetsamp, discard
3267132451Sroberto	 * the new one and leave the building.
3268132451Sroberto	 */
3269132451Sroberto	rval = XEVNT_OK;
3270132451Sroberto	yp = cp;
3271132451Sroberto	zp = &cinfo;
3272132451Sroberto	for (xp = cinfo; xp != NULL; xp = xp->link) {
3273132451Sroberto		if (strcmp(cp->subject, xp->subject) == 0 &&
3274132451Sroberto		    strcmp(cp->issuer, xp->issuer) == 0) {
3275132451Sroberto			if (ntohl(cp->cert.fstamp) <=
3276132451Sroberto			    ntohl(xp->cert.fstamp)) {
3277132451Sroberto				*zp = xp->link;;
3278132451Sroberto				cert_free(xp);
3279132451Sroberto			} else {
3280132451Sroberto				cert_free(cp);
3281132451Sroberto				return (XEVNT_TSP);
3282132451Sroberto			}
3283132451Sroberto			break;
3284132451Sroberto		}
3285132451Sroberto		zp = &xp->link;
3286132451Sroberto	}
3287132451Sroberto	yp->link = cinfo;
3288132451Sroberto	cinfo = yp;
3289132451Sroberto
3290132451Sroberto	/*
3291132451Sroberto	 * Scan the certificate list to see if Y is signed by X.
3292132451Sroberto	 */
3293132451Sroberto	for (yp = cinfo; yp != NULL; yp = yp->link) {
3294132451Sroberto		for (xp = cinfo; xp != NULL; xp = xp->link) {
3295132451Sroberto			if (yp->flags & CERT_ERROR)
3296132451Sroberto				continue;
3297132451Sroberto
3298132451Sroberto			/*
3299132451Sroberto			 * If issuer Y matches subject X and signature Y
3300132451Sroberto			 * is valid using public key X, then Y is valid.
3301132451Sroberto			 */
3302132451Sroberto			if (strcmp(yp->issuer, xp->subject) != 0)
3303132451Sroberto				continue;
3304132451Sroberto
3305132451Sroberto			if (cert_valid(yp, xp->pkey) != XEVNT_OK) {
3306132451Sroberto				yp->flags |= CERT_ERROR;
3307132451Sroberto				continue;
3308132451Sroberto			}
3309132451Sroberto			xp->flags |= CERT_SIGN;
3310132451Sroberto
3311132451Sroberto			/*
3312132451Sroberto			 * If X is trusted, then Y is trusted. Note that
3313132451Sroberto			 * we might stumble over a self signed
3314132451Sroberto			 * certificate that is not trusted, at least
3315132451Sroberto			 * temporarily. This can happen when a dude
3316132451Sroberto			 * first comes up, but has not synchronized the
3317132451Sroberto			 * clock and had its certificate signed by its
3318132451Sroberto			 * server. In case of broken certificate trail,
3319132451Sroberto			 * this might result in a loop that could
3320132451Sroberto			 * persist until timeout.
3321132451Sroberto			 */
3322132451Sroberto			if (!(xp->flags & CERT_TRUST))
3323132451Sroberto				continue;
3324132451Sroberto
3325132451Sroberto			yp->flags |= CERT_TRUST;
3326132451Sroberto
3327132451Sroberto			/*
3328132451Sroberto			 * If subject Y matches the server subject name,
3329132451Sroberto			 * then Y has completed the certificate trail.
3330132451Sroberto			 * Save the group key and light the valid bit.
3331132451Sroberto			 */
3332132451Sroberto			if (strcmp(yp->subject, peer->subject) != 0)
3333132451Sroberto				continue;
3334132451Sroberto
3335132451Sroberto			if (yp->grpkey != NULL) {
3336132451Sroberto				if (peer->grpkey != NULL)
3337132451Sroberto					BN_free(peer->grpkey);
3338132451Sroberto				peer->grpkey = BN_bin2bn(yp->grpkey,
3339132451Sroberto				     yp->grplen, NULL);
3340132451Sroberto			}
3341132451Sroberto			peer->crypto |= CRYPTO_FLAG_VALID;
3342132451Sroberto
3343132451Sroberto			/*
3344132451Sroberto			 * If the server has an an identity scheme,
3345132451Sroberto			 * fetch the identity credentials. If not, the
3346132451Sroberto			 * identity is verified only by the trusted
3347132451Sroberto			 * certificate. The next signature will set the
3348132451Sroberto			 * server proventic.
3349132451Sroberto			 */
3350132451Sroberto			if (peer->crypto & (CRYPTO_FLAG_GQ |
3351132451Sroberto			    CRYPTO_FLAG_IFF | CRYPTO_FLAG_MV))
3352132451Sroberto				continue;
3353132451Sroberto
3354132451Sroberto			peer->crypto |= CRYPTO_FLAG_VRFY;
3355132451Sroberto		}
3356132451Sroberto	}
3357132451Sroberto
3358132451Sroberto	/*
3359132451Sroberto	 * That was awesome. Now update the timestamps and signatures.
3360132451Sroberto	 */
3361132451Sroberto	crypto_update();
3362132451Sroberto	return (rval);
3363132451Sroberto}
3364132451Sroberto
3365132451Sroberto
3366132451Sroberto/*
3367132451Sroberto * cert_free - free certificate information structure
3368132451Sroberto */
3369132451Srobertovoid
3370132451Srobertocert_free(
3371132451Sroberto	struct cert_info *cinf	/* certificate info/value structure */
3372132451Sroberto	)
3373132451Sroberto{
3374132451Sroberto	if (cinf->pkey != NULL)
3375132451Sroberto		EVP_PKEY_free(cinf->pkey);
3376132451Sroberto	if (cinf->subject != NULL)
3377132451Sroberto		free(cinf->subject);
3378132451Sroberto	if (cinf->issuer != NULL)
3379132451Sroberto		free(cinf->issuer);
3380132451Sroberto	if (cinf->grpkey != NULL)
3381132451Sroberto		free(cinf->grpkey);
3382132451Sroberto	value_free(&cinf->cert);
3383132451Sroberto	free(cinf);
3384132451Sroberto}
3385132451Sroberto
3386132451Sroberto
3387132451Sroberto/*
3388132451Sroberto ***********************************************************************
3389132451Sroberto *								       *
3390132451Sroberto * The following routines are used only at initialization time         *
3391132451Sroberto *								       *
3392132451Sroberto ***********************************************************************
3393132451Sroberto */
3394132451Sroberto/*
3395132451Sroberto * crypto_key - load cryptographic parameters and keys from files
3396132451Sroberto *
3397132451Sroberto * This routine loads a PEM-encoded public/private key pair and extracts
3398132451Sroberto * the filestamp from the file name.
3399132451Sroberto *
3400132451Sroberto * Returns public key pointer if valid, NULL if not. Side effect updates
3401132451Sroberto * the filestamp if valid.
3402132451Sroberto */
3403132451Srobertostatic EVP_PKEY *
3404132451Srobertocrypto_key(
3405132451Sroberto	char	*cp,		/* file name */
3406132451Sroberto	tstamp_t *fstamp	/* filestamp */
3407132451Sroberto	)
3408132451Sroberto{
3409132451Sroberto	FILE	*str;		/* file handle */
3410132451Sroberto	EVP_PKEY *pkey = NULL;	/* public/private key */
3411132451Sroberto	char	filename[MAXFILENAME]; /* name of key file */
3412132451Sroberto	char	linkname[MAXFILENAME]; /* filestamp buffer) */
3413132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3414132451Sroberto	char	*ptr;
3415132451Sroberto
3416132451Sroberto	/*
3417132451Sroberto	 * Open the key file. If the first character of the file name is
3418132451Sroberto	 * not '/', prepend the keys directory string. If something goes
3419132451Sroberto	 * wrong, abandon ship.
3420132451Sroberto	 */
342182498Sroberto	if (*cp == '/')
342282498Sroberto		strcpy(filename, cp);
342382498Sroberto	else
342482498Sroberto		snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
342582498Sroberto	str = fopen(filename, "r");
3426132451Sroberto	if (str == NULL)
3427132451Sroberto		return (NULL);
3428132451Sroberto
3429132451Sroberto	/*
3430132451Sroberto	 * Read the filestamp, which is contained in the first line.
3431132451Sroberto	 */
3432132451Sroberto	if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
3433132451Sroberto		msyslog(LOG_ERR, "crypto_key: no data %s\n",
3434132451Sroberto		    filename);
3435132451Sroberto		return (NULL);
343682498Sroberto	}
3437132451Sroberto	if ((ptr = strrchr(ptr, '.')) == NULL) {
3438132451Sroberto		msyslog(LOG_ERR, "crypto_key: no filestamp %s\n",
3439132451Sroberto		    filename);
3440132451Sroberto		return (NULL);
3441132451Sroberto	}
3442132451Sroberto	if (sscanf(++ptr, "%u", fstamp) != 1) {
3443132451Sroberto		msyslog(LOG_ERR, "crypto_key: invalid timestamp %s\n",
3444132451Sroberto		    filename);
3445132451Sroberto		return (NULL);
3446132451Sroberto	}
344782498Sroberto
344882498Sroberto	/*
3449132451Sroberto	 * Read and decrypt PEM-encoded private key.
345082498Sroberto	 */
3451132451Sroberto	pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd);
3452132451Sroberto	fclose(str);
3453132451Sroberto	if (pkey == NULL) {
3454132451Sroberto		msyslog(LOG_ERR, "crypto_key %s\n",
3455132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3456132451Sroberto		return (NULL);
345782498Sroberto	}
345882498Sroberto
345982498Sroberto	/*
3460132451Sroberto	 * Leave tracks in the cryptostats.
346182498Sroberto	 */
3462132451Sroberto	if ((ptr = strrchr(linkname, '\n')) != NULL)
3463132451Sroberto		*ptr = '\0';
3464132451Sroberto	sprintf(statstr, "%s mod %d", &linkname[2],
3465132451Sroberto	    EVP_PKEY_size(pkey) * 8);
3466132451Sroberto	record_crypto_stats(NULL, statstr);
3467132451Sroberto#ifdef DEBUG
3468132451Sroberto	if (debug)
3469132451Sroberto		printf("crypto_key: %s\n", statstr);
3470132451Sroberto	if (debug > 1) {
3471132451Sroberto		if (EVP_MD_type(pkey) == EVP_PKEY_DSA)
3472132451Sroberto			DSA_print_fp(stdout, pkey->pkey.dsa, 0);
3473132451Sroberto		else
3474132451Sroberto			RSA_print_fp(stdout, pkey->pkey.rsa, 0);
347582498Sroberto	}
3476132451Sroberto#endif
3477132451Sroberto	return (pkey);
3478132451Sroberto}
347982498Sroberto
3480132451Sroberto
3481132451Sroberto/*
3482132451Sroberto * crypto_cert - load certificate from file
3483132451Sroberto *
3484132451Sroberto * This routine loads a X.509 RSA or DSA certificate from a file and
3485132451Sroberto * constructs a info/cert value structure for this machine. The
3486132451Sroberto * structure includes a filestamp extracted from the file name. Later
3487132451Sroberto * the certificate can be sent to another machine by request.
3488132451Sroberto *
3489132451Sroberto * Returns certificate info/value pointer if valid, NULL if not.
3490132451Sroberto */
3491132451Srobertostatic struct cert_info *	/* certificate information */
3492132451Srobertocrypto_cert(
3493132451Sroberto	char	*cp		/* file name */
3494132451Sroberto	)
3495132451Sroberto{
3496132451Sroberto	struct cert_info *ret; /* certificate information */
3497132451Sroberto	FILE	*str;		/* file handle */
3498132451Sroberto	char	filename[MAXFILENAME]; /* name of certificate file */
3499132451Sroberto	char	linkname[MAXFILENAME]; /* filestamp buffer */
3500132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3501132451Sroberto	tstamp_t fstamp;	/* filestamp */
3502132451Sroberto	long	len;
3503132451Sroberto	char	*ptr;
3504132451Sroberto	char	*name, *header;
3505132451Sroberto	u_char	*data;
3506132451Sroberto
350782498Sroberto	/*
3508132451Sroberto	 * Open the certificate file. If the first character of the file
3509132451Sroberto	 * name is not '/', prepend the keys directory string. If
3510132451Sroberto	 * something goes wrong, abandon ship.
351182498Sroberto	 */
3512132451Sroberto	if (*cp == '/')
3513132451Sroberto		strcpy(filename, cp);
3514132451Sroberto	else
3515132451Sroberto		snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
3516132451Sroberto	str = fopen(filename, "r");
3517132451Sroberto	if (str == NULL)
3518132451Sroberto		return (NULL);
351982498Sroberto
3520132451Sroberto	/*
3521132451Sroberto	 * Read the filestamp, which is contained in the first line.
3522132451Sroberto	 */
3523132451Sroberto	if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
3524132451Sroberto		msyslog(LOG_ERR, "crypto_cert: no data %s\n",
3525132451Sroberto		    filename);
3526132451Sroberto		return (NULL);
3527132451Sroberto	}
3528132451Sroberto	if ((ptr = strrchr(ptr, '.')) == NULL) {
3529132451Sroberto		msyslog(LOG_ERR, "crypto_cert: no filestamp %s\n",
3530132451Sroberto		    filename);
3531132451Sroberto		return (NULL);
3532132451Sroberto	}
3533132451Sroberto	if (sscanf(++ptr, "%u", &fstamp) != 1) {
3534132451Sroberto		msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s\n",
3535132451Sroberto		    filename);
3536132451Sroberto		return (NULL);
3537132451Sroberto	}
353882498Sroberto
353982498Sroberto	/*
3540132451Sroberto	 * Read PEM-encoded certificate and install.
354182498Sroberto	 */
3542132451Sroberto	if (!PEM_read(str, &name, &header, &data, &len)) {
3543132451Sroberto		msyslog(LOG_ERR, "crypto_cert %s\n",
3544132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3545132451Sroberto		return (NULL);
3546132451Sroberto	}
3547132451Sroberto	free(header);
3548132451Sroberto	if (strcmp(name, "CERTIFICATE") !=0) {
3549132451Sroberto		msyslog(LOG_INFO, "crypto_cert: wrong PEM type %s",
3550132451Sroberto		    name);
3551132451Sroberto		free(name);
3552132451Sroberto		free(data);
3553132451Sroberto		return (NULL);
3554132451Sroberto	}
3555132451Sroberto	free(name);
355682498Sroberto
355782498Sroberto	/*
3558132451Sroberto	 * Parse certificate and generate info/value structure.
355982498Sroberto	 */
3560132451Sroberto	ret = cert_parse(data, len, fstamp);
3561132451Sroberto	free(data);
3562132451Sroberto	if (ret == NULL)
3563132451Sroberto		return (NULL);
3564132451Sroberto	if ((ptr = strrchr(linkname, '\n')) != NULL)
3565132451Sroberto		*ptr = '\0';
3566132451Sroberto	sprintf(statstr, "%s 0x%x len %lu", &linkname[2], ret->flags,
3567132451Sroberto	    len);
3568132451Sroberto	record_crypto_stats(NULL, statstr);
356982498Sroberto#ifdef DEBUG
357082498Sroberto	if (debug)
3571132451Sroberto		printf("crypto_cert: %s\n", statstr);
357282498Sroberto#endif
3573132451Sroberto	return (ret);
357482498Sroberto}
357582498Sroberto
357682498Sroberto
357782498Sroberto/*
3578132451Sroberto * crypto_tai - load leapseconds table from file
3579132451Sroberto *
3580132451Sroberto * This routine loads the ERTS leapsecond file in NIST text format,
3581132451Sroberto * converts to a value structure and extracts a filestamp from the file
3582132451Sroberto * name. The data are used to establish the TAI offset from UTC, which
3583132451Sroberto * is provided to the kernel if supported. Later the data can be sent to
3584132451Sroberto * another machine on request.
358582498Sroberto */
358682498Srobertostatic void
358782498Srobertocrypto_tai(
3588132451Sroberto	char	*cp		/* file name */
358982498Sroberto	)
359082498Sroberto{
3591132451Sroberto	FILE	*str;		/* file handle */
3592132451Sroberto	char	buf[NTP_MAXSTRLEN];	/* file line buffer */
3593132451Sroberto	u_int	leapsec[MAX_LEAP]; /* NTP time at leaps */
3594132451Sroberto	u_int	offset;		/* offset at leap (s) */
3595132451Sroberto	char	filename[MAXFILENAME]; /* name of leapseconds file */
3596132451Sroberto	char	linkname[MAXFILENAME]; /* file link (for filestamp) */
3597132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3598132451Sroberto	tstamp_t fstamp;	/* filestamp */
3599132451Sroberto	u_int	len;
3600132451Sroberto	char	*ptr;
3601132451Sroberto	int	rval, i;
360282498Sroberto#ifdef KERNEL_PLL
360382498Sroberto#if NTP_API > 3
360482498Sroberto	struct timex ntv;	/* kernel interface structure */
360582498Sroberto#endif /* NTP_API */
360682498Sroberto#endif /* KERNEL_PLL */
360782498Sroberto
360882498Sroberto	/*
360982498Sroberto	 * Open the file and discard comment lines. If the first
361082498Sroberto	 * character of the file name is not '/', prepend the keys
361182498Sroberto	 * directory string. If the file is not found, not to worry; it
361282498Sroberto	 * can be retrieved over the net. But, if it is found with
361382498Sroberto	 * errors, we crash and burn.
361482498Sroberto	 */
361582498Sroberto	if (*cp == '/')
361682498Sroberto		strcpy(filename, cp);
361782498Sroberto	else
361882498Sroberto		snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
3619132451Sroberto	if ((str = fopen(filename, "r")) == NULL)
362082498Sroberto		return;
3621132451Sroberto
3622132451Sroberto	/*
3623132451Sroberto	 * Extract filestamp if present.
3624132451Sroberto	 */
3625132451Sroberto	rval = readlink(filename, linkname, MAXFILENAME - 1);
3626132451Sroberto	if (rval > 0) {
3627132451Sroberto		linkname[rval] = '\0';
3628132451Sroberto		ptr = strrchr(linkname, '.');
3629132451Sroberto	} else {
3630132451Sroberto		ptr = strrchr(filename, '.');
363182498Sroberto	}
3632132451Sroberto	if (ptr != NULL)
3633132451Sroberto		sscanf(++ptr, "%u", &fstamp);
3634132451Sroberto	else
3635132451Sroberto		fstamp = 0;
3636132451Sroberto	tai_leap.fstamp = htonl(fstamp);
363782498Sroberto
363882498Sroberto	/*
363982498Sroberto	 * We are rather paranoid here, since an intruder might cause a
364082498Sroberto	 * coredump by infiltrating naughty values. Empty lines and
364182498Sroberto	 * comments are ignored. Other lines must begin with two
364282498Sroberto	 * integers followed by junk or comments. The first integer is
364382498Sroberto	 * the NTP seconds of leap insertion, the second is the offset
364482498Sroberto	 * of TAI relative to UTC after that insertion. The second word
364582498Sroberto	 * must equal the initial insertion of ten seconds on 1 January
364682498Sroberto	 * 1972 plus one second for each succeeding insertion.
364782498Sroberto	 */
364882498Sroberto	i = 0;
364982498Sroberto	while (i < MAX_LEAP) {
3650132451Sroberto		ptr = fgets(buf, NTP_MAXSTRLEN - 1, str);
3651132451Sroberto		if (ptr == NULL)
365282498Sroberto			break;
365382498Sroberto		if (strlen(buf) < 1)
365482498Sroberto			continue;
365582498Sroberto		if (*buf == '#')
365682498Sroberto			continue;
365782498Sroberto		if (sscanf(buf, "%u %u", &leapsec[i], &offset) != 2)
365882498Sroberto			continue;
3659132451Sroberto		if (i != (int)(offset - TAI_1972)) {
366082498Sroberto			break;
366182498Sroberto		}
366282498Sroberto		i++;
366382498Sroberto	}
366482498Sroberto	fclose(str);
3665132451Sroberto	if (ptr != NULL) {
3666132451Sroberto		msyslog(LOG_INFO,
3667132451Sroberto		    "crypto_tai: leapseconds file %s error %d", cp,
366882498Sroberto		    rval);
366982498Sroberto		exit (-1);
367082498Sroberto	}
367182498Sroberto
367282498Sroberto	/*
367382498Sroberto	 * The extension field table entries consists of the NTP seconds
367482498Sroberto	 * of leap insertion in reverse order, so that the most recent
367582498Sroberto	 * insertion is the first entry in the table.
367682498Sroberto	 */
367782498Sroberto	len = i * 4;
367882498Sroberto	tai_leap.vallen = htonl(len);
3679132451Sroberto	ptr = emalloc(len);
3680132451Sroberto	tai_leap.ptr = (unsigned char *) ptr;
368182498Sroberto	for (; i >= 0; i--) {
3682132451Sroberto		*ptr++ = (char) htonl(leapsec[i]);
368382498Sroberto	}
368482498Sroberto	crypto_flags |= CRYPTO_FLAG_TAI;
368582498Sroberto	sys_tai = len / 4 + TAI_1972 - 1;
368682498Sroberto#ifdef KERNEL_PLL
368782498Sroberto#if NTP_API > 3
368882498Sroberto	ntv.modes = MOD_TAI;
368982498Sroberto	ntv.constant = sys_tai;
369082498Sroberto	if (ntp_adjtime(&ntv) == TIME_ERROR)
3691132451Sroberto		msyslog(LOG_INFO,
3692132451Sroberto		    "crypto_tai: kernel TAI update failed");
369382498Sroberto#endif /* NTP_API */
369482498Sroberto#endif /* KERNEL_PLL */
3695132451Sroberto	sprintf(statstr, "%s link %d fs %u offset %u", cp, rval, fstamp,
3696132451Sroberto	    ntohl(tai_leap.vallen) / 4 + TAI_1972 - 1);
3697132451Sroberto	record_crypto_stats(NULL, statstr);
3698132451Sroberto#ifdef DEBUG
3699132451Sroberto	if (debug)
3700132451Sroberto		printf("crypto_tai: %s\n", statstr);
3701132451Sroberto#endif
3702132451Sroberto}
370382498Sroberto
370482498Sroberto
3705132451Sroberto/*
3706132451Sroberto * crypto_setup - load keys, certificate and leapseconds table
3707132451Sroberto *
3708132451Sroberto * This routine loads the public/private host key and certificate. If
3709132451Sroberto * available, it loads the public/private sign key, which defaults to
3710132451Sroberto * the host key, and leapseconds table. The host key must be RSA, but
3711132451Sroberto * the sign key can be either RSA or DSA. In either case, the public key
3712132451Sroberto * on the certificate must agree with the sign key.
3713132451Sroberto */
3714132451Srobertovoid
3715132451Srobertocrypto_setup(void)
3716132451Sroberto{
3717132451Sroberto	EVP_PKEY *pkey;		/* private/public key pair */
3718132451Sroberto	char	filename[MAXFILENAME]; /* file name buffer */
3719132451Sroberto	l_fp	seed;		/* crypto PRNG seed as NTP timestamp */
3720132451Sroberto	tstamp_t fstamp;	/* filestamp */
3721132451Sroberto	tstamp_t sstamp;	/* sign filestamp */
3722132451Sroberto	u_int	len, bytes;
3723132451Sroberto	u_char	*ptr;
3724132451Sroberto
372582498Sroberto	/*
3726132451Sroberto	 * Initialize structures.
372782498Sroberto	 */
3728132451Sroberto	if (!crypto_flags)
3729132451Sroberto		return;
3730132451Sroberto	gethostname(filename, MAXFILENAME);
3731132451Sroberto	bytes = strlen(filename) + 1;
3732132451Sroberto	sys_hostname = emalloc(bytes);
3733132451Sroberto	memcpy(sys_hostname, filename, bytes);
3734132451Sroberto	if (passwd == NULL)
3735132451Sroberto		passwd = sys_hostname;
3736132451Sroberto	memset(&hostval, 0, sizeof(hostval));
3737132451Sroberto	memset(&pubkey, 0, sizeof(pubkey));
3738132451Sroberto	memset(&tai_leap, 0, sizeof(tai_leap));
3739132451Sroberto
3740132451Sroberto	/*
3741132451Sroberto	 * Load required random seed file and seed the random number
3742132451Sroberto	 * generator. Be default, it is found in the user home
3743132451Sroberto	 * directory. The root home directory may be / or /root,
3744132451Sroberto	 * depending on the system. Wiggle the contents a bit and write
3745132451Sroberto	 * it back so the sequence does not repeat when we next restart.
3746132451Sroberto	 */
3747132451Sroberto	ERR_load_crypto_strings();
3748132451Sroberto	if (rand_file == NULL) {
3749132451Sroberto		if ((RAND_file_name(filename, MAXFILENAME)) != NULL) {
3750132451Sroberto			rand_file = emalloc(strlen(filename) + 1);
3751132451Sroberto			strcpy(rand_file, filename);
3752132451Sroberto		}
3753132451Sroberto	} else if (*rand_file != '/') {
3754132451Sroberto		snprintf(filename, MAXFILENAME, "%s/%s", keysdir,
3755132451Sroberto		    rand_file);
3756132451Sroberto		free(rand_file);
3757132451Sroberto		rand_file = emalloc(strlen(filename) + 1);
3758132451Sroberto		strcpy(rand_file, filename);
375982498Sroberto	}
3760132451Sroberto	if (rand_file == NULL) {
3761132451Sroberto		msyslog(LOG_ERR,
3762132451Sroberto		    "crypto_setup: random seed file not specified");
3763132451Sroberto		exit (-1);
3764132451Sroberto	}
3765132451Sroberto	if ((bytes = RAND_load_file(rand_file, -1)) == 0) {
3766132451Sroberto		msyslog(LOG_ERR,
3767132451Sroberto		    "crypto_setup: random seed file %s not found\n",
3768132451Sroberto		    rand_file);
3769132451Sroberto		exit (-1);
3770132451Sroberto	}
3771132451Sroberto	get_systime(&seed);
3772132451Sroberto	RAND_seed(&seed, sizeof(l_fp));
3773132451Sroberto	RAND_write_file(rand_file);
3774132451Sroberto	OpenSSL_add_all_algorithms();
377582498Sroberto#ifdef DEBUG
377682498Sroberto	if (debug)
377782498Sroberto		printf(
3778132451Sroberto		    "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
3779132451Sroberto		    SSLeay(), rand_file, bytes);
378082498Sroberto#endif
3781132451Sroberto
3782132451Sroberto	/*
3783132451Sroberto	 * Load required host key from file "ntpkey_host_<hostname>". It
3784132451Sroberto	 * also becomes the default sign key.
3785132451Sroberto	 */
3786132451Sroberto	if (host_file == NULL) {
3787132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_host_%s",
3788132451Sroberto		    sys_hostname);
3789132451Sroberto		host_file = emalloc(strlen(filename) + 1);
3790132451Sroberto		strcpy(host_file, filename);
3791132451Sroberto	}
3792132451Sroberto	pkey = crypto_key(host_file, &fstamp);
3793132451Sroberto	if (pkey == NULL) {
3794132451Sroberto		msyslog(LOG_ERR,
3795132451Sroberto		    "crypto_setup: host key file %s not found or corrupt",
3796132451Sroberto		    host_file);
3797132451Sroberto		exit (-1);
3798132451Sroberto	}
3799132451Sroberto	host_pkey = pkey;
3800132451Sroberto	sign_pkey = pkey;
3801132451Sroberto	sstamp = fstamp;
3802132451Sroberto	hostval.fstamp = htonl(fstamp);
3803132451Sroberto	if (EVP_MD_type(host_pkey) != EVP_PKEY_RSA) {
3804132451Sroberto		msyslog(LOG_ERR,
3805132451Sroberto		    "crypto_setup: host key is not RSA key type");
3806132451Sroberto		exit (-1);
3807132451Sroberto	}
3808132451Sroberto	hostval.vallen = htonl(strlen(sys_hostname));
3809132451Sroberto	hostval.ptr = (unsigned char *) sys_hostname;
3810132451Sroberto
3811132451Sroberto	/*
3812132451Sroberto	 * Construct public key extension field for agreement scheme.
3813132451Sroberto	 */
3814132451Sroberto	len = i2d_PublicKey(host_pkey, NULL);
3815132451Sroberto	ptr = emalloc(len);
3816132451Sroberto	pubkey.ptr = ptr;
3817132451Sroberto	i2d_PublicKey(host_pkey, &ptr);
3818132451Sroberto	pubkey.vallen = htonl(len);
3819132451Sroberto	pubkey.fstamp = hostval.fstamp;
3820132451Sroberto
3821132451Sroberto	/*
3822132451Sroberto	 * Load optional sign key from file "ntpkey_sign_<hostname>". If
3823132451Sroberto	 * loaded, it becomes the sign key.
3824132451Sroberto	 */
3825132451Sroberto	if (sign_file == NULL) {
3826132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_sign_%s",
3827132451Sroberto		    sys_hostname);
3828132451Sroberto		sign_file = emalloc(strlen(filename) + 1);
3829132451Sroberto		strcpy(sign_file, filename);
3830132451Sroberto	}
3831132451Sroberto	pkey = crypto_key(sign_file, &fstamp);
3832132451Sroberto	if (pkey != NULL) {
3833132451Sroberto		sign_pkey = pkey;
3834132451Sroberto		sstamp = fstamp;
3835132451Sroberto	}
3836132451Sroberto	sign_siglen = EVP_PKEY_size(sign_pkey);
3837132451Sroberto
3838132451Sroberto	/*
3839132451Sroberto	 * Load optional IFF parameters from file
3840132451Sroberto	 * "ntpkey_iff_<hostname>".
3841132451Sroberto	 */
3842132451Sroberto	if (iffpar_file == NULL) {
3843132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
3844132451Sroberto		    sys_hostname);
3845132451Sroberto		iffpar_file = emalloc(strlen(filename) + 1);
3846132451Sroberto		strcpy(iffpar_file, filename);
3847132451Sroberto	}
3848132451Sroberto	iffpar_pkey = crypto_key(iffpar_file, &if_fstamp);
3849132451Sroberto	if (iffpar_pkey != NULL)
3850132451Sroberto		crypto_flags |= CRYPTO_FLAG_IFF;
3851132451Sroberto
3852132451Sroberto	/*
3853132451Sroberto	 * Load optional GQ parameters from file "ntpkey_gq_<hostname>".
3854132451Sroberto	 */
3855132451Sroberto	if (gqpar_file == NULL) {
3856132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
3857132451Sroberto		    sys_hostname);
3858132451Sroberto		gqpar_file = emalloc(strlen(filename) + 1);
3859132451Sroberto		strcpy(gqpar_file, filename);
3860132451Sroberto	}
3861132451Sroberto	gqpar_pkey = crypto_key(gqpar_file, &gq_fstamp);
3862132451Sroberto	if (gqpar_pkey != NULL)
3863132451Sroberto		crypto_flags |= CRYPTO_FLAG_GQ;
3864132451Sroberto
3865132451Sroberto	/*
3866132451Sroberto	 * Load optional MV parameters from file "ntpkey_mv_<hostname>".
3867132451Sroberto	 */
3868132451Sroberto	if (mvpar_file == NULL) {
3869132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
3870132451Sroberto		    sys_hostname);
3871132451Sroberto		mvpar_file = emalloc(strlen(filename) + 1);
3872132451Sroberto		strcpy(mvpar_file, filename);
3873132451Sroberto	}
3874132451Sroberto	mvpar_pkey = crypto_key(mvpar_file, &mv_fstamp);
3875132451Sroberto	if (mvpar_pkey != NULL)
3876132451Sroberto		crypto_flags |= CRYPTO_FLAG_MV;
3877132451Sroberto
3878132451Sroberto	/*
3879132451Sroberto	 * Load required certificate from file "ntpkey_cert_<hostname>".
3880132451Sroberto	 */
3881132451Sroberto	if (cert_file == NULL) {
3882132451Sroberto		snprintf(filename, MAXFILENAME, "ntpkey_cert_%s",
3883132451Sroberto		    sys_hostname);
3884132451Sroberto		cert_file = emalloc(strlen(filename) + 1);
3885132451Sroberto		strcpy(cert_file, filename);
3886132451Sroberto	}
3887132451Sroberto	if ((cinfo = crypto_cert(cert_file)) == NULL) {
3888132451Sroberto		msyslog(LOG_ERR,
3889132451Sroberto		    "certificate file %s not found or corrupt",
3890132451Sroberto		    cert_file);
3891132451Sroberto		exit (-1);
3892132451Sroberto	}
3893132451Sroberto
3894132451Sroberto	/*
3895132451Sroberto	 * The subject name must be the same as the host name, unless
3896132451Sroberto	 * the certificate is private, in which case it may have come
3897132451Sroberto	 * from another host.
3898132451Sroberto	 */
3899132451Sroberto	if (!(cinfo->flags & CERT_PRIV) && strcmp(cinfo->subject,
3900132451Sroberto	    sys_hostname) != 0) {
3901132451Sroberto		msyslog(LOG_ERR,
3902132451Sroberto		    "crypto_setup: certificate %s not for this host",
3903132451Sroberto		    cert_file);
3904132451Sroberto		cert_free(cinfo);
3905132451Sroberto		exit (-1);
3906132451Sroberto	}
3907132451Sroberto
3908132451Sroberto	/*
3909132451Sroberto	 * It the certificate is trusted, the subject must be the same
3910132451Sroberto	 * as the issuer, in other words it must be self signed.
3911132451Sroberto	 */
3912132451Sroberto	if (cinfo->flags & CERT_PRIV && strcmp(cinfo->subject,
3913132451Sroberto	    cinfo->issuer) != 0) {
3914132451Sroberto		if (cert_valid(cinfo, sign_pkey) != XEVNT_OK) {
3915132451Sroberto			msyslog(LOG_ERR,
3916132451Sroberto			    "crypto_setup: certificate %s is trusted, but not self signed.",
3917132451Sroberto			    cert_file);
3918132451Sroberto			cert_free(cinfo);
3919132451Sroberto			exit (-1);
3920132451Sroberto		}
3921132451Sroberto	}
3922132451Sroberto	sign_digest = cinfo->digest;
3923132451Sroberto	if (cinfo->flags & CERT_PRIV)
3924132451Sroberto		crypto_flags |= CRYPTO_FLAG_PRIV;
3925132451Sroberto	crypto_flags |= cinfo->nid << 16;
3926132451Sroberto
3927132451Sroberto	/*
3928132451Sroberto	 * Load optional leapseconds table from file "ntpkey_leap". If
3929132451Sroberto	 * the file is missing or defective, the values can later be
3930132451Sroberto	 * retrieved from a server.
3931132451Sroberto	 */
3932132451Sroberto	if (leap_file == NULL)
3933132451Sroberto		leap_file = "ntpkey_leap";
3934132451Sroberto	crypto_tai(leap_file);
3935132451Sroberto#ifdef DEBUG
3936132451Sroberto	if (debug)
3937132451Sroberto		printf(
3938132451Sroberto		    "crypto_setup: flags 0x%x host %s signature %s\n",
3939132451Sroberto		    crypto_flags, sys_hostname, OBJ_nid2ln(cinfo->nid));
3940132451Sroberto#endif
394182498Sroberto}
394282498Sroberto
394382498Sroberto
394482498Sroberto/*
3945132451Sroberto * crypto_config - configure data from crypto configuration command.
394682498Sroberto */
394782498Srobertovoid
394882498Srobertocrypto_config(
3949132451Sroberto	int	item,		/* configuration item */
3950132451Sroberto	char	*cp		/* file name */
395182498Sroberto	)
395282498Sroberto{
395382498Sroberto	switch (item) {
395482498Sroberto
395582498Sroberto	/*
3956132451Sroberto	 * Set random seed file name.
395782498Sroberto	 */
3958132451Sroberto	case CRYPTO_CONF_RAND:
3959132451Sroberto		rand_file = emalloc(strlen(cp) + 1);
3960132451Sroberto		strcpy(rand_file, cp);
396182498Sroberto		break;
396282498Sroberto
396382498Sroberto	/*
3964132451Sroberto	 * Set private key password.
396582498Sroberto	 */
3966132451Sroberto	case CRYPTO_CONF_PW:
3967132451Sroberto		passwd = emalloc(strlen(cp) + 1);
3968132451Sroberto		strcpy(passwd, cp);
3969132451Sroberto		break;
3970132451Sroberto
3971132451Sroberto	/*
3972132451Sroberto	 * Set host file name.
3973132451Sroberto	 */
397482498Sroberto	case CRYPTO_CONF_PRIV:
3975132451Sroberto		host_file = emalloc(strlen(cp) + 1);
3976132451Sroberto		strcpy(host_file, cp);
397782498Sroberto		break;
397882498Sroberto
397982498Sroberto	/*
3980132451Sroberto	 * Set sign key file name.
398182498Sroberto	 */
3982132451Sroberto	case CRYPTO_CONF_SIGN:
3983132451Sroberto		sign_file = emalloc(strlen(cp) + 1);
3984132451Sroberto		strcpy(sign_file, cp);
398582498Sroberto		break;
398682498Sroberto
398782498Sroberto	/*
3988132451Sroberto	 * Set iff parameters file name.
398982498Sroberto	 */
3990132451Sroberto	case CRYPTO_CONF_IFFPAR:
3991132451Sroberto		iffpar_file = emalloc(strlen(cp) + 1);
3992132451Sroberto		strcpy(iffpar_file, cp);
399382498Sroberto		break;
399482498Sroberto
399582498Sroberto	/*
3996132451Sroberto	 * Set gq parameters file name.
399782498Sroberto	 */
3998132451Sroberto	case CRYPTO_CONF_GQPAR:
3999132451Sroberto		gqpar_file = emalloc(strlen(cp) + 1);
4000132451Sroberto		strcpy(gqpar_file, cp);
400182498Sroberto		break;
400282498Sroberto
400382498Sroberto	/*
4004132451Sroberto	 * Set mv parameters file name.
400582498Sroberto	 */
4006132451Sroberto	case CRYPTO_CONF_MVPAR:
4007132451Sroberto		mvpar_file = emalloc(strlen(cp) + 1);
4008132451Sroberto		strcpy(mvpar_file, cp);
400982498Sroberto		break;
401082498Sroberto
401182498Sroberto	/*
4012132451Sroberto	 * Set certificate file name.
401382498Sroberto	 */
4014132451Sroberto	case CRYPTO_CONF_CERT:
4015132451Sroberto		cert_file = emalloc(strlen(cp) + 1);
4016132451Sroberto		strcpy(cert_file, cp);
401782498Sroberto		break;
4018132451Sroberto
4019132451Sroberto	/*
4020132451Sroberto	 * Set leapseconds file name.
4021132451Sroberto	 */
4022132451Sroberto	case CRYPTO_CONF_LEAP:
4023132451Sroberto		leap_file = emalloc(strlen(cp) + 1);
4024132451Sroberto		strcpy(leap_file, cp);
4025132451Sroberto		break;
402682498Sroberto	}
402782498Sroberto	crypto_flags |= CRYPTO_FLAG_ENAB;
402882498Sroberto}
402982498Sroberto# else
403082498Srobertoint ntp_crypto_bs_pubkey;
4031132451Sroberto# endif /* OPENSSL */
4032