182498Sroberto/*
282498Sroberto * ntp_crypto.c - NTP version 4 public key routines
382498Sroberto */
482498Sroberto#ifdef HAVE_CONFIG_H
582498Sroberto#include <config.h>
682498Sroberto#endif
782498Sroberto
8285612Sdelphij#ifdef AUTOKEY
982498Sroberto#include <stdio.h>
10285612Sdelphij#include <stdlib.h>	/* strtoul */
1182498Sroberto#include <sys/types.h>
12132451Sroberto#include <sys/param.h>
1382498Sroberto#include <unistd.h>
1482498Sroberto#include <fcntl.h>
1582498Sroberto
1682498Sroberto#include "ntpd.h"
1782498Sroberto#include "ntp_stdlib.h"
18132451Sroberto#include "ntp_unixtime.h"
1982498Sroberto#include "ntp_string.h"
20285612Sdelphij#include "ntp_random.h"
21285612Sdelphij#include "ntp_assert.h"
22285612Sdelphij#include "ntp_calendar.h"
23285612Sdelphij#include "ntp_leapsec.h"
2482498Sroberto
25316069Sdelphij#include "openssl/asn1.h"
26132451Sroberto#include "openssl/bn.h"
27316069Sdelphij#include "openssl/crypto.h"
28132451Sroberto#include "openssl/err.h"
29132451Sroberto#include "openssl/evp.h"
30316069Sdelphij#include "openssl/opensslv.h"
31132451Sroberto#include "openssl/pem.h"
32132451Sroberto#include "openssl/rand.h"
33316069Sdelphij#include "openssl/x509.h"
34132451Sroberto#include "openssl/x509v3.h"
35309008Sdelphij#include "libssl_compat.h"
36132451Sroberto
3782498Sroberto#ifdef KERNEL_PLL
3882498Sroberto#include "ntp_syscall.h"
3982498Sroberto#endif /* KERNEL_PLL */
4082498Sroberto
4182498Sroberto/*
42285612Sdelphij * calcomp - compare two calendar structures, ignoring yearday and weekday; like strcmp
43285612Sdelphij * No, it's not a plotter.  If you don't understand that, you're too young.
44285612Sdelphij */
45285612Sdelphijstatic int calcomp(struct calendar *pjd1, struct calendar *pjd2)
46285612Sdelphij{
47285612Sdelphij	int32_t diff;	/* large enough to hold the signed difference between two uint16_t values */
48285612Sdelphij
49285612Sdelphij	diff = pjd1->year - pjd2->year;
50285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
51285612Sdelphij	/* same year; compare months */
52285612Sdelphij	diff = pjd1->month - pjd2->month;
53285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
54285612Sdelphij	/* same year and month; compare monthday */
55285612Sdelphij	diff = pjd1->monthday - pjd2->monthday;
56285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
57285612Sdelphij	/* same year and month and monthday; compare time */
58285612Sdelphij	diff = pjd1->hour - pjd2->hour;
59285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
60285612Sdelphij	diff = pjd1->minute - pjd2->minute;
61285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
62285612Sdelphij	diff = pjd1->second - pjd2->second;
63285612Sdelphij	if (diff < 0) return -1; else if (diff > 0) return 1;
64285612Sdelphij	/* identical */
65285612Sdelphij	return 0;
66285612Sdelphij}
67285612Sdelphij
68285612Sdelphij/*
69132451Sroberto * Extension field message format
7082498Sroberto *
71132451Sroberto * These are always signed and saved before sending in network byte
72132451Sroberto * order. They must be converted to and from host byte order for
73132451Sroberto * processing.
7482498Sroberto *
75132451Sroberto * +-------+-------+
76132451Sroberto * |   op  |  len  | <- extension pointer
77132451Sroberto * +-------+-------+
78285612Sdelphij * |    associd    |
79132451Sroberto * +---------------+
80132451Sroberto * |   timestamp   | <- value pointer
81132451Sroberto * +---------------+
82132451Sroberto * |   filestamp   |
83132451Sroberto * +---------------+
84132451Sroberto * |   value len   |
85132451Sroberto * +---------------+
86132451Sroberto * |               |
87132451Sroberto * =     value     =
88132451Sroberto * |               |
89132451Sroberto * +---------------+
90132451Sroberto * | signature len |
91132451Sroberto * +---------------+
92132451Sroberto * |               |
93132451Sroberto * =   signature   =
94132451Sroberto * |               |
95132451Sroberto * +---------------+
9682498Sroberto *
97132451Sroberto * The CRYPTO_RESP bit is set to 0 for requests, 1 for responses.
98132451Sroberto * Requests carry the association ID of the receiver; responses carry
99132451Sroberto * the association ID of the sender. Some messages include only the
100132451Sroberto * operation/length and association ID words and so have length 8
101132451Sroberto * octets. Ohers include the value structure and associated value and
102132451Sroberto * signature fields. These messages include the timestamp, filestamp,
103132451Sroberto * value and signature words and so have length at least 24 octets. The
104132451Sroberto * signature and/or value fields can be empty, in which case the
105132451Sroberto * respective length words are zero. An empty value with nonempty
106132451Sroberto * signature is syntactically valid, but semantically questionable.
107132451Sroberto *
108132451Sroberto * The filestamp represents the time when a cryptographic data file such
109132451Sroberto * as a public/private key pair is created. It follows every reference
110132451Sroberto * depending on that file and serves as a means to obsolete earlier data
111132451Sroberto * of the same type. The timestamp represents the time when the
112132451Sroberto * cryptographic data of the message were last signed. Creation of a
113132451Sroberto * cryptographic data file or signing a message can occur only when the
114132451Sroberto * creator or signor is synchronized to an authoritative source and
115132451Sroberto * proventicated to a trusted authority.
116132451Sroberto *
117285612Sdelphij * Note there are several conditions required for server trust. First,
118285612Sdelphij * the public key on the server certificate must be verified, which can
119285612Sdelphij * involve a hike along the certificate trail to a trusted host. Next,
120285612Sdelphij * the server trust must be confirmed by one of several identity
121285612Sdelphij * schemes. Valid cryptographic values are signed with attached
122285612Sdelphij * timestamp and filestamp. Individual packet trust is confirmed
123285612Sdelphij * relative to these values by a message digest with keys generated by a
124285612Sdelphij * reverse-order pseudorandom hash.
125285612Sdelphij *
126285612Sdelphij * State decomposition. These flags are lit in the order given. They are
127285612Sdelphij * dim only when the association is demobilized.
128285612Sdelphij *
129285612Sdelphij * CRYPTO_FLAG_ENAB	Lit upon acceptance of a CRYPTO_ASSOC message
130285612Sdelphij * CRYPTO_FLAG_CERT	Lit when a self-digned trusted certificate is
131285612Sdelphij *			accepted.
132285612Sdelphij * CRYPTO_FLAG_VRFY	Lit when identity is confirmed.
133285612Sdelphij * CRYPTO_FLAG_PROV	Lit when the first signature is verified.
134285612Sdelphij * CRYPTO_FLAG_COOK	Lit when a valid cookie is accepted.
135285612Sdelphij * CRYPTO_FLAG_AUTO	Lit when valid autokey values are accepted.
136285612Sdelphij * CRYPTO_FLAG_SIGN	Lit when the server signed certificate is
137285612Sdelphij *			accepted.
138285612Sdelphij * CRYPTO_FLAG_LEAP	Lit when the leapsecond values are accepted.
13982498Sroberto */
14082498Sroberto/*
141132451Sroberto * Cryptodefines
14282498Sroberto */
143132451Sroberto#define TAI_1972	10	/* initial TAI offset (s) */
144132451Sroberto#define MAX_LEAP	100	/* max UTC leapseconds (s) */
145132451Sroberto#define VALUE_LEN	(6 * 4) /* min response field length */
146281230Sdelphij#define MAX_VALLEN	(65535 - VALUE_LEN)
147132451Sroberto#define YEAR		(60 * 60 * 24 * 365) /* seconds in year */
14882498Sroberto
14982498Sroberto/*
150132451Sroberto * Global cryptodata in host byte order
15182498Sroberto */
152132451Srobertou_int32	crypto_flags = 0x0;	/* status word */
153285612Sdelphijint	crypto_nid = KEY_TYPE_MD5; /* digest nid */
154285612Sdelphijchar	*sys_hostname = NULL;
155285612Sdelphijchar	*sys_groupname = NULL;
156285612Sdelphijstatic char *host_filename = NULL;	/* host file name */
157285612Sdelphijstatic char *ident_filename = NULL;	/* group file name */
15882498Sroberto
15982498Sroberto/*
160132451Sroberto * Global cryptodata in network byte order
16182498Sroberto */
162285612Sdelphijstruct cert_info *cinfo = NULL;	/* certificate info/value cache */
163285612Sdelphijstruct cert_info *cert_host = NULL; /* host certificate */
164285612Sdelphijstruct pkey_info *pkinfo = NULL; /* key info/value cache */
165132451Srobertostruct value hostval;		/* host value */
166132451Srobertostruct value pubkey;		/* public key */
167285612Sdelphijstruct value tai_leap;		/* leapseconds values */
168285612Sdelphijstruct pkey_info *iffkey_info = NULL; /* IFF keys */
169285612Sdelphijstruct pkey_info *gqkey_info = NULL; /* GQ keys */
170285612Sdelphijstruct pkey_info *mvkey_info = NULL; /* MV keys */
17182498Sroberto
17282498Sroberto/*
173132451Sroberto * Private cryptodata in host byte order
17482498Sroberto */
175132451Srobertostatic char *passwd = NULL;	/* private key password */
176132451Srobertostatic EVP_PKEY *host_pkey = NULL; /* host key */
177132451Srobertostatic EVP_PKEY *sign_pkey = NULL; /* sign key */
178132451Srobertostatic const EVP_MD *sign_digest = NULL; /* sign digest */
179132451Srobertostatic u_int sign_siglen;	/* sign key length */
180132451Srobertostatic char *rand_file = NULL;	/* random seed file */
18182498Sroberto
18282498Sroberto/*
18382498Sroberto * Cryptotypes
18482498Sroberto */
185285612Sdelphijstatic	int	crypto_verify	(struct exten *, struct value *,
186285612Sdelphij				    struct peer *);
187285612Sdelphijstatic	int	crypto_encrypt	(const u_char *, u_int, keyid_t *,
188285612Sdelphij				    struct value *);
189285612Sdelphijstatic	int	crypto_alice	(struct peer *, struct value *);
190285612Sdelphijstatic	int	crypto_alice2	(struct peer *, struct value *);
191285612Sdelphijstatic	int	crypto_alice3	(struct peer *, struct value *);
192285612Sdelphijstatic	int	crypto_bob	(struct exten *, struct value *);
193285612Sdelphijstatic	int	crypto_bob2	(struct exten *, struct value *);
194285612Sdelphijstatic	int	crypto_bob3	(struct exten *, struct value *);
195285612Sdelphijstatic	int	crypto_iff	(struct exten *, struct peer *);
196285612Sdelphijstatic	int	crypto_gq	(struct exten *, struct peer *);
197285612Sdelphijstatic	int	crypto_mv	(struct exten *, struct peer *);
198285612Sdelphijstatic	int	crypto_send	(struct exten *, struct value *, int);
199285612Sdelphijstatic	tstamp_t crypto_time	(void);
200316069Sdelphijstatic	void	asn_to_calendar		(const ASN1_TIME *, struct calendar*);
201285612Sdelphijstatic	struct cert_info *cert_parse (const u_char *, long, tstamp_t);
202285612Sdelphijstatic	int	cert_sign	(struct exten *, struct value *);
203285612Sdelphijstatic	struct cert_info *cert_install (struct exten *, struct peer *);
204285612Sdelphijstatic	int	cert_hike	(struct peer *, struct cert_info *);
205285612Sdelphijstatic	void	cert_free	(struct cert_info *);
206285612Sdelphijstatic	struct pkey_info *crypto_key (char *, char *, sockaddr_u *);
207285612Sdelphijstatic	void	bighash		(BIGNUM *, BIGNUM *);
208285612Sdelphijstatic	struct cert_info *crypto_cert (char *);
209289997Sglebiusstatic	u_int	exten_payload_size(const struct exten *);
21082498Sroberto
211132451Sroberto#ifdef SYS_WINNT
212132451Srobertoint
213132451Srobertoreadlink(char * link, char * file, int len) {
214132451Sroberto	return (-1);
215132451Sroberto}
216132451Sroberto#endif
21782498Sroberto
21882498Sroberto/*
21982498Sroberto * session_key - generate session key
22082498Sroberto *
22182498Sroberto * This routine generates a session key from the source address,
22282498Sroberto * destination address, key ID and private value. The value of the
22382498Sroberto * session key is the MD5 hash of these values, while the next key ID is
22482498Sroberto * the first four octets of the hash.
225132451Sroberto *
226285612Sdelphij * Returns the next key ID or 0 if there is no destination address.
22782498Sroberto */
228132451Srobertokeyid_t
22982498Srobertosession_key(
230285612Sdelphij	sockaddr_u *srcadr, 	/* source address */
231285612Sdelphij	sockaddr_u *dstadr, 	/* destination address */
232132451Sroberto	keyid_t	keyno,		/* key ID */
233132451Sroberto	keyid_t	private,	/* private value */
234132451Sroberto	u_long	lifetime 	/* key lifetime */
23582498Sroberto	)
23682498Sroberto{
237309008Sdelphij	EVP_MD_CTX *ctx;	/* message digest context */
238132451Sroberto	u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
239132451Sroberto	keyid_t	keyid;		/* key identifer */
240132451Sroberto	u_int32	header[10];	/* data in network byte order */
241132451Sroberto	u_int	hdlen, len;
24282498Sroberto
243182007Sroberto	if (!dstadr)
244182007Sroberto		return 0;
245182007Sroberto
24682498Sroberto	/*
24782498Sroberto	 * Generate the session key and key ID. If the lifetime is
24882498Sroberto	 * greater than zero, install the key and call it trusted.
24982498Sroberto	 */
250132451Sroberto	hdlen = 0;
251285612Sdelphij	switch(AF(srcadr)) {
252132451Sroberto	case AF_INET:
253285612Sdelphij		header[0] = NSRCADR(srcadr);
254285612Sdelphij		header[1] = NSRCADR(dstadr);
255132451Sroberto		header[2] = htonl(keyno);
256132451Sroberto		header[3] = htonl(private);
257132451Sroberto		hdlen = 4 * sizeof(u_int32);
258132451Sroberto		break;
259182007Sroberto
260132451Sroberto	case AF_INET6:
261285612Sdelphij		memcpy(&header[0], PSOCK_ADDR6(srcadr),
262132451Sroberto		    sizeof(struct in6_addr));
263285612Sdelphij		memcpy(&header[4], PSOCK_ADDR6(dstadr),
264132451Sroberto		    sizeof(struct in6_addr));
265132451Sroberto		header[8] = htonl(keyno);
266132451Sroberto		header[9] = htonl(private);
267132451Sroberto		hdlen = 10 * sizeof(u_int32);
268132451Sroberto		break;
269132451Sroberto	}
270309008Sdelphij	ctx = EVP_MD_CTX_new();
271330141Sdelphij#   if defined(OPENSSL) && defined(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW)
272330141Sdelphij	/* [Bug 3457] set flags and don't kill them again */
273330141Sdelphij	EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
274330141Sdelphij	EVP_DigestInit_ex(ctx, EVP_get_digestbynid(crypto_nid), NULL);
275330141Sdelphij#   else
276309008Sdelphij	EVP_DigestInit(ctx, EVP_get_digestbynid(crypto_nid));
277330141Sdelphij#   endif
278309008Sdelphij	EVP_DigestUpdate(ctx, (u_char *)header, hdlen);
279309008Sdelphij	EVP_DigestFinal(ctx, dgst, &len);
280309008Sdelphij	EVP_MD_CTX_free(ctx);
281132451Sroberto	memcpy(&keyid, dgst, 4);
28282498Sroberto	keyid = ntohl(keyid);
28382498Sroberto	if (lifetime != 0) {
284294569Sdelphij		MD5auth_setkey(keyno, crypto_nid, dgst, len, NULL);
28582498Sroberto		authtrust(keyno, lifetime);
28682498Sroberto	}
287285612Sdelphij	DPRINTF(2, ("session_key: %s > %s %08x %08x hash %08x life %lu\n",
288132451Sroberto		    stoa(srcadr), stoa(dstadr), keyno,
289285612Sdelphij		    private, keyid, lifetime));
290285612Sdelphij
29182498Sroberto	return (keyid);
29282498Sroberto}
29382498Sroberto
29482498Sroberto
29582498Sroberto/*
29682498Sroberto * make_keylist - generate key list
29782498Sroberto *
298182007Sroberto * Returns
299182007Sroberto * XEVNT_OK	success
300285612Sdelphij * XEVNT_ERR	protocol error
301182007Sroberto *
30282498Sroberto * This routine constructs a pseudo-random sequence by repeatedly
30382498Sroberto * hashing the session key starting from a given source address,
30482498Sroberto * destination address, private value and the next key ID of the
30582498Sroberto * preceeding session key. The last entry on the list is saved along
30682498Sroberto * with its sequence number and public signature.
30782498Sroberto */
308182007Srobertoint
30982498Srobertomake_keylist(
31082498Sroberto	struct peer *peer,	/* peer structure pointer */
31182498Sroberto	struct interface *dstadr /* interface */
31282498Sroberto	)
31382498Sroberto{
314309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
315132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
31682498Sroberto	struct autokey *ap;	/* autokey pointer */
317132451Sroberto	struct value *vp;	/* value pointer */
318132451Sroberto	keyid_t	keyid = 0;	/* next key ID */
319132451Sroberto	keyid_t	cookie;		/* private value */
320285612Sdelphij	long	lifetime;
321182007Sroberto	u_int	len, mpoll;
322132451Sroberto	int	i;
32382498Sroberto
324182007Sroberto	if (!dstadr)
325285612Sdelphij		return XEVNT_ERR;
326182007Sroberto
32782498Sroberto	/*
32882498Sroberto	 * Allocate the key list if necessary.
32982498Sroberto	 */
330132451Sroberto	tstamp = crypto_time();
33182498Sroberto	if (peer->keylist == NULL)
332285612Sdelphij		peer->keylist = eallocarray(NTP_MAXSESSION,
333285612Sdelphij					    sizeof(keyid_t));
33482498Sroberto
33582498Sroberto	/*
33682498Sroberto	 * Generate an initial key ID which is unique and greater than
33782498Sroberto	 * NTP_MAXKEY.
33882498Sroberto	 */
33982498Sroberto	while (1) {
340285612Sdelphij		keyid = ntp_random() & 0xffffffff;
341285612Sdelphij		if (keyid <= NTP_MAXKEY)
342285612Sdelphij			continue;
343285612Sdelphij
34482498Sroberto		if (authhavekey(keyid))
34582498Sroberto			continue;
34682498Sroberto		break;
34782498Sroberto	}
34882498Sroberto
34982498Sroberto	/*
35082498Sroberto	 * Generate up to NTP_MAXSESSION session keys. Stop if the
35182498Sroberto	 * next one would not be unique or not a session key ID or if
35282498Sroberto	 * it would expire before the next poll. The private value
35382498Sroberto	 * included in the hash is zero if broadcast mode, the peer
35482498Sroberto	 * cookie if client mode or the host cookie if symmetric modes.
35582498Sroberto	 */
356182007Sroberto	mpoll = 1 << min(peer->ppoll, peer->hpoll);
357285612Sdelphij	lifetime = min(1U << sys_automax, NTP_MAXSESSION * mpoll);
35882498Sroberto	if (peer->hmode == MODE_BROADCAST)
35982498Sroberto		cookie = 0;
36082498Sroberto	else
361132451Sroberto		cookie = peer->pcookie;
36282498Sroberto	for (i = 0; i < NTP_MAXSESSION; i++) {
36382498Sroberto		peer->keylist[i] = keyid;
36482498Sroberto		peer->keynumber = i;
36582498Sroberto		keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
366285612Sdelphij		    cookie, lifetime + mpoll);
367182007Sroberto		lifetime -= mpoll;
36882498Sroberto		if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
369285612Sdelphij		    lifetime < 0 || tstamp == 0)
37082498Sroberto			break;
37182498Sroberto	}
37282498Sroberto
37382498Sroberto	/*
37482498Sroberto	 * Save the last session key ID, sequence number and timestamp,
37582498Sroberto	 * then sign these values for later retrieval by the clients. Be
376132451Sroberto	 * careful not to use invalid key media. Use the public values
377132451Sroberto	 * timestamp as filestamp.
37882498Sroberto	 */
379132451Sroberto	vp = &peer->sndval;
380132451Sroberto	if (vp->ptr == NULL)
381132451Sroberto		vp->ptr = emalloc(sizeof(struct autokey));
382132451Sroberto	ap = (struct autokey *)vp->ptr;
38382498Sroberto	ap->seq = htonl(peer->keynumber);
38482498Sroberto	ap->key = htonl(keyid);
385132451Sroberto	vp->tstamp = htonl(tstamp);
386132451Sroberto	vp->fstamp = hostval.tstamp;
387132451Sroberto	vp->vallen = htonl(sizeof(struct autokey));
388132451Sroberto	vp->siglen = 0;
389182007Sroberto	if (tstamp != 0) {
390132451Sroberto		if (vp->sig == NULL)
391132451Sroberto			vp->sig = emalloc(sign_siglen);
392309008Sdelphij		ctx = EVP_MD_CTX_new();
393309008Sdelphij		EVP_SignInit(ctx, sign_digest);
394309008Sdelphij		EVP_SignUpdate(ctx, (u_char *)vp, 12);
395309008Sdelphij		EVP_SignUpdate(ctx, vp->ptr, sizeof(struct autokey));
396309008Sdelphij		if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
397289997Sglebius			INSIST(len <= sign_siglen);
398132451Sroberto			vp->siglen = htonl(len);
399285612Sdelphij			peer->flags |= FLAG_ASSOC;
400285612Sdelphij		}
401309008Sdelphij		EVP_MD_CTX_free(ctx);
402132451Sroberto	}
403285612Sdelphij	DPRINTF(1, ("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
404285612Sdelphij		    peer->keynumber, keyid, cookie, ntohl(vp->tstamp),
405285612Sdelphij		    ntohl(vp->fstamp), peer->hpoll));
406182007Sroberto	return (XEVNT_OK);
40782498Sroberto}
40882498Sroberto
40982498Sroberto
41082498Sroberto/*
41182498Sroberto * crypto_recv - parse extension fields
41282498Sroberto *
41382498Sroberto * This routine is called when the packet has been matched to an
41482498Sroberto * association and passed sanity, format and MAC checks. We believe the
41582498Sroberto * extension field values only if the field has proper format and
41682498Sroberto * length, the timestamp and filestamp are valid and the signature has
41782498Sroberto * valid length and is verified. There are a few cases where some values
418132451Sroberto * are believed even if the signature fails, but only if the proventic
41982498Sroberto * bit is not set.
420285612Sdelphij *
421285612Sdelphij * Returns
422285612Sdelphij * XEVNT_OK	success
423285612Sdelphij * XEVNT_ERR	protocol error
424285612Sdelphij * XEVNT_LEN	bad field format or length
42582498Sroberto */
426132451Srobertoint
42782498Srobertocrypto_recv(
42882498Sroberto	struct peer *peer,	/* peer structure pointer */
42982498Sroberto	struct recvbuf *rbufp	/* packet buffer pointer */
43082498Sroberto	)
43182498Sroberto{
432132451Sroberto	const EVP_MD *dp;	/* message digest algorithm */
433132451Sroberto	u_int32	*pkt;		/* receive packet pointer */
434132451Sroberto	struct autokey *ap, *bp; /* autokey pointer */
435132451Sroberto	struct exten *ep, *fp;	/* extension pointers */
436285612Sdelphij	struct cert_info *xinfo; /* certificate info pointer */
437289997Sglebius	int	macbytes;	/* length of MAC field, signed by intention */
438132451Sroberto	int	authlen;	/* offset of MAC field */
439132451Sroberto	associd_t associd;	/* association ID */
440132451Sroberto	tstamp_t fstamp = 0;	/* filestamp */
441132451Sroberto	u_int	len;		/* extension field length */
442132451Sroberto	u_int	code;		/* extension field opcode */
443132451Sroberto	u_int	vallen = 0;	/* value length */
444132451Sroberto	X509	*cert;		/* X509 certificate */
445132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
446132451Sroberto	keyid_t	cookie;		/* crumbles */
447182007Sroberto	int	hismode;	/* packet mode */
448132451Sroberto	int	rval = XEVNT_OK;
449285612Sdelphij	const u_char *puch;
450132451Sroberto	u_int32 temp32;
45182498Sroberto
45282498Sroberto	/*
45382498Sroberto	 * Initialize. Note that the packet has already been checked for
454132451Sroberto	 * valid format and extension field lengths. First extract the
455132451Sroberto	 * field length, command code and association ID in host byte
456132451Sroberto	 * order. These are used with all commands and modes. Then check
457132451Sroberto	 * the version number, which must be 2, and length, which must
458132451Sroberto	 * be at least 8 for requests and VALUE_LEN (24) for responses.
459132451Sroberto	 * Packets that fail either test sink without a trace. The
460132451Sroberto	 * association ID is saved only if nonzero.
46182498Sroberto	 */
46282498Sroberto	authlen = LEN_PKT_NOMAC;
463182007Sroberto	hismode = (int)PKT_MODE((&rbufp->recv_pkt)->li_vn_mode);
464289997Sglebius	while ((macbytes = rbufp->recv_length - authlen) > (int)MAX_MAC_LEN) {
465289997Sglebius		/* We can be reasonably sure that we can read at least
466289997Sglebius		 * the opcode and the size field here. More stringent
467289997Sglebius		 * checks follow up shortly.
468289997Sglebius		 */
469132451Sroberto		pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
470132451Sroberto		ep = (struct exten *)pkt;
471132451Sroberto		code = ntohl(ep->opcode) & 0xffff0000;
472132451Sroberto		len = ntohl(ep->opcode) & 0x0000ffff;
473285612Sdelphij		// HMS: Why pkt[1] instead of ep->associd ?
474285612Sdelphij		associd = (associd_t)ntohl(pkt[1]);
475132451Sroberto		rval = XEVNT_OK;
476285612Sdelphij		DPRINTF(1, ("crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
477132451Sroberto			    peer->crypto, authlen, len, code >> 16,
478285612Sdelphij			    associd));
479132451Sroberto
480132451Sroberto		/*
481132451Sroberto		 * Check version number and field length. If bad,
482132451Sroberto		 * quietly ignore the packet.
483132451Sroberto		 */
484182007Sroberto		if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8) {
485285612Sdelphij			sys_badlength++;
486132451Sroberto			code |= CRYPTO_ERROR;
487132451Sroberto		}
488132451Sroberto
489289997Sglebius		/* Check if the declared size fits into the remaining
490293650Sglebius		 * buffer. We *know* 'macbytes' > 0 here!
491289997Sglebius		 */
492293650Sglebius		if (len > (u_int)macbytes) {
493289997Sglebius			DPRINTF(1, ("crypto_recv: possible attack detected, associd %d\n",
494289997Sglebius				    associd));
495289997Sglebius			return XEVNT_LEN;
496289997Sglebius		}
497289997Sglebius
498289997Sglebius		/* Check if the paylod of the extension fits into the
499289997Sglebius		 * declared frame.
500289997Sglebius		 */
501132451Sroberto		if (len >= VALUE_LEN) {
502132451Sroberto			fstamp = ntohl(ep->fstamp);
503132451Sroberto			vallen = ntohl(ep->vallen);
504281230Sdelphij			/*
505281230Sdelphij			 * Bug 2761: I hope this isn't too early...
506281230Sdelphij			 */
507281230Sdelphij			if (   vallen == 0
508281230Sdelphij			    || len - VALUE_LEN < vallen)
509281230Sdelphij				return XEVNT_LEN;
510132451Sroberto		}
51182498Sroberto		switch (code) {
51282498Sroberto
51382498Sroberto		/*
514132451Sroberto		 * Install status word, host name, signature scheme and
515132451Sroberto		 * association ID. In OpenSSL the signature algorithm is
516132451Sroberto		 * bound to the digest algorithm, so the NID completely
517132451Sroberto		 * defines the signature scheme. Note the request and
518132451Sroberto		 * response are identical, but neither is validated by
519132451Sroberto		 * signature. The request is processed here only in
520182007Sroberto		 * symmetric modes. The server name field might be
521132451Sroberto		 * useful to implement access controls in future.
52282498Sroberto		 */
523132451Sroberto		case CRYPTO_ASSOC:
524132451Sroberto
525132451Sroberto			/*
526285612Sdelphij			 * If our state machine is running when this
527285612Sdelphij			 * message arrives, the other fellow might have
528285612Sdelphij			 * restarted. However, this could be an
529285612Sdelphij			 * intruder, so just clamp the poll interval and
530285612Sdelphij			 * find out for ourselves. Otherwise, pass the
531285612Sdelphij			 * extension field to the transmit side.
532132451Sroberto			 */
533285612Sdelphij			if (peer->crypto & CRYPTO_FLAG_CERT) {
534182007Sroberto				rval = XEVNT_ERR;
535182007Sroberto				break;
536182007Sroberto			}
537285612Sdelphij			if (peer->cmmd) {
538285612Sdelphij				if (peer->assoc != associd) {
539285612Sdelphij					rval = XEVNT_ERR;
540285612Sdelphij					break;
541285612Sdelphij				}
542289997Sglebius				free(peer->cmmd); /* will be set again! */
543285612Sdelphij			}
544132451Sroberto			fp = emalloc(len);
545132451Sroberto			memcpy(fp, ep, len);
546285612Sdelphij			fp->associd = htonl(peer->associd);
547132451Sroberto			peer->cmmd = fp;
548132451Sroberto			/* fall through */
549132451Sroberto
55082498Sroberto		case CRYPTO_ASSOC | CRYPTO_RESP:
551132451Sroberto
552132451Sroberto			/*
553132451Sroberto			 * Discard the message if it has already been
554182007Sroberto			 * stored or the message has been amputated.
555132451Sroberto			 */
556285612Sdelphij			if (peer->crypto) {
557285612Sdelphij				if (peer->assoc != associd)
558285612Sdelphij					rval = XEVNT_ERR;
559132451Sroberto				break;
560285612Sdelphij			}
561285612Sdelphij			INSIST(len >= VALUE_LEN);
562182007Sroberto			if (vallen == 0 || vallen > MAXHOSTNAME ||
563281230Sdelphij			    len - VALUE_LEN < vallen) {
564132451Sroberto				rval = XEVNT_LEN;
565132451Sroberto				break;
56682498Sroberto			}
567285612Sdelphij			DPRINTF(1, ("crypto_recv: ident host 0x%x %d server 0x%x %d\n",
568285612Sdelphij				    crypto_flags, peer->associd, fstamp,
569285612Sdelphij				    peer->assoc));
570285612Sdelphij			temp32 = crypto_flags & CRYPTO_FLAG_MASK;
571132451Sroberto
572132451Sroberto			/*
573285612Sdelphij			 * If the client scheme is PC, the server scheme
574285612Sdelphij			 * must be PC. The public key and identity are
575285612Sdelphij			 * presumed valid, so we skip the certificate
576285612Sdelphij			 * and identity exchanges and move immediately
577285612Sdelphij			 * to the cookie exchange which confirms the
578285612Sdelphij			 * server signature.
579132451Sroberto			 */
580132451Sroberto			if (crypto_flags & CRYPTO_FLAG_PRIV) {
581182007Sroberto				if (!(fstamp & CRYPTO_FLAG_PRIV)) {
582132451Sroberto					rval = XEVNT_KEY;
583182007Sroberto					break;
584285612Sdelphij				}
585285612Sdelphij				fstamp |= CRYPTO_FLAG_CERT |
586285612Sdelphij				    CRYPTO_FLAG_VRFY | CRYPTO_FLAG_SIGN;
587182007Sroberto
588182007Sroberto			/*
589285612Sdelphij			 * It is an error if either peer supports
590285612Sdelphij			 * identity, but the other does not.
591182007Sroberto			 */
592285612Sdelphij			} else if (hismode == MODE_ACTIVE || hismode ==
593285612Sdelphij			    MODE_PASSIVE) {
594285612Sdelphij				if ((temp32 && !(fstamp &
595285612Sdelphij				    CRYPTO_FLAG_MASK)) ||
596285612Sdelphij				    (!temp32 && (fstamp &
597285612Sdelphij				    CRYPTO_FLAG_MASK))) {
598285612Sdelphij					rval = XEVNT_KEY;
599285612Sdelphij					break;
600285612Sdelphij				}
601132451Sroberto			}
602132451Sroberto
603132451Sroberto			/*
604182007Sroberto			 * Discard the message if the signature digest
605182007Sroberto			 * NID is not supported.
606132451Sroberto			 */
607132451Sroberto			temp32 = (fstamp >> 16) & 0xffff;
608132451Sroberto			dp =
609132451Sroberto			    (const EVP_MD *)EVP_get_digestbynid(temp32);
610182007Sroberto			if (dp == NULL) {
611132451Sroberto				rval = XEVNT_MD;
612132451Sroberto				break;
613182007Sroberto			}
614132451Sroberto
615132451Sroberto			/*
616132451Sroberto			 * Save status word, host name and message
617285612Sdelphij			 * digest/signature type. If this is from a
618285612Sdelphij			 * broadcast and the association ID has changed,
619285612Sdelphij			 * request the autokey values.
620132451Sroberto			 */
621285612Sdelphij			peer->assoc = associd;
622285612Sdelphij			if (hismode == MODE_SERVER)
623285612Sdelphij				fstamp |= CRYPTO_FLAG_AUTO;
624285612Sdelphij			if (!(fstamp & CRYPTO_FLAG_TAI))
625285612Sdelphij				fstamp |= CRYPTO_FLAG_LEAP;
626285612Sdelphij			RAND_bytes((u_char *)&peer->hcookie, 4);
627132451Sroberto			peer->crypto = fstamp;
628132451Sroberto			peer->digest = dp;
629285612Sdelphij			if (peer->subject != NULL)
630285612Sdelphij				free(peer->subject);
631132451Sroberto			peer->subject = emalloc(vallen + 1);
632132451Sroberto			memcpy(peer->subject, ep->pkt, vallen);
633132451Sroberto			peer->subject[vallen] = '\0';
634285612Sdelphij			if (peer->issuer != NULL)
635285612Sdelphij				free(peer->issuer);
636285612Sdelphij			peer->issuer = estrdup(peer->subject);
637285612Sdelphij			snprintf(statstr, sizeof(statstr),
638285612Sdelphij			    "assoc %d %d host %s %s", peer->associd,
639285612Sdelphij			    peer->assoc, peer->subject,
640285612Sdelphij			    OBJ_nid2ln(temp32));
641132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
642285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
64382498Sroberto			break;
64482498Sroberto
64582498Sroberto		/*
646132451Sroberto		 * Decode X509 certificate in ASN.1 format and extract
647132451Sroberto		 * the data containing, among other things, subject
648132451Sroberto		 * name and public key. In the default identification
649132451Sroberto		 * scheme, the certificate trail is followed to a self
650132451Sroberto		 * signed trusted certificate.
65182498Sroberto		 */
652132451Sroberto		case CRYPTO_CERT | CRYPTO_RESP:
653132451Sroberto
654132451Sroberto			/*
655285612Sdelphij			 * Discard the message if empty or invalid.
656132451Sroberto			 */
657285612Sdelphij			if (len < VALUE_LEN)
658285612Sdelphij				break;
659285612Sdelphij
660132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
661132451Sroberto			    XEVNT_OK)
662132451Sroberto				break;
663132451Sroberto
664132451Sroberto			/*
665132451Sroberto			 * Scan the certificate list to delete old
666132451Sroberto			 * versions and link the newest version first on
667285612Sdelphij			 * the list. Then, verify the signature. If the
668285612Sdelphij			 * certificate is bad or missing, just ignore
669285612Sdelphij			 * it.
670132451Sroberto			 */
671285612Sdelphij			if ((xinfo = cert_install(ep, peer)) == NULL) {
672285612Sdelphij				rval = XEVNT_CRT;
673132451Sroberto				break;
674285612Sdelphij			}
675285612Sdelphij			if ((rval = cert_hike(peer, xinfo)) != XEVNT_OK)
676285612Sdelphij				break;
677132451Sroberto
678132451Sroberto			/*
679182007Sroberto			 * We plug in the public key and lifetime from
680132451Sroberto			 * the first certificate received. However, note
681132451Sroberto			 * that this certificate might not be signed by
682132451Sroberto			 * the server, so we can't check the
683132451Sroberto			 * signature/digest NID.
684132451Sroberto			 */
685132451Sroberto			if (peer->pkey == NULL) {
686285612Sdelphij				puch = xinfo->cert.ptr;
687285612Sdelphij				cert = d2i_X509(NULL, &puch,
688285612Sdelphij				    ntohl(xinfo->cert.vallen));
689132451Sroberto				peer->pkey = X509_get_pubkey(cert);
690132451Sroberto				X509_free(cert);
69182498Sroberto			}
692182007Sroberto			peer->flash &= ~TEST8;
693285612Sdelphij			temp32 = xinfo->nid;
694285612Sdelphij			snprintf(statstr, sizeof(statstr),
695285612Sdelphij			    "cert %s %s 0x%x %s (%u) fs %u",
696285612Sdelphij			    xinfo->subject, xinfo->issuer, xinfo->flags,
697132451Sroberto			    OBJ_nid2ln(temp32), temp32,
698132451Sroberto			    ntohl(ep->fstamp));
699132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
700285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
70182498Sroberto			break;
70282498Sroberto
70382498Sroberto		/*
704285612Sdelphij		 * Schnorr (IFF) identity scheme. This scheme is
705285612Sdelphij		 * designed for use with shared secret server group keys
706285612Sdelphij		 * and where the certificate may be generated by a third
707285612Sdelphij		 * party. The client sends a challenge to the server,
708285612Sdelphij		 * which performs a calculation and returns the result.
709285612Sdelphij		 * A positive result is possible only if both client and
710132451Sroberto		 * server contain the same secret group key.
71182498Sroberto		 */
712132451Sroberto		case CRYPTO_IFF | CRYPTO_RESP:
71382498Sroberto
714132451Sroberto			/*
715285612Sdelphij			 * Discard the message if invalid.
716132451Sroberto			 */
717132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
718132451Sroberto			    XEVNT_OK)
719132451Sroberto				break;
720132451Sroberto
72182498Sroberto			/*
722285612Sdelphij			 * If the challenge matches the response, the
723285612Sdelphij			 * server public key, signature and identity are
724132451Sroberto			 * all verified at the same time. The server is
725132451Sroberto			 * declared trusted, so we skip further
726285612Sdelphij			 * certificate exchanges and move immediately to
727285612Sdelphij			 * the cookie exchange.
72882498Sroberto			 */
729132451Sroberto			if ((rval = crypto_iff(ep, peer)) != XEVNT_OK)
730132451Sroberto				break;
731132451Sroberto
732285612Sdelphij			peer->crypto |= CRYPTO_FLAG_VRFY;
733182007Sroberto			peer->flash &= ~TEST8;
734285612Sdelphij			snprintf(statstr, sizeof(statstr), "iff %s fs %u",
735285612Sdelphij			    peer->issuer, ntohl(ep->fstamp));
736132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
737285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
73882498Sroberto			break;
73982498Sroberto
74082498Sroberto		/*
741132451Sroberto		 * Guillou-Quisquater (GQ) identity scheme. This scheme
742132451Sroberto		 * is designed for use with public certificates carrying
743132451Sroberto		 * the GQ public key in an extension field. The client
744132451Sroberto		 * sends a challenge to the server, which performs a
745132451Sroberto		 * calculation and returns the result. A positive result
746132451Sroberto		 * is possible only if both client and server contain
747132451Sroberto		 * the same group key and the server has the matching GQ
748132451Sroberto		 * private key.
74982498Sroberto		 */
750132451Sroberto		case CRYPTO_GQ | CRYPTO_RESP:
751132451Sroberto
752132451Sroberto			/*
753285612Sdelphij			 * Discard the message if invalid
754132451Sroberto			 */
755132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
756132451Sroberto			    XEVNT_OK)
757132451Sroberto				break;
758132451Sroberto
759132451Sroberto			/*
760285612Sdelphij			 * If the challenge matches the response, the
761285612Sdelphij			 * server public key, signature and identity are
762132451Sroberto			 * all verified at the same time. The server is
763132451Sroberto			 * declared trusted, so we skip further
764285612Sdelphij			 * certificate exchanges and move immediately to
765285612Sdelphij			 * the cookie exchange.
766132451Sroberto			 */
767132451Sroberto			if ((rval = crypto_gq(ep, peer)) != XEVNT_OK)
768132451Sroberto				break;
769132451Sroberto
770285612Sdelphij			peer->crypto |= CRYPTO_FLAG_VRFY;
771182007Sroberto			peer->flash &= ~TEST8;
772285612Sdelphij			snprintf(statstr, sizeof(statstr), "gq %s fs %u",
773285612Sdelphij			    peer->issuer, ntohl(ep->fstamp));
774132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
775285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
77682498Sroberto			break;
77782498Sroberto
77882498Sroberto		/*
779285612Sdelphij		 * Mu-Varadharajan (MV) identity scheme. This scheme is
780285612Sdelphij		 * designed for use with three levels of trust, trusted
781285612Sdelphij		 * host, server and client. The trusted host key is
782285612Sdelphij		 * opaque to servers and clients; the server keys are
783285612Sdelphij		 * opaque to clients and each client key is different.
784285612Sdelphij		 * Client keys can be revoked without requiring new key
785285612Sdelphij		 * generations.
78682498Sroberto		 */
787132451Sroberto		case CRYPTO_MV | CRYPTO_RESP:
788132451Sroberto
789132451Sroberto			/*
790285612Sdelphij			 * Discard the message if invalid.
791132451Sroberto			 */
792132451Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
793132451Sroberto			    XEVNT_OK)
794132451Sroberto				break;
795132451Sroberto
796132451Sroberto			/*
797285612Sdelphij			 * If the challenge matches the response, the
798285612Sdelphij			 * server public key, signature and identity are
799132451Sroberto			 * all verified at the same time. The server is
800132451Sroberto			 * declared trusted, so we skip further
801285612Sdelphij			 * certificate exchanges and move immediately to
802285612Sdelphij			 * the cookie exchange.
803132451Sroberto			 */
804132451Sroberto			if ((rval = crypto_mv(ep, peer)) != XEVNT_OK)
805132451Sroberto				break;
806132451Sroberto
807285612Sdelphij			peer->crypto |= CRYPTO_FLAG_VRFY;
808182007Sroberto			peer->flash &= ~TEST8;
809285612Sdelphij			snprintf(statstr, sizeof(statstr), "mv %s fs %u",
810285612Sdelphij			    peer->issuer, ntohl(ep->fstamp));
811132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
812285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
813132451Sroberto			break;
81482498Sroberto
815132451Sroberto
816132451Sroberto		/*
817132451Sroberto		 * Cookie response in client and symmetric modes. If the
818132451Sroberto		 * cookie bit is set, the working cookie is the EXOR of
819132451Sroberto		 * the current and new values.
820132451Sroberto		 */
821132451Sroberto		case CRYPTO_COOK | CRYPTO_RESP:
822132451Sroberto
82382498Sroberto			/*
824285612Sdelphij			 * Discard the message if invalid or signature
825285612Sdelphij			 * not verified with respect to the cookie
826285612Sdelphij			 * values.
82782498Sroberto			 */
828132451Sroberto			if ((rval = crypto_verify(ep, &peer->cookval,
829132451Sroberto			    peer)) != XEVNT_OK)
830132451Sroberto				break;
831132451Sroberto
83282498Sroberto			/*
833132451Sroberto			 * Decrypt the cookie, hunting all the time for
834132451Sroberto			 * errors.
83582498Sroberto			 */
836285612Sdelphij			if (vallen == (u_int)EVP_PKEY_size(host_pkey)) {
837309008Sdelphij				RSA *rsa = EVP_PKEY_get0_RSA(host_pkey);
838309008Sdelphij				u_int32 *cookiebuf = malloc(RSA_size(rsa));
839285612Sdelphij				if (!cookiebuf) {
840276072Sdelphij					rval = XEVNT_CKY;
841276072Sdelphij					break;
842276072Sdelphij				}
843285612Sdelphij
844276072Sdelphij				if (RSA_private_decrypt(vallen,
845132451Sroberto				    (u_char *)ep->pkt,
846276072Sdelphij				    (u_char *)cookiebuf,
847309008Sdelphij				    rsa,
848276072Sdelphij				    RSA_PKCS1_OAEP_PADDING) != 4) {
849276072Sdelphij					rval = XEVNT_CKY;
850276072Sdelphij					free(cookiebuf);
851276072Sdelphij					break;
852276072Sdelphij				} else {
853276072Sdelphij					cookie = ntohl(*cookiebuf);
854276072Sdelphij					free(cookiebuf);
855276072Sdelphij				}
856132451Sroberto			} else {
857132451Sroberto				rval = XEVNT_CKY;
858132451Sroberto				break;
859132451Sroberto			}
86082498Sroberto
86182498Sroberto			/*
862132451Sroberto			 * Install cookie values and light the cookie
863132451Sroberto			 * bit. If this is not broadcast client mode, we
864132451Sroberto			 * are done here.
86582498Sroberto			 */
866132451Sroberto			key_expire(peer);
867285612Sdelphij			if (hismode == MODE_ACTIVE || hismode ==
868285612Sdelphij			    MODE_PASSIVE)
869285612Sdelphij				peer->pcookie = peer->hcookie ^ cookie;
870132451Sroberto			else
871132451Sroberto				peer->pcookie = cookie;
872285612Sdelphij			peer->crypto |= CRYPTO_FLAG_COOK;
873182007Sroberto			peer->flash &= ~TEST8;
874285612Sdelphij			snprintf(statstr, sizeof(statstr),
875285612Sdelphij			    "cook %x ts %u fs %u", peer->pcookie,
876285612Sdelphij			    ntohl(ep->tstamp), ntohl(ep->fstamp));
877132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
878285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
87982498Sroberto			break;
88082498Sroberto
88182498Sroberto		/*
882132451Sroberto		 * Install autokey values in broadcast client and
883132451Sroberto		 * symmetric modes. We have to do this every time the
884132451Sroberto		 * sever/peer cookie changes or a new keylist is
885132451Sroberto		 * rolled. Ordinarily, this is automatic as this message
886132451Sroberto		 * is piggybacked on the first NTP packet sent upon
887132451Sroberto		 * either of these events. Note that a broadcast client
888132451Sroberto		 * or symmetric peer can receive this response without a
889132451Sroberto		 * matching request.
89082498Sroberto		 */
891132451Sroberto		case CRYPTO_AUTO | CRYPTO_RESP:
89282498Sroberto
893132451Sroberto			/*
894285612Sdelphij			 * Discard the message if invalid or signature
895285612Sdelphij			 * not verified with respect to the receive
896285612Sdelphij			 * autokey values.
897132451Sroberto			 */
898132451Sroberto			if ((rval = crypto_verify(ep, &peer->recval,
899285612Sdelphij			    peer)) != XEVNT_OK)
900132451Sroberto				break;
901132451Sroberto
90282498Sroberto			/*
903285612Sdelphij			 * Discard the message if a broadcast client and
904285612Sdelphij			 * the association ID does not match. This might
905285612Sdelphij			 * happen if a broacast server restarts the
906285612Sdelphij			 * protocol. A protocol restart will occur at
907285612Sdelphij			 * the next ASSOC message.
908285612Sdelphij			 */
909285612Sdelphij			if ((peer->cast_flags & MDF_BCLNT) &&
910285612Sdelphij			    peer->assoc != associd)
911285612Sdelphij				break;
912285612Sdelphij
913285612Sdelphij			/*
914132451Sroberto			 * Install autokey values and light the
915132451Sroberto			 * autokey bit. This is not hard.
91682498Sroberto			 */
917285612Sdelphij			if (ep->tstamp == 0)
918285612Sdelphij				break;
919285612Sdelphij
920132451Sroberto			if (peer->recval.ptr == NULL)
921132451Sroberto				peer->recval.ptr =
922132451Sroberto				    emalloc(sizeof(struct autokey));
923132451Sroberto			bp = (struct autokey *)peer->recval.ptr;
924132451Sroberto			peer->recval.tstamp = ep->tstamp;
925132451Sroberto			peer->recval.fstamp = ep->fstamp;
926132451Sroberto			ap = (struct autokey *)ep->pkt;
927132451Sroberto			bp->seq = ntohl(ap->seq);
928132451Sroberto			bp->key = ntohl(ap->key);
929132451Sroberto			peer->pkeyid = bp->key;
930132451Sroberto			peer->crypto |= CRYPTO_FLAG_AUTO;
931182007Sroberto			peer->flash &= ~TEST8;
932285612Sdelphij			snprintf(statstr, sizeof(statstr),
933132451Sroberto			    "auto seq %d key %x ts %u fs %u", bp->seq,
934132451Sroberto			    bp->key, ntohl(ep->tstamp),
935132451Sroberto			    ntohl(ep->fstamp));
936132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
937285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
93882498Sroberto			break;
939182007Sroberto
940182007Sroberto		/*
941182007Sroberto		 * X509 certificate sign response. Validate the
942182007Sroberto		 * certificate signed by the server and install. Later
943182007Sroberto		 * this can be provided to clients of this server in
944182007Sroberto		 * lieu of the self signed certificate in order to
945182007Sroberto		 * validate the public key.
946182007Sroberto		 */
947182007Sroberto		case CRYPTO_SIGN | CRYPTO_RESP:
94882498Sroberto
949182007Sroberto			/*
950285612Sdelphij			 * Discard the message if invalid.
951182007Sroberto			 */
952182007Sroberto			if ((rval = crypto_verify(ep, NULL, peer)) !=
953182007Sroberto			    XEVNT_OK)
954182007Sroberto				break;
955182007Sroberto
956182007Sroberto			/*
957182007Sroberto			 * Scan the certificate list to delete old
958182007Sroberto			 * versions and link the newest version first on
959182007Sroberto			 * the list.
960182007Sroberto			 */
961285612Sdelphij			if ((xinfo = cert_install(ep, peer)) == NULL) {
962285612Sdelphij				rval = XEVNT_CRT;
963182007Sroberto				break;
964285612Sdelphij			}
965182007Sroberto			peer->crypto |= CRYPTO_FLAG_SIGN;
966182007Sroberto			peer->flash &= ~TEST8;
967285612Sdelphij			temp32 = xinfo->nid;
968285612Sdelphij			snprintf(statstr, sizeof(statstr),
969285612Sdelphij			    "sign %s %s 0x%x %s (%u) fs %u",
970285612Sdelphij			    xinfo->subject, xinfo->issuer, xinfo->flags,
971182007Sroberto			    OBJ_nid2ln(temp32), temp32,
972182007Sroberto			    ntohl(ep->fstamp));
973182007Sroberto			record_crypto_stats(&peer->srcadr, statstr);
974285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
975182007Sroberto			break;
976182007Sroberto
97782498Sroberto		/*
978285612Sdelphij		 * Install leapseconds values. While the leapsecond
979285612Sdelphij		 * values epoch, TAI offset and values expiration epoch
980285612Sdelphij		 * are retained, only the current TAI offset is provided
981285612Sdelphij		 * via the kernel to other applications.
98282498Sroberto		 */
983285612Sdelphij		case CRYPTO_LEAP | CRYPTO_RESP:
984132451Sroberto			/*
985285612Sdelphij			 * Discard the message if invalid. We can't
986285612Sdelphij			 * compare the value timestamps here, as they
987285612Sdelphij			 * can be updated by different servers.
988132451Sroberto			 */
989285612Sdelphij			rval = crypto_verify(ep, NULL, peer);
990285612Sdelphij			if ((rval   != XEVNT_OK          ) ||
991285612Sdelphij			    (vallen != 3*sizeof(uint32_t))  )
992132451Sroberto				break;
993132451Sroberto
994285612Sdelphij			/* Check if we can update the basic TAI offset
995285612Sdelphij			 * for our current leap frame. This is a hack
996285612Sdelphij			 * and ignores the time stamps in the autokey
997285612Sdelphij			 * message.
998132451Sroberto			 */
999285612Sdelphij			if (sys_leap != LEAP_NOTINSYNC)
1000285612Sdelphij				leapsec_autokey_tai(ntohl(ep->pkt[0]),
1001285612Sdelphij						    rbufp->recv_time.l_ui, NULL);
1002285612Sdelphij			tai_leap.tstamp = ep->tstamp;
1003285612Sdelphij			tai_leap.fstamp = ep->fstamp;
1004285612Sdelphij			crypto_update();
1005285612Sdelphij			mprintf_event(EVNT_TAI, peer,
1006285612Sdelphij				      "%d seconds", ntohl(ep->pkt[0]));
1007132451Sroberto			peer->crypto |= CRYPTO_FLAG_LEAP;
1008182007Sroberto			peer->flash &= ~TEST8;
1009285612Sdelphij			snprintf(statstr, sizeof(statstr),
1010285612Sdelphij				 "leap TAI offset %d at %u expire %u fs %u",
1011285612Sdelphij				 ntohl(ep->pkt[0]), ntohl(ep->pkt[1]),
1012285612Sdelphij				 ntohl(ep->pkt[2]), ntohl(ep->fstamp));
1013132451Sroberto			record_crypto_stats(&peer->srcadr, statstr);
1014285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
101582498Sroberto			break;
101682498Sroberto
101782498Sroberto		/*
1018132451Sroberto		 * We come here in symmetric modes for miscellaneous
1019132451Sroberto		 * commands that have value fields but are processed on
1020132451Sroberto		 * the transmit side. All we need do here is check for
1021285612Sdelphij		 * valid field length. Note that ASSOC is handled
1022285612Sdelphij		 * separately.
102382498Sroberto		 */
1024182007Sroberto		case CRYPTO_CERT:
1025132451Sroberto		case CRYPTO_IFF:
1026132451Sroberto		case CRYPTO_GQ:
1027132451Sroberto		case CRYPTO_MV:
1028285612Sdelphij		case CRYPTO_COOK:
1029132451Sroberto		case CRYPTO_SIGN:
1030132451Sroberto			if (len < VALUE_LEN) {
1031132451Sroberto				rval = XEVNT_LEN;
103282498Sroberto				break;
1033132451Sroberto			}
1034132451Sroberto			/* fall through */
1035132451Sroberto
1036132451Sroberto		/*
1037285612Sdelphij		 * We come here in symmetric modes for requests
1038285612Sdelphij		 * requiring a response (above plus AUTO and LEAP) and
1039285612Sdelphij		 * for responses. If a request, save the extension field
1040285612Sdelphij		 * for later; invalid requests will be caught on the
1041285612Sdelphij		 * transmit side. If an error or invalid response,
1042285612Sdelphij		 * declare a protocol error.
1043132451Sroberto		 */
1044132451Sroberto		default:
1045132451Sroberto			if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {
1046182007Sroberto				rval = XEVNT_ERR;
1047285612Sdelphij			} else if (peer->cmmd == NULL) {
1048132451Sroberto				fp = emalloc(len);
1049132451Sroberto				memcpy(fp, ep, len);
1050132451Sroberto				peer->cmmd = fp;
1051132451Sroberto			}
105282498Sroberto		}
1053132451Sroberto
1054132451Sroberto		/*
1055132451Sroberto		 * The first error found terminates the extension field
1056285612Sdelphij		 * scan and we return the laundry to the caller.
1057132451Sroberto		 */
1058285612Sdelphij		if (rval != XEVNT_OK) {
1059285612Sdelphij			snprintf(statstr, sizeof(statstr),
1060285612Sdelphij			    "%04x %d %02x %s", htonl(ep->opcode),
1061285612Sdelphij			    associd, rval, eventstr(rval));
1062182007Sroberto			record_crypto_stats(&peer->srcadr, statstr);
1063285612Sdelphij			DPRINTF(1, ("crypto_recv: %s\n", statstr));
1064285612Sdelphij			return (rval);
1065132451Sroberto		}
1066285612Sdelphij		authlen += (len + 3) / 4 * 4;
106782498Sroberto	}
1068132451Sroberto	return (rval);
106982498Sroberto}
107082498Sroberto
107182498Sroberto
107282498Sroberto/*
107382498Sroberto * crypto_xmit - construct extension fields
107482498Sroberto *
107582498Sroberto * This routine is called both when an association is configured and
1076132451Sroberto * when one is not. The only case where this matters is to retrieve the
1077132451Sroberto * autokey information, in which case the caller has to provide the
107882498Sroberto * association ID to match the association.
1079132451Sroberto *
1080285612Sdelphij * Side effect: update the packet offset.
1081285612Sdelphij *
1082285612Sdelphij * Errors
1083285612Sdelphij * XEVNT_OK	success
1084285612Sdelphij * XEVNT_CRT	bad or missing certificate
1085285612Sdelphij * XEVNT_ERR	protocol error
1086285612Sdelphij * XEVNT_LEN	bad field format or length
1087285612Sdelphij * XEVNT_PER	host certificate expired
108882498Sroberto */
1089132451Srobertoint
109082498Srobertocrypto_xmit(
1091285612Sdelphij	struct peer *peer,	/* peer structure pointer */
1092132451Sroberto	struct pkt *xpkt,	/* transmit packet pointer */
1093285612Sdelphij	struct recvbuf *rbufp,	/* receive buffer pointer */
1094132451Sroberto	int	start,		/* offset to extension field */
1095132451Sroberto	struct exten *ep,	/* extension pointer */
1096132451Sroberto	keyid_t cookie		/* session cookie */
109782498Sroberto	)
109882498Sroberto{
1099285612Sdelphij	struct exten *fp;	/* extension pointers */
1100285612Sdelphij	struct cert_info *cp, *xp, *yp; /* cert info/value pointer */
1101285612Sdelphij	sockaddr_u *srcadr_sin; /* source address */
1102132451Sroberto	u_int32	*pkt;		/* packet pointer */
1103132451Sroberto	u_int	opcode;		/* extension field opcode */
1104132451Sroberto	char	certname[MAXHOSTNAME + 1]; /* subject name buffer */
1105132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
1106182007Sroberto	tstamp_t tstamp;
1107285612Sdelphij	struct calendar tscal;
1108132451Sroberto	u_int	vallen;
1109132451Sroberto	struct value vtemp;
1110132451Sroberto	associd_t associd;
1111132451Sroberto	int	rval;
1112285612Sdelphij	int	len;
1113132451Sroberto	keyid_t tcookie;
111482498Sroberto
111582498Sroberto	/*
111682498Sroberto	 * Generate the requested extension field request code, length
1117132451Sroberto	 * and association ID. If this is a response and the host is not
1118132451Sroberto	 * synchronized, light the error bit and go home.
111982498Sroberto	 */
1120132451Sroberto	pkt = (u_int32 *)xpkt + start / 4;
1121132451Sroberto	fp = (struct exten *)pkt;
1122132451Sroberto	opcode = ntohl(ep->opcode);
1123285612Sdelphij	if (peer != NULL) {
1124285612Sdelphij		srcadr_sin = &peer->srcadr;
1125285612Sdelphij		if (!(opcode & CRYPTO_RESP))
1126285612Sdelphij			peer->opcode = ep->opcode;
1127285612Sdelphij	} else {
1128285612Sdelphij		srcadr_sin = &rbufp->recv_srcadr;
1129285612Sdelphij	}
1130132451Sroberto	associd = (associd_t) ntohl(ep->associd);
113182498Sroberto	len = 8;
1132285612Sdelphij	fp->opcode = htonl((opcode & 0xffff0000) | len);
1133285612Sdelphij	fp->associd = ep->associd;
1134132451Sroberto	rval = XEVNT_OK;
1135182007Sroberto	tstamp = crypto_time();
1136132451Sroberto	switch (opcode & 0xffff0000) {
113782498Sroberto
113882498Sroberto	/*
1139132451Sroberto	 * Send association request and response with status word and
1140132451Sroberto	 * host name. Note, this message is not signed and the filestamp
1141182007Sroberto	 * contains only the status word.
114282498Sroberto	 */
1143285612Sdelphij	case CRYPTO_ASSOC:
114482498Sroberto	case CRYPTO_ASSOC | CRYPTO_RESP:
1145285612Sdelphij		len = crypto_send(fp, &hostval, start);
1146182007Sroberto		fp->fstamp = htonl(crypto_flags);
1147182007Sroberto		break;
1148182007Sroberto
114982498Sroberto	/*
1150132451Sroberto	 * Send certificate request. Use the values from the extension
1151132451Sroberto	 * field.
115282498Sroberto	 */
1153132451Sroberto	case CRYPTO_CERT:
1154132451Sroberto		memset(&vtemp, 0, sizeof(vtemp));
1155132451Sroberto		vtemp.tstamp = ep->tstamp;
1156132451Sroberto		vtemp.fstamp = ep->fstamp;
1157132451Sroberto		vtemp.vallen = ep->vallen;
1158182007Sroberto		vtemp.ptr = (u_char *)ep->pkt;
1159285612Sdelphij		len = crypto_send(fp, &vtemp, start);
1160132451Sroberto		break;
1161132451Sroberto
1162132451Sroberto	/*
1163285612Sdelphij	 * Send sign request. Use the host certificate, which is self-
1164285612Sdelphij	 * signed and may or may not be trusted.
1165132451Sroberto	 */
1166132451Sroberto	case CRYPTO_SIGN:
1167285612Sdelphij		(void)ntpcal_ntp_to_date(&tscal, tstamp, NULL);
1168285612Sdelphij		if ((calcomp(&tscal, &(cert_host->first)) < 0)
1169285612Sdelphij		|| (calcomp(&tscal, &(cert_host->last)) > 0))
1170285612Sdelphij			rval = XEVNT_PER;
1171285612Sdelphij		else
1172285612Sdelphij			len = crypto_send(fp, &cert_host->cert, start);
1173285612Sdelphij		break;
1174285612Sdelphij
1175285612Sdelphij	/*
1176285612Sdelphij	 * Send certificate response. Use the name in the extension
1177285612Sdelphij	 * field to find the certificate in the cache. If the request
1178285612Sdelphij	 * contains no subject name, assume the name of this host. This
1179285612Sdelphij	 * is for backwards compatibility. Private certificates are
1180285612Sdelphij	 * never sent.
1181285612Sdelphij	 *
1182285612Sdelphij	 * There may be several certificates matching the request. First
1183285612Sdelphij	 * choice is a self-signed trusted certificate; second choice is
1184285612Sdelphij	 * any certificate signed by another host. There is no third
1185285612Sdelphij	 * choice.
1186285612Sdelphij	 */
1187132451Sroberto	case CRYPTO_CERT | CRYPTO_RESP:
1188289997Sglebius		vallen = exten_payload_size(ep); /* Must be <64k */
1189289997Sglebius		if (vallen == 0 || vallen >= sizeof(certname) ) {
1190182007Sroberto			rval = XEVNT_LEN;
119182498Sroberto			break;
119282498Sroberto		}
1193182007Sroberto
1194182007Sroberto		/*
1195285612Sdelphij		 * Find all public valid certificates with matching
1196285612Sdelphij		 * subject. If a self-signed, trusted certificate is
1197285612Sdelphij		 * found, use that certificate. If not, use the last non
1198285612Sdelphij		 * self-signed certificate.
1199182007Sroberto		 */
1200285612Sdelphij		memcpy(certname, ep->pkt, vallen);
1201285612Sdelphij		certname[vallen] = '\0';
1202285612Sdelphij		xp = yp = NULL;
1203132451Sroberto		for (cp = cinfo; cp != NULL; cp = cp->link) {
1204285612Sdelphij			if (cp->flags & (CERT_PRIV | CERT_ERROR))
1205132451Sroberto				continue;
1206182007Sroberto
1207285612Sdelphij			if (strcmp(certname, cp->subject) != 0)
1208285612Sdelphij				continue;
1209285612Sdelphij
1210285612Sdelphij			if (strcmp(certname, cp->issuer) != 0)
1211285612Sdelphij				yp = cp;
1212285612Sdelphij			else if (cp ->flags & CERT_TRUST)
1213285612Sdelphij				xp = cp;
1214285612Sdelphij			continue;
1215132451Sroberto		}
1216182007Sroberto
1217182007Sroberto		/*
1218285612Sdelphij		 * Be careful who you trust. If the certificate is not
1219285612Sdelphij		 * found, return an empty response. Note that we dont
1220285612Sdelphij		 * enforce lifetimes here.
1221182007Sroberto		 *
1222285612Sdelphij		 * The timestamp and filestamp are taken from the
1223182007Sroberto		 * certificate value structure. For all certificates the
1224182007Sroberto		 * timestamp is the latest signature update time. For
1225182007Sroberto		 * host and imported certificates the filestamp is the
1226182007Sroberto		 * creation epoch. For signed certificates the filestamp
1227182007Sroberto		 * is the creation epoch of the trusted certificate at
1228285612Sdelphij		 * the root of the certificate trail. In principle, this
1229182007Sroberto		 * allows strong checking for signature masquerade.
1230182007Sroberto		 */
1231285612Sdelphij		if (xp == NULL)
1232285612Sdelphij			xp = yp;
1233285612Sdelphij		if (xp == NULL)
1234285612Sdelphij			break;
1235285612Sdelphij
1236182007Sroberto		if (tstamp == 0)
1237182007Sroberto			break;
1238182007Sroberto
1239285612Sdelphij		len = crypto_send(fp, &xp->cert, start);
124082498Sroberto		break;
124182498Sroberto
124282498Sroberto	/*
1243132451Sroberto	 * Send challenge in Schnorr (IFF) identity scheme.
124482498Sroberto	 */
1245132451Sroberto	case CRYPTO_IFF:
1246285612Sdelphij		if (peer == NULL)
1247285612Sdelphij			break;		/* hack attack */
1248285612Sdelphij
1249182007Sroberto		if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) {
1250285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1251182007Sroberto			value_free(&vtemp);
1252182007Sroberto		}
125382498Sroberto		break;
125482498Sroberto
125582498Sroberto	/*
1256132451Sroberto	 * Send response in Schnorr (IFF) identity scheme.
125782498Sroberto	 */
1258132451Sroberto	case CRYPTO_IFF | CRYPTO_RESP:
1259182007Sroberto		if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) {
1260285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1261182007Sroberto			value_free(&vtemp);
1262182007Sroberto		}
1263132451Sroberto		break;
1264132451Sroberto
126582498Sroberto	/*
1266132451Sroberto	 * Send challenge in Guillou-Quisquater (GQ) identity scheme.
126782498Sroberto	 */
1268132451Sroberto	case CRYPTO_GQ:
1269285612Sdelphij		if (peer == NULL)
1270285612Sdelphij			break;		/* hack attack */
1271285612Sdelphij
1272182007Sroberto		if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) {
1273285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1274182007Sroberto			value_free(&vtemp);
1275182007Sroberto		}
127682498Sroberto		break;
127782498Sroberto
127882498Sroberto	/*
1279132451Sroberto	 * Send response in Guillou-Quisquater (GQ) identity scheme.
128082498Sroberto	 */
1281132451Sroberto	case CRYPTO_GQ | CRYPTO_RESP:
1282182007Sroberto		if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) {
1283285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1284182007Sroberto			value_free(&vtemp);
1285182007Sroberto		}
1286132451Sroberto		break;
1287132451Sroberto
1288132451Sroberto	/*
1289132451Sroberto	 * Send challenge in MV identity scheme.
1290132451Sroberto	 */
1291132451Sroberto	case CRYPTO_MV:
1292285612Sdelphij		if (peer == NULL)
1293285612Sdelphij			break;		/* hack attack */
1294285612Sdelphij
1295182007Sroberto		if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) {
1296285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1297182007Sroberto			value_free(&vtemp);
1298182007Sroberto		}
129982498Sroberto		break;
130082498Sroberto
130182498Sroberto	/*
1302132451Sroberto	 * Send response in MV identity scheme.
130382498Sroberto	 */
1304132451Sroberto	case CRYPTO_MV | CRYPTO_RESP:
1305182007Sroberto		if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) {
1306285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1307182007Sroberto			value_free(&vtemp);
1308182007Sroberto		}
1309132451Sroberto		break;
1310132451Sroberto
1311132451Sroberto	/*
1312132451Sroberto	 * Send certificate sign response. The integrity of the request
1313132451Sroberto	 * certificate has already been verified on the receive side.
1314132451Sroberto	 * Sign the response using the local server key. Use the
1315132451Sroberto	 * filestamp from the request and use the timestamp as the
1316132451Sroberto	 * current time. Light the error bit if the certificate is
1317132451Sroberto	 * invalid or contains an unverified signature.
1318132451Sroberto	 */
1319132451Sroberto	case CRYPTO_SIGN | CRYPTO_RESP:
1320285612Sdelphij		if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK) {
1321285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1322285612Sdelphij			value_free(&vtemp);
1323285612Sdelphij		}
1324132451Sroberto		break;
1325132451Sroberto
1326132451Sroberto	/*
1327132451Sroberto	 * Send public key and signature. Use the values from the public
1328132451Sroberto	 * key.
1329132451Sroberto	 */
1330132451Sroberto	case CRYPTO_COOK:
1331285612Sdelphij		len = crypto_send(fp, &pubkey, start);
1332132451Sroberto		break;
1333132451Sroberto
1334132451Sroberto	/*
1335132451Sroberto	 * Encrypt and send cookie and signature. Light the error bit if
1336132451Sroberto	 * anything goes wrong.
1337132451Sroberto	 */
1338132451Sroberto	case CRYPTO_COOK | CRYPTO_RESP:
1339281230Sdelphij		vallen = ntohl(ep->vallen);	/* Must be <64k */
1340281230Sdelphij		if (   vallen == 0
1341281230Sdelphij		    || (vallen >= MAX_VALLEN)
1342281230Sdelphij		    || (opcode & 0x0000ffff)  < VALUE_LEN + vallen) {
1343182007Sroberto			rval = XEVNT_LEN;
134482498Sroberto			break;
134582498Sroberto		}
1346285612Sdelphij		if (peer == NULL)
1347132451Sroberto			tcookie = cookie;
1348285612Sdelphij		else
1349285612Sdelphij			tcookie = peer->hcookie;
1350281230Sdelphij		if ((rval = crypto_encrypt((const u_char *)ep->pkt, vallen, &tcookie, &vtemp))
1351281230Sdelphij		    == XEVNT_OK) {
1352285612Sdelphij			len = crypto_send(fp, &vtemp, start);
1353281230Sdelphij			value_free(&vtemp);
1354281230Sdelphij		}
135582498Sroberto		break;
135682498Sroberto
135782498Sroberto	/*
1358132451Sroberto	 * Find peer and send autokey data and signature in broadcast
1359132451Sroberto	 * server and symmetric modes. Use the values in the autokey
1360132451Sroberto	 * structure. If no association is found, either the server has
1361132451Sroberto	 * restarted with new associations or some perp has replayed an
1362132451Sroberto	 * old message, in which case light the error bit.
136382498Sroberto	 */
1364132451Sroberto	case CRYPTO_AUTO | CRYPTO_RESP:
1365285612Sdelphij		if (peer == NULL) {
1366285612Sdelphij			if ((peer = findpeerbyassoc(associd)) == NULL) {
1367285612Sdelphij				rval = XEVNT_ERR;
1368285612Sdelphij				break;
1369285612Sdelphij			}
137082498Sroberto		}
1371132451Sroberto		peer->flags &= ~FLAG_ASSOC;
1372285612Sdelphij		len = crypto_send(fp, &peer->sndval, start);
137382498Sroberto		break;
137482498Sroberto
137582498Sroberto	/*
1376285612Sdelphij	 * Send leapseconds values and signature. Use the values from
1377285612Sdelphij	 * the tai structure. If no table has been loaded, just send an
1378182007Sroberto	 * empty request.
137982498Sroberto	 */
1380285612Sdelphij	case CRYPTO_LEAP | CRYPTO_RESP:
1381285612Sdelphij		len = crypto_send(fp, &tai_leap, start);
138282498Sroberto		break;
138382498Sroberto
138482498Sroberto	/*
1385285612Sdelphij	 * Default - Send a valid command for unknown requests; send
1386285612Sdelphij	 * an error response for unknown resonses.
138782498Sroberto	 */
138882498Sroberto	default:
138982498Sroberto		if (opcode & CRYPTO_RESP)
1390182007Sroberto			rval = XEVNT_ERR;
139182498Sroberto	}
139282498Sroberto
139382498Sroberto	/*
1394182007Sroberto	 * In case of error, flame the log. If a request, toss the
1395182007Sroberto	 * puppy; if a response, return so the sender can flame, too.
1396132451Sroberto	 */
1397182007Sroberto	if (rval != XEVNT_OK) {
1398285612Sdelphij		u_int32	uint32;
1399285612Sdelphij
1400285612Sdelphij		uint32 = CRYPTO_ERROR;
1401285612Sdelphij		opcode |= uint32;
1402285612Sdelphij		fp->opcode |= htonl(uint32);
1403285612Sdelphij		snprintf(statstr, sizeof(statstr),
1404285612Sdelphij		    "%04x %d %02x %s", opcode, associd, rval,
1405285612Sdelphij		    eventstr(rval));
1406132451Sroberto		record_crypto_stats(srcadr_sin, statstr);
1407285612Sdelphij		DPRINTF(1, ("crypto_xmit: %s\n", statstr));
1408182007Sroberto		if (!(opcode & CRYPTO_RESP))
1409182007Sroberto			return (0);
1410132451Sroberto	}
1411285612Sdelphij	DPRINTF(1, ("crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n",
1412285612Sdelphij		    crypto_flags, start, len, opcode >> 16, associd));
141382498Sroberto	return (len);
141482498Sroberto}
141582498Sroberto
1416132451Sroberto
141782498Sroberto/*
1418285612Sdelphij * crypto_verify - verify the extension field value and signature
1419132451Sroberto *
1420132451Sroberto * Returns
1421132451Sroberto * XEVNT_OK	success
1422285612Sdelphij * XEVNT_ERR	protocol error
1423285612Sdelphij * XEVNT_FSP	bad filestamp
1424132451Sroberto * XEVNT_LEN	bad field format or length
1425132451Sroberto * XEVNT_PUB	bad or missing public key
1426132451Sroberto * XEVNT_SGL	bad signature length
1427132451Sroberto * XEVNT_SIG	signature not verified
1428285612Sdelphij * XEVNT_TSP	bad timestamp
142982498Sroberto */
1430132451Srobertostatic int
1431132451Srobertocrypto_verify(
1432132451Sroberto	struct exten *ep,	/* extension pointer */
1433132451Sroberto	struct value *vp,	/* value pointer */
1434132451Sroberto	struct peer *peer	/* peer structure pointer */
1435132451Sroberto	)
143682498Sroberto{
1437132451Sroberto	EVP_PKEY *pkey;		/* server public key */
1438309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
1439182007Sroberto	tstamp_t tstamp, tstamp1 = 0; /* timestamp */
1440182007Sroberto	tstamp_t fstamp, fstamp1 = 0; /* filestamp */
1441132451Sroberto	u_int	vallen;		/* value length */
1442132451Sroberto	u_int	siglen;		/* signature length */
1443132451Sroberto	u_int	opcode, len;
1444132451Sroberto	int	i;
144582498Sroberto
144682498Sroberto	/*
1447285612Sdelphij	 * We are extremely parannoyed. We require valid opcode, length,
1448285612Sdelphij	 * association ID, timestamp, filestamp, public key, digest,
1449285612Sdelphij	 * signature length and signature, where relevant. Note that
1450285612Sdelphij	 * preliminary length checks are done in the main loop.
145182498Sroberto	 */
1452132451Sroberto	len = ntohl(ep->opcode) & 0x0000ffff;
1453132451Sroberto	opcode = ntohl(ep->opcode) & 0xffff0000;
145482498Sroberto
145582498Sroberto	/*
1456285612Sdelphij	 * Check for valid value header, association ID and extension
1457285612Sdelphij	 * field length. Remember, it is not an error to receive an
1458285612Sdelphij	 * unsolicited response; however, the response ID must match
1459285612Sdelphij	 * the association ID.
146082498Sroberto	 */
1461132451Sroberto	if (opcode & CRYPTO_ERROR)
1462182007Sroberto		return (XEVNT_ERR);
1463182007Sroberto
1464285612Sdelphij 	if (len < VALUE_LEN)
1465285612Sdelphij		return (XEVNT_LEN);
1466285612Sdelphij
1467285612Sdelphij	if (opcode == (CRYPTO_AUTO | CRYPTO_RESP) && (peer->pmode ==
1468285612Sdelphij	    MODE_BROADCAST || (peer->cast_flags & MDF_BCLNT))) {
1469285612Sdelphij		if (ntohl(ep->associd) != peer->assoc)
1470285612Sdelphij			return (XEVNT_ERR);
1471132451Sroberto	} else {
1472285612Sdelphij		if (ntohl(ep->associd) != peer->associd)
1473285612Sdelphij			return (XEVNT_ERR);
1474132451Sroberto	}
1475182007Sroberto
1476132451Sroberto	/*
1477285612Sdelphij	 * We have a valid value header. Check for valid value and
1478285612Sdelphij	 * signature field lengths. The extension field length must be
1479285612Sdelphij	 * long enough to contain the value header, value and signature.
1480285612Sdelphij	 * Note both the value and signature field lengths are rounded
1481285612Sdelphij	 * up to the next word (4 octets).
1482132451Sroberto	 */
1483132451Sroberto	vallen = ntohl(ep->vallen);
1484281230Sdelphij	if (   vallen == 0
1485281230Sdelphij	    || vallen > MAX_VALLEN)
1486281230Sdelphij		return (XEVNT_LEN);
1487285612Sdelphij
1488132451Sroberto	i = (vallen + 3) / 4;
1489132451Sroberto	siglen = ntohl(ep->pkt[i++]);
1490281230Sdelphij	if (   siglen > MAX_VALLEN
1491281230Sdelphij	    || len - VALUE_LEN < ((vallen + 3) / 4) * 4
1492281230Sdelphij	    || len - VALUE_LEN - ((vallen + 3) / 4) * 4
1493281230Sdelphij	      < ((siglen + 3) / 4) * 4)
1494132451Sroberto		return (XEVNT_LEN);
1495132451Sroberto
1496182007Sroberto	/*
1497182007Sroberto	 * Check for valid timestamp and filestamp. If the timestamp is
1498182007Sroberto	 * zero, the sender is not synchronized and signatures are
1499285612Sdelphij	 * not possible. If nonzero the timestamp must not precede the
1500182007Sroberto	 * filestamp. The timestamp and filestamp must not precede the
1501285612Sdelphij	 * corresponding values in the value structure, if present.
1502285612Sdelphij 	 */
1503182007Sroberto	tstamp = ntohl(ep->tstamp);
1504182007Sroberto	fstamp = ntohl(ep->fstamp);
1505182007Sroberto	if (tstamp == 0)
1506285612Sdelphij		return (XEVNT_TSP);
1507182007Sroberto
1508182007Sroberto	if (tstamp < fstamp)
1509182007Sroberto		return (XEVNT_TSP);
1510182007Sroberto
1511182007Sroberto	if (vp != NULL) {
1512182007Sroberto		tstamp1 = ntohl(vp->tstamp);
1513182007Sroberto		fstamp1 = ntohl(vp->fstamp);
1514285612Sdelphij		if (tstamp1 != 0 && fstamp1 != 0) {
1515285612Sdelphij			if (tstamp < tstamp1)
1516285612Sdelphij				return (XEVNT_TSP);
1517182007Sroberto
1518285612Sdelphij			if ((tstamp < fstamp1 || fstamp < fstamp1))
1519285612Sdelphij				return (XEVNT_FSP);
1520285612Sdelphij		}
1521182007Sroberto	}
1522182007Sroberto
1523182007Sroberto	/*
1524285612Sdelphij	 * At the time the certificate message is validated, the public
1525285612Sdelphij	 * key in the message is not available. Thus, don't try to
1526285612Sdelphij	 * verify the signature.
1527285612Sdelphij	 */
1528285612Sdelphij	if (opcode == (CRYPTO_CERT | CRYPTO_RESP))
1529285612Sdelphij		return (XEVNT_OK);
1530285612Sdelphij
1531285612Sdelphij	/*
1532182007Sroberto	 * Check for valid signature length, public key and digest
1533182007Sroberto	 * algorithm.
1534182007Sroberto	 */
1535132451Sroberto	if (crypto_flags & peer->crypto & CRYPTO_FLAG_PRIV)
1536132451Sroberto		pkey = sign_pkey;
1537132451Sroberto	else
1538132451Sroberto		pkey = peer->pkey;
1539182007Sroberto	if (siglen == 0 || pkey == NULL || peer->digest == NULL)
1540285612Sdelphij		return (XEVNT_ERR);
1541132451Sroberto
1542182007Sroberto	if (siglen != (u_int)EVP_PKEY_size(pkey))
1543182007Sroberto		return (XEVNT_SGL);
1544182007Sroberto
1545132451Sroberto	/*
1546182007Sroberto	 * Darn, I thought we would never get here. Verify the
1547182007Sroberto	 * signature. If the identity exchange is verified, light the
1548285612Sdelphij	 * proventic bit. What a relief.
1549132451Sroberto	 */
1550309008Sdelphij	ctx = EVP_MD_CTX_new();
1551309008Sdelphij	EVP_VerifyInit(ctx, peer->digest);
1552281230Sdelphij	/* XXX: the "+ 12" needs to be at least documented... */
1553309008Sdelphij	EVP_VerifyUpdate(ctx, (u_char *)&ep->tstamp, vallen + 12);
1554309008Sdelphij	if (EVP_VerifyFinal(ctx, (u_char *)&ep->pkt[i], siglen,
1555309008Sdelphij	    pkey) <= 0) {
1556309008Sdelphij		EVP_MD_CTX_free(ctx);
1557182007Sroberto		return (XEVNT_SIG);
1558309008Sdelphij	}
1559309008Sdelphij	EVP_MD_CTX_free(ctx);
1560182007Sroberto
1561285612Sdelphij	if (peer->crypto & CRYPTO_FLAG_VRFY)
1562182007Sroberto		peer->crypto |= CRYPTO_FLAG_PROV;
1563182007Sroberto	return (XEVNT_OK);
1564132451Sroberto}
1565132451Sroberto
1566132451Sroberto
1567132451Sroberto/*
1568281230Sdelphij * crypto_encrypt - construct vp (encrypted cookie and signature) from
1569281230Sdelphij * the public key and cookie.
1570132451Sroberto *
1571281230Sdelphij * Returns:
1572132451Sroberto * XEVNT_OK	success
1573285612Sdelphij * XEVNT_CKY	bad or missing cookie
1574132451Sroberto * XEVNT_PUB	bad or missing public key
1575132451Sroberto */
1576132451Srobertostatic int
1577132451Srobertocrypto_encrypt(
1578281230Sdelphij	const u_char *ptr,	/* Public Key */
1579281230Sdelphij	u_int	vallen,		/* Length of Public Key */
1580281230Sdelphij	keyid_t	*cookie,	/* server cookie */
1581281230Sdelphij	struct value *vp	/* value pointer */
1582132451Sroberto	)
1583132451Sroberto{
1584132451Sroberto	EVP_PKEY *pkey;		/* public key */
1585309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
1586132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
1587132451Sroberto	u_int32	temp32;
1588285612Sdelphij	u_char *puch;
1589132451Sroberto
1590132451Sroberto	/*
1591132451Sroberto	 * Extract the public key from the request.
1592132451Sroberto	 */
1593281230Sdelphij	pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, vallen);
1594132451Sroberto	if (pkey == NULL) {
1595285612Sdelphij		msyslog(LOG_ERR, "crypto_encrypt: %s",
1596132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
1597132451Sroberto		return (XEVNT_PUB);
159882498Sroberto	}
159982498Sroberto
160082498Sroberto	/*
1601132451Sroberto	 * Encrypt the cookie, encode in ASN.1 and sign.
160282498Sroberto	 */
1603285612Sdelphij	memset(vp, 0, sizeof(struct value));
1604132451Sroberto	tstamp = crypto_time();
1605132451Sroberto	vp->tstamp = htonl(tstamp);
1606132451Sroberto	vp->fstamp = hostval.tstamp;
1607281230Sdelphij	vallen = EVP_PKEY_size(pkey);
1608281230Sdelphij	vp->vallen = htonl(vallen);
1609281230Sdelphij	vp->ptr = emalloc(vallen);
1610285612Sdelphij	puch = vp->ptr;
1611132451Sroberto	temp32 = htonl(*cookie);
1612285612Sdelphij	if (RSA_public_encrypt(4, (u_char *)&temp32, puch,
1613309008Sdelphij	    EVP_PKEY_get0_RSA(pkey), RSA_PKCS1_OAEP_PADDING) <= 0) {
1614285612Sdelphij		msyslog(LOG_ERR, "crypto_encrypt: %s",
1615132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
1616285612Sdelphij		free(vp->ptr);
1617132451Sroberto		EVP_PKEY_free(pkey);
1618132451Sroberto		return (XEVNT_CKY);
1619132451Sroberto	}
1620132451Sroberto	EVP_PKEY_free(pkey);
1621132451Sroberto	if (tstamp == 0)
1622132451Sroberto		return (XEVNT_OK);
1623182007Sroberto
1624132451Sroberto	vp->sig = emalloc(sign_siglen);
1625309008Sdelphij	ctx = EVP_MD_CTX_new();
1626309008Sdelphij	EVP_SignInit(ctx, sign_digest);
1627309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
1628309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, vallen);
1629309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &vallen, sign_pkey)) {
1630289997Sglebius		INSIST(vallen <= sign_siglen);
1631285612Sdelphij		vp->siglen = htonl(vallen);
1632285612Sdelphij	}
1633309008Sdelphij	EVP_MD_CTX_free(ctx);
1634132451Sroberto	return (XEVNT_OK);
1635132451Sroberto}
163682498Sroberto
1637132451Sroberto
1638132451Sroberto/*
1639132451Sroberto * crypto_ident - construct extension field for identity scheme
1640132451Sroberto *
1641132451Sroberto * This routine determines which identity scheme is in use and
1642132451Sroberto * constructs an extension field for that scheme.
1643285612Sdelphij *
1644285612Sdelphij * Returns
1645285612Sdelphij * CRYTPO_IFF	IFF scheme
1646285612Sdelphij * CRYPTO_GQ	GQ scheme
1647285612Sdelphij * CRYPTO_MV	MV scheme
1648285612Sdelphij * CRYPTO_NULL	no available scheme
1649132451Sroberto */
1650132451Srobertou_int
1651132451Srobertocrypto_ident(
1652132451Sroberto	struct peer *peer	/* peer structure pointer */
1653132451Sroberto	)
1654132451Sroberto{
1655285612Sdelphij	char		filename[MAXFILENAME];
1656285612Sdelphij	const char *	scheme_name;
1657285612Sdelphij	u_int		scheme_id;
1658132451Sroberto
165982498Sroberto	/*
1660285612Sdelphij	 * We come here after the group trusted host has been found; its
1661285612Sdelphij	 * name defines the group name. Search the key cache for all
1662285612Sdelphij	 * keys matching the same group name in order IFF, GQ and MV.
1663285612Sdelphij	 * Use the first one available.
166482498Sroberto	 */
1665285612Sdelphij	scheme_name = NULL;
1666132451Sroberto	if (peer->crypto & CRYPTO_FLAG_IFF) {
1667285612Sdelphij		scheme_name = "iff";
1668285612Sdelphij		scheme_id = CRYPTO_IFF;
1669285612Sdelphij	} else if (peer->crypto & CRYPTO_FLAG_GQ) {
1670285612Sdelphij		scheme_name = "gq";
1671285612Sdelphij		scheme_id = CRYPTO_GQ;
1672285612Sdelphij	} else if (peer->crypto & CRYPTO_FLAG_MV) {
1673285612Sdelphij		scheme_name = "mv";
1674285612Sdelphij		scheme_id = CRYPTO_MV;
1675132451Sroberto	}
1676132451Sroberto
1677285612Sdelphij	if (scheme_name != NULL) {
1678285612Sdelphij		snprintf(filename, sizeof(filename), "ntpkey_%spar_%s",
1679285612Sdelphij		    scheme_name, peer->ident);
1680285612Sdelphij		peer->ident_pkey = crypto_key(filename, NULL,
1681285612Sdelphij		    &peer->srcadr);
1682132451Sroberto		if (peer->ident_pkey != NULL)
1683285612Sdelphij			return scheme_id;
1684132451Sroberto	}
1685132451Sroberto
1686285612Sdelphij	msyslog(LOG_NOTICE,
1687285612Sdelphij	    "crypto_ident: no identity parameters found for group %s",
1688285612Sdelphij	    peer->ident);
1689285612Sdelphij
1690285612Sdelphij	return CRYPTO_NULL;
1691132451Sroberto}
169282498Sroberto
1693132451Sroberto
1694132451Sroberto/*
1695132451Sroberto * crypto_args - construct extension field from arguments
1696132451Sroberto *
1697132451Sroberto * This routine creates an extension field with current timestamps and
1698132451Sroberto * specified opcode, association ID and optional string. Note that the
1699132451Sroberto * extension field is created here, but freed after the crypto_xmit()
1700132451Sroberto * call in the protocol module.
1701132451Sroberto *
1702285612Sdelphij * Returns extension field pointer (no errors)
1703281230Sdelphij *
1704281230Sdelphij * XXX: opcode and len should really be 32-bit quantities and
1705281230Sdelphij * we should make sure that str is not too big.
1706132451Sroberto */
1707132451Srobertostruct exten *
1708132451Srobertocrypto_args(
1709132451Sroberto	struct peer *peer,	/* peer structure pointer */
1710132451Sroberto	u_int	opcode,		/* operation code */
1711285612Sdelphij	associd_t associd,	/* association ID */
1712132451Sroberto	char	*str		/* argument string */
1713132451Sroberto	)
1714132451Sroberto{
1715132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
1716132451Sroberto	struct exten *ep;	/* extension field pointer */
1717132451Sroberto	u_int	len;		/* extension field length */
1718285612Sdelphij	size_t	slen = 0;
1719132451Sroberto
1720132451Sroberto	tstamp = crypto_time();
1721132451Sroberto	len = sizeof(struct exten);
1722281230Sdelphij	if (str != NULL) {
1723281230Sdelphij		slen = strlen(str);
1724285612Sdelphij		INSIST(slen < MAX_VALLEN);
1725281230Sdelphij		len += slen;
1726281230Sdelphij	}
1727285612Sdelphij	ep = emalloc_zero(len);
1728182007Sroberto	if (opcode == 0)
1729182007Sroberto		return (ep);
1730182007Sroberto
1731285612Sdelphij	REQUIRE(0 == (len    & ~0x0000ffff));
1732285612Sdelphij	REQUIRE(0 == (opcode & ~0xffff0000));
1733285612Sdelphij
1734132451Sroberto	ep->opcode = htonl(opcode + len);
1735285612Sdelphij	ep->associd = htonl(associd);
1736132451Sroberto	ep->tstamp = htonl(tstamp);
1737132451Sroberto	ep->fstamp = hostval.tstamp;
1738132451Sroberto	ep->vallen = 0;
1739132451Sroberto	if (str != NULL) {
1740281230Sdelphij		ep->vallen = htonl(slen);
1741281230Sdelphij		memcpy((char *)ep->pkt, str, slen);
1742132451Sroberto	}
1743132451Sroberto	return (ep);
174482498Sroberto}
174582498Sroberto
174682498Sroberto
174782498Sroberto/*
1748132451Sroberto * crypto_send - construct extension field from value components
1749132451Sroberto *
1750285612Sdelphij * The value and signature fields are zero-padded to a word boundary.
1751285612Sdelphij * Note: it is not polite to send a nonempty signature with zero
1752285612Sdelphij * timestamp or a nonzero timestamp with an empty signature, but those
1753285612Sdelphij * rules are not enforced here.
1754281230Sdelphij *
1755281230Sdelphij * XXX This code won't work on a box with 16-bit ints.
175682498Sroberto */
1757285612Sdelphijint
1758132451Srobertocrypto_send(
1759132451Sroberto	struct exten *ep,	/* extension field pointer */
1760285612Sdelphij	struct value *vp,	/* value pointer */
1761285612Sdelphij	int	start		/* buffer offset */
1762132451Sroberto	)
176382498Sroberto{
1764285612Sdelphij	u_int	len, vallen, siglen, opcode;
1765285612Sdelphij	u_int	i, j;
176682498Sroberto
176782498Sroberto	/*
1768285612Sdelphij	 * Calculate extension field length and check for buffer
1769285612Sdelphij	 * overflow. Leave room for the MAC.
177082498Sroberto	 */
1771285612Sdelphij	len = 16;				/* XXX Document! */
1772285612Sdelphij	vallen = ntohl(vp->vallen);
1773285612Sdelphij	INSIST(vallen <= MAX_VALLEN);
1774285612Sdelphij	len += ((vallen + 3) / 4 + 1) * 4;
1775285612Sdelphij	siglen = ntohl(vp->siglen);
1776285612Sdelphij	len += ((siglen + 3) / 4 + 1) * 4;
1777285612Sdelphij	if (start + len > sizeof(struct pkt) - MAX_MAC_LEN)
1778285612Sdelphij		return (0);
1779285612Sdelphij
1780285612Sdelphij	/*
1781285612Sdelphij	 * Copy timestamps.
1782285612Sdelphij	 */
1783132451Sroberto	ep->tstamp = vp->tstamp;
1784132451Sroberto	ep->fstamp = vp->fstamp;
1785132451Sroberto	ep->vallen = vp->vallen;
1786132451Sroberto
1787132451Sroberto	/*
1788285612Sdelphij	 * Copy value. If the data field is empty or zero length,
1789285612Sdelphij	 * encode an empty value with length zero.
1790285612Sdelphij	 */
1791285612Sdelphij	i = 0;
1792285612Sdelphij	if (vallen > 0 && vp->ptr != NULL) {
1793285612Sdelphij		j = vallen / 4;
1794285612Sdelphij		if (j * 4 < vallen)
1795285612Sdelphij			ep->pkt[i + j++] = 0;
1796285612Sdelphij		memcpy(&ep->pkt[i], vp->ptr, vallen);
1797285612Sdelphij		i += j;
1798285612Sdelphij	}
1799285612Sdelphij
1800285612Sdelphij	/*
1801132451Sroberto	 * Copy signature. If the signature field is empty or zero
1802132451Sroberto	 * length, encode an empty signature with length zero.
1803132451Sroberto	 */
1804132451Sroberto	ep->pkt[i++] = vp->siglen;
1805285612Sdelphij	if (siglen > 0 && vp->sig != NULL) {
1806285612Sdelphij		j = siglen / 4;
1807285612Sdelphij		if (j * 4 < siglen)
1808285612Sdelphij			ep->pkt[i + j++] = 0;
1809285612Sdelphij		memcpy(&ep->pkt[i], vp->sig, siglen);
1810289997Sglebius		/* i += j; */	/* We don't use i after this */
1811285612Sdelphij	}
1812285612Sdelphij	opcode = ntohl(ep->opcode);
1813285612Sdelphij	ep->opcode = htonl((opcode & 0xffff0000) | len);
1814285612Sdelphij	ENSURE(len <= MAX_VALLEN);
1815132451Sroberto	return (len);
1816132451Sroberto}
1817132451Sroberto
1818132451Sroberto
1819132451Sroberto/*
1820132451Sroberto * crypto_update - compute new public value and sign extension fields
1821132451Sroberto *
1822132451Sroberto * This routine runs periodically, like once a day, and when something
1823132451Sroberto * changes. It updates the timestamps on three value structures and one
1824132451Sroberto * value structure list, then signs all the structures:
1825132451Sroberto *
1826132451Sroberto * hostval	host name (not signed)
1827132451Sroberto * pubkey	public key
1828132451Sroberto * cinfo	certificate info/value list
1829285612Sdelphij * tai_leap	leap values
1830132451Sroberto *
1831285612Sdelphij * Filestamps are proventic data, so this routine runs only when the
1832285612Sdelphij * host is synchronized to a proventicated source. Thus, the timestamp
1833285612Sdelphij * is proventic and can be used to deflect clogging attacks.
1834132451Sroberto *
1835132451Sroberto * Returns void (no errors)
1836132451Sroberto */
1837132451Srobertovoid
1838132451Srobertocrypto_update(void)
1839132451Sroberto{
1840309008Sdelphij	EVP_MD_CTX *ctx;	/* message digest context */
1841285612Sdelphij	struct cert_info *cp;	/* certificate info/value */
1842132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
1843285612Sdelphij	u_int32	*ptr;
1844132451Sroberto	u_int	len;
1845285612Sdelphij	leap_result_t leap_data;
1846132451Sroberto
1847285612Sdelphij	hostval.tstamp = htonl(crypto_time());
1848285612Sdelphij	if (hostval.tstamp == 0)
184982498Sroberto		return;
1850182007Sroberto
1851309008Sdelphij	ctx = EVP_MD_CTX_new();
1852309008Sdelphij
185382498Sroberto	/*
1854132451Sroberto	 * Sign public key and timestamps. The filestamp is derived from
1855132451Sroberto	 * the host key file extension from wherever the file was
1856132451Sroberto	 * generated.
185782498Sroberto	 */
1858132451Sroberto	if (pubkey.vallen != 0) {
1859132451Sroberto		pubkey.tstamp = hostval.tstamp;
1860132451Sroberto		pubkey.siglen = 0;
1861132451Sroberto		if (pubkey.sig == NULL)
1862132451Sroberto			pubkey.sig = emalloc(sign_siglen);
1863309008Sdelphij		EVP_SignInit(ctx, sign_digest);
1864309008Sdelphij		EVP_SignUpdate(ctx, (u_char *)&pubkey, 12);
1865309008Sdelphij		EVP_SignUpdate(ctx, pubkey.ptr, ntohl(pubkey.vallen));
1866309008Sdelphij		if (EVP_SignFinal(ctx, pubkey.sig, &len, sign_pkey)) {
1867289997Sglebius			INSIST(len <= sign_siglen);
1868132451Sroberto			pubkey.siglen = htonl(len);
1869285612Sdelphij		}
187082498Sroberto	}
187182498Sroberto
187282498Sroberto	/*
1873132451Sroberto	 * Sign certificates and timestamps. The filestamp is derived
1874132451Sroberto	 * from the certificate file extension from wherever the file
1875182007Sroberto	 * was generated. Note we do not throw expired certificates
1876182007Sroberto	 * away; they may have signed younger ones.
187782498Sroberto	 */
1878285612Sdelphij	for (cp = cinfo; cp != NULL; cp = cp->link) {
1879182007Sroberto		cp->cert.tstamp = hostval.tstamp;
1880182007Sroberto		cp->cert.siglen = 0;
1881182007Sroberto		if (cp->cert.sig == NULL)
1882182007Sroberto			cp->cert.sig = emalloc(sign_siglen);
1883309008Sdelphij		EVP_SignInit(ctx, sign_digest);
1884309008Sdelphij		EVP_SignUpdate(ctx, (u_char *)&cp->cert, 12);
1885309008Sdelphij		EVP_SignUpdate(ctx, cp->cert.ptr,
1886182007Sroberto		    ntohl(cp->cert.vallen));
1887309008Sdelphij		if (EVP_SignFinal(ctx, cp->cert.sig, &len, sign_pkey)) {
1888289997Sglebius			INSIST(len <= sign_siglen);
1889182007Sroberto			cp->cert.siglen = htonl(len);
1890285612Sdelphij		}
189182498Sroberto	}
189282498Sroberto
189382498Sroberto	/*
1894285612Sdelphij	 * Sign leapseconds values and timestamps. Note it is not an
1895285612Sdelphij	 * error to return null values.
189682498Sroberto	 */
1897285612Sdelphij	tai_leap.tstamp = hostval.tstamp;
1898285612Sdelphij	tai_leap.fstamp = hostval.fstamp;
1899285612Sdelphij
1900285612Sdelphij	/* Get the leap second era. We might need a full lookup early
1901285612Sdelphij	 * after start, when the cache is not yet loaded.
1902285612Sdelphij	 */
1903285612Sdelphij	leapsec_frame(&leap_data);
1904285612Sdelphij	if ( ! memcmp(&leap_data.ebase, &leap_data.ttime, sizeof(vint64))) {
1905285612Sdelphij		time_t   now    = time(NULL);
1906285612Sdelphij		uint32_t nowntp = (uint32_t)now + JAN_1970;
1907285612Sdelphij		leapsec_query(&leap_data, nowntp, &now);
190882498Sroberto	}
1909285612Sdelphij
1910285612Sdelphij	/* Create the data block. The protocol does not work without. */
1911285612Sdelphij	len = 3 * sizeof(u_int32);
1912285612Sdelphij	if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) {
1913285612Sdelphij		free(tai_leap.ptr);
1914285612Sdelphij		tai_leap.ptr = emalloc(len);
1915285612Sdelphij		tai_leap.vallen = htonl(len);
1916285612Sdelphij	}
1917285612Sdelphij	ptr = (u_int32 *)tai_leap.ptr;
1918285612Sdelphij	if (leap_data.tai_offs > 10) {
1919285612Sdelphij		/* create a TAI / leap era block. The end time is a
1920285612Sdelphij		 * fake -- maybe we can do better.
1921285612Sdelphij		 */
1922285612Sdelphij		ptr[0] = htonl(leap_data.tai_offs);
1923285612Sdelphij		ptr[1] = htonl(leap_data.ebase.d_s.lo);
1924285612Sdelphij		if (leap_data.ttime.d_s.hi >= 0)
1925285612Sdelphij			ptr[2] = htonl(leap_data.ttime.D_s.lo +  7*86400);
1926285612Sdelphij		else
1927285612Sdelphij			ptr[2] = htonl(leap_data.ebase.D_s.lo + 25*86400);
1928285612Sdelphij	} else {
1929285612Sdelphij		/* no leap era available */
1930285612Sdelphij		memset(ptr, 0, len);
1931285612Sdelphij	}
1932285612Sdelphij	if (tai_leap.sig == NULL)
1933285612Sdelphij		tai_leap.sig = emalloc(sign_siglen);
1934309008Sdelphij	EVP_SignInit(ctx, sign_digest);
1935309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&tai_leap, 12);
1936309008Sdelphij	EVP_SignUpdate(ctx, tai_leap.ptr, len);
1937309008Sdelphij	if (EVP_SignFinal(ctx, tai_leap.sig, &len, sign_pkey)) {
1938289997Sglebius		INSIST(len <= sign_siglen);
1939285612Sdelphij		tai_leap.siglen = htonl(len);
1940285612Sdelphij	}
1941285612Sdelphij	crypto_flags |= CRYPTO_FLAG_TAI;
1942285612Sdelphij
1943285612Sdelphij	snprintf(statstr, sizeof(statstr), "signature update ts %u",
1944285612Sdelphij	    ntohl(hostval.tstamp));
1945132451Sroberto	record_crypto_stats(NULL, statstr);
1946285612Sdelphij	DPRINTF(1, ("crypto_update: %s\n", statstr));
1947309008Sdelphij	EVP_MD_CTX_free(ctx);
194882498Sroberto}
194982498Sroberto
1950285612Sdelphij/*
1951285612Sdelphij * crypto_update_taichange - eventually trigger crypto_update
1952285612Sdelphij *
1953285612Sdelphij * This is called when a change in 'sys_tai' is detected. This will
1954285612Sdelphij * happen shortly after a leap second is detected, but unhappily also
1955285612Sdelphij * early after system start; also, the crypto stuff might be unused and
1956285612Sdelphij * an unguarded call to crypto_update() causes a crash.
1957285612Sdelphij *
1958285612Sdelphij * This function makes sure that there already *is* a valid crypto block
1959285612Sdelphij * for the use with autokey, and only calls 'crypto_update()' if it can
1960285612Sdelphij * succeed.
1961285612Sdelphij *
1962285612Sdelphij * Returns void (no errors)
1963285612Sdelphij */
1964285612Sdelphijvoid
1965285612Sdelphijcrypto_update_taichange(void)
1966285612Sdelphij{
1967285612Sdelphij	static const u_int len = 3 * sizeof(u_int32);
196882498Sroberto
1969285612Sdelphij	/* check if the signing digest algo is available */
1970285612Sdelphij	if (sign_digest == NULL || sign_pkey == NULL)
1971285612Sdelphij		return;
1972285612Sdelphij
1973285612Sdelphij	/* check size of TAI extension block */
1974285612Sdelphij	if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len)
1975285612Sdelphij		return;
1976285612Sdelphij
1977285612Sdelphij	/* crypto_update should at least not crash here! */
1978285612Sdelphij	crypto_update();
1979285612Sdelphij}
1980285612Sdelphij
198182498Sroberto/*
1982132451Sroberto * value_free - free value structure components.
1983132451Sroberto *
1984132451Sroberto * Returns void (no errors)
198582498Sroberto */
1986132451Srobertovoid
1987132451Srobertovalue_free(
1988132451Sroberto	struct value *vp	/* value structure */
198982498Sroberto	)
199082498Sroberto{
1991132451Sroberto	if (vp->ptr != NULL)
1992132451Sroberto		free(vp->ptr);
1993132451Sroberto	if (vp->sig != NULL)
1994132451Sroberto		free(vp->sig);
1995132451Sroberto	memset(vp, 0, sizeof(struct value));
1996132451Sroberto}
199782498Sroberto
1998132451Sroberto
1999132451Sroberto/*
2000285612Sdelphij * crypto_time - returns current NTP time.
2001285612Sdelphij *
2002285612Sdelphij * Returns NTP seconds if in synch, 0 otherwise
2003132451Sroberto */
2004132451Srobertotstamp_t
2005132451Srobertocrypto_time()
2006132451Sroberto{
2007285612Sdelphij	l_fp	tstamp;		/* NTP time */
2008132451Sroberto
2009132451Sroberto	L_CLR(&tstamp);
2010132451Sroberto	if (sys_leap != LEAP_NOTINSYNC)
2011132451Sroberto		get_systime(&tstamp);
2012132451Sroberto	return (tstamp.l_ui);
2013132451Sroberto}
2014132451Sroberto
2015132451Sroberto
2016132451Sroberto/*
2017285612Sdelphij * asn_to_calendar - convert ASN1_TIME time structure to struct calendar.
2018285612Sdelphij *
2019132451Sroberto */
2020285612Sdelphijstatic
2021285612Sdelphijvoid
2022285612Sdelphijasn_to_calendar	(
2023316069Sdelphij	const ASN1_TIME *asn1time,	/* pointer to ASN1_TIME structure */
2024285612Sdelphij	struct calendar *pjd	/* pointer to result */
2025132451Sroberto	)
2026132451Sroberto{
2027285612Sdelphij	size_t	len;		/* length of ASN1_TIME string */
2028285612Sdelphij	char	v[24];		/* writable copy of ASN1_TIME string */
2029285612Sdelphij	unsigned long	temp;	/* result from strtoul */
2030132451Sroberto
203182498Sroberto	/*
2032132451Sroberto	 * Extract time string YYMMDDHHMMSSZ from ASN1 time structure.
2033285612Sdelphij	 * Or YYYYMMDDHHMMSSZ.
2034132451Sroberto	 * Note that the YY, MM, DD fields start with one, the HH, MM,
2035285612Sdelphij	 * SS fields start with zero and the Z character is ignored.
2036285612Sdelphij	 * Also note that two-digit years less than 50 map to years greater than
2037285612Sdelphij	 * 100. Dontcha love ASN.1? Better than MIL-188.
203882498Sroberto	 */
2039285612Sdelphij	len = asn1time->length;
2040289997Sglebius	REQUIRE(len < sizeof(v));
2041285612Sdelphij	(void)strncpy(v, (char *)(asn1time->data), len);
2042289997Sglebius	REQUIRE(len >= 13);
2043285612Sdelphij	temp = strtoul(v+len-3, NULL, 10);
2044285612Sdelphij	pjd->second = temp;
2045285612Sdelphij	v[len-3] = '\0';
2046182007Sroberto
2047285612Sdelphij	temp = strtoul(v+len-5, NULL, 10);
2048285612Sdelphij	pjd->minute = temp;
2049285612Sdelphij	v[len-5] = '\0';
2050285612Sdelphij
2051285612Sdelphij	temp = strtoul(v+len-7, NULL, 10);
2052285612Sdelphij	pjd->hour = temp;
2053285612Sdelphij	v[len-7] = '\0';
2054285612Sdelphij
2055285612Sdelphij	temp = strtoul(v+len-9, NULL, 10);
2056285612Sdelphij	pjd->monthday = temp;
2057285612Sdelphij	v[len-9] = '\0';
2058285612Sdelphij
2059285612Sdelphij	temp = strtoul(v+len-11, NULL, 10);
2060285612Sdelphij	pjd->month = temp;
2061285612Sdelphij	v[len-11] = '\0';
2062285612Sdelphij
2063285612Sdelphij	temp = strtoul(v, NULL, 10);
2064285612Sdelphij	/* handle two-digit years */
2065285612Sdelphij	if (temp < 50UL)
2066285612Sdelphij	    temp += 100UL;
2067285612Sdelphij	if (temp < 150UL)
2068285612Sdelphij	    temp += 1900UL;
2069285612Sdelphij	pjd->year = temp;
2070285612Sdelphij
2071285612Sdelphij	pjd->yearday = pjd->weekday = 0;
2072285612Sdelphij	return;
2073132451Sroberto}
2074132451Sroberto
2075132451Sroberto
2076132451Sroberto/*
2077132451Sroberto * bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number.
2078285612Sdelphij *
2079285612Sdelphij * Returns void (no errors)
2080132451Sroberto */
2081285612Sdelphijstatic void
2082132451Srobertobighash(
2083132451Sroberto	BIGNUM	*bn,		/* BIGNUM * from */
2084132451Sroberto	BIGNUM	*bk		/* BIGNUM * to */
2085132451Sroberto	)
2086132451Sroberto{
2087309008Sdelphij	EVP_MD_CTX *ctx;	/* message digest context */
2088132451Sroberto	u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
2089132451Sroberto	u_char	*ptr;		/* a BIGNUM as binary string */
2090132451Sroberto	u_int	len;
2091132451Sroberto
2092132451Sroberto	len = BN_num_bytes(bn);
2093132451Sroberto	ptr = emalloc(len);
2094132451Sroberto	BN_bn2bin(bn, ptr);
2095309008Sdelphij	ctx = EVP_MD_CTX_new();
2096330141Sdelphij#   if defined(OPENSSL) && defined(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW)
2097330141Sdelphij	/* [Bug 3457] set flags and don't kill them again */
2098330141Sdelphij	EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
2099330141Sdelphij	EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
2100330141Sdelphij#   else
2101309008Sdelphij	EVP_DigestInit(ctx, EVP_md5());
2102330141Sdelphij#   endif
2103309008Sdelphij	EVP_DigestUpdate(ctx, ptr, len);
2104309008Sdelphij	EVP_DigestFinal(ctx, dgst, &len);
2105309008Sdelphij	EVP_MD_CTX_free(ctx);
2106132451Sroberto	BN_bin2bn(dgst, len, bk);
2107285612Sdelphij	free(ptr);
2108132451Sroberto}
2109132451Sroberto
2110132451Sroberto
2111132451Sroberto/*
2112132451Sroberto ***********************************************************************
2113132451Sroberto *								       *
2114132451Sroberto * The following routines implement the Schnorr (IFF) identity scheme  *
2115132451Sroberto *								       *
2116132451Sroberto ***********************************************************************
2117132451Sroberto *
2118132451Sroberto * The Schnorr (IFF) identity scheme is intended for use when
2119285612Sdelphij * certificates are generated by some other trusted certificate
2120285612Sdelphij * authority and the certificate cannot be used to convey public
2121285612Sdelphij * parameters. There are two kinds of files: encrypted server files that
2122285612Sdelphij * contain private and public values and nonencrypted client files that
2123285612Sdelphij * contain only public values. New generations of server files must be
2124285612Sdelphij * securely transmitted to all servers of the group; client files can be
2125285612Sdelphij * distributed by any means. The scheme is self contained and
2126285612Sdelphij * independent of new generations of host keys, sign keys and
2127285612Sdelphij * certificates.
2128132451Sroberto *
2129285612Sdelphij * The IFF values hide in a DSA cuckoo structure which uses the same
2130285612Sdelphij * parameters. The values are used by an identity scheme based on DSA
2131285612Sdelphij * cryptography and described in Stimson p. 285. The p is a 512-bit
2132285612Sdelphij * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1
2133285612Sdelphij * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a
2134285612Sdelphij * private random group key b (0 < b < q) and public key v = g^b, then
2135285612Sdelphij * sends (p, q, g, b) to the servers and (p, q, g, v) to the clients.
2136285612Sdelphij * Alice challenges Bob to confirm identity using the protocol described
2137285612Sdelphij * below.
2138132451Sroberto *
2139132451Sroberto * How it works
2140132451Sroberto *
2141132451Sroberto * The scheme goes like this. Both Alice and Bob have the public primes
2142132451Sroberto * p, q and generator g. The TA gives private key b to Bob and public
2143285612Sdelphij * key v to Alice.
2144132451Sroberto *
2145285612Sdelphij * Alice rolls new random challenge r (o < r < q) and sends to Bob in
2146285612Sdelphij * the IFF request message. Bob rolls new random k (0 < k < q), then
2147285612Sdelphij * computes y = k + b r mod q and x = g^k mod p and sends (y, hash(x))
2148285612Sdelphij * to Alice in the response message. Besides making the response
2149285612Sdelphij * shorter, the hash makes it effectivey impossible for an intruder to
2150285612Sdelphij * solve for b by observing a number of these messages.
2151132451Sroberto *
2152132451Sroberto * Alice receives the response and computes g^y v^r mod p. After a bit
2153132451Sroberto * of algebra, this simplifies to g^k. If the hash of this result
2154132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed
2155132451Sroberto * response binds this knowledge to Bob's private key and the public key
2156132451Sroberto * previously received in his certificate.
2157132451Sroberto *
2158132451Sroberto * crypto_alice - construct Alice's challenge in IFF scheme
2159132451Sroberto *
2160132451Sroberto * Returns
2161132451Sroberto * XEVNT_OK	success
2162285612Sdelphij * XEVNT_ID	bad or missing group key
2163132451Sroberto * XEVNT_PUB	bad or missing public key
2164132451Sroberto */
2165132451Srobertostatic int
2166132451Srobertocrypto_alice(
2167132451Sroberto	struct peer *peer,	/* peer pointer */
2168132451Sroberto	struct value *vp	/* value pointer */
2169132451Sroberto	)
2170132451Sroberto{
2171132451Sroberto	DSA	*dsa;		/* IFF parameters */
2172132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2173309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2174132451Sroberto	tstamp_t tstamp;
2175132451Sroberto	u_int	len;
2176309008Sdelphij	const BIGNUM *q;
2177132451Sroberto
2178132451Sroberto	/*
2179132451Sroberto	 * The identity parameters must have correct format and content.
2180132451Sroberto	 */
2181285612Sdelphij	if (peer->ident_pkey == NULL) {
2182285612Sdelphij		msyslog(LOG_NOTICE, "crypto_alice: scheme unavailable");
2183132451Sroberto		return (XEVNT_ID);
2184285612Sdelphij	}
2185182007Sroberto
2186309008Sdelphij	if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) {
2187285612Sdelphij		msyslog(LOG_NOTICE, "crypto_alice: defective key");
2188132451Sroberto		return (XEVNT_PUB);
2189132451Sroberto	}
2190132451Sroberto
2191132451Sroberto	/*
2192285612Sdelphij	 * Roll new random r (0 < r < q).
2193132451Sroberto	 */
2194132451Sroberto	if (peer->iffval != NULL)
2195132451Sroberto		BN_free(peer->iffval);
2196132451Sroberto	peer->iffval = BN_new();
2197309008Sdelphij	DSA_get0_pqg(dsa, NULL, &q, NULL);
2198309008Sdelphij	len = BN_num_bytes(q);
2199285612Sdelphij	BN_rand(peer->iffval, len * 8, -1, 1);	/* r mod q*/
2200285612Sdelphij	bctx = BN_CTX_new();
2201309008Sdelphij	BN_mod(peer->iffval, peer->iffval, q, bctx);
2202132451Sroberto	BN_CTX_free(bctx);
2203132451Sroberto
2204132451Sroberto	/*
2205132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2206132451Sroberto	 */
2207285612Sdelphij	memset(vp, 0, sizeof(struct value));
2208132451Sroberto	tstamp = crypto_time();
2209132451Sroberto	vp->tstamp = htonl(tstamp);
2210285612Sdelphij	vp->fstamp = htonl(peer->ident_pkey->fstamp);
2211132451Sroberto	vp->vallen = htonl(len);
2212132451Sroberto	vp->ptr = emalloc(len);
2213132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2214132451Sroberto	if (tstamp == 0)
2215132451Sroberto		return (XEVNT_OK);
2216182007Sroberto
2217132451Sroberto	vp->sig = emalloc(sign_siglen);
2218309008Sdelphij	ctx = EVP_MD_CTX_new();
2219309008Sdelphij	EVP_SignInit(ctx, sign_digest);
2220309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
2221309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
2222309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
2223289997Sglebius		INSIST(len <= sign_siglen);
2224132451Sroberto		vp->siglen = htonl(len);
2225285612Sdelphij	}
2226309008Sdelphij	EVP_MD_CTX_free(ctx);
2227132451Sroberto	return (XEVNT_OK);
2228132451Sroberto}
2229132451Sroberto
2230132451Sroberto
2231132451Sroberto/*
2232132451Sroberto * crypto_bob - construct Bob's response to Alice's challenge
2233132451Sroberto *
2234132451Sroberto * Returns
2235132451Sroberto * XEVNT_OK	success
2236285612Sdelphij * XEVNT_ERR	protocol error
2237182007Sroberto * XEVNT_ID	bad or missing group key
2238132451Sroberto */
2239132451Srobertostatic int
2240132451Srobertocrypto_bob(
2241132451Sroberto	struct exten *ep,	/* extension pointer */
2242132451Sroberto	struct value *vp	/* value pointer */
2243132451Sroberto	)
2244132451Sroberto{
2245132451Sroberto	DSA	*dsa;		/* IFF parameters */
2246132451Sroberto	DSA_SIG	*sdsa;		/* DSA signature context fake */
2247132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2248309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2249132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2250132451Sroberto	BIGNUM	*bn, *bk, *r;
2251132451Sroberto	u_char	*ptr;
2252289997Sglebius	u_int	len;		/* extension field value length */
2253309008Sdelphij	const BIGNUM *p, *q, *g;
2254309008Sdelphij	const BIGNUM *priv_key;
2255132451Sroberto
2256132451Sroberto	/*
2257132451Sroberto	 * If the IFF parameters are not valid, something awful
2258132451Sroberto	 * happened or we are being tormented.
2259132451Sroberto	 */
2260285612Sdelphij	if (iffkey_info == NULL) {
2261285612Sdelphij		msyslog(LOG_NOTICE, "crypto_bob: scheme unavailable");
2262182007Sroberto		return (XEVNT_ID);
2263132451Sroberto	}
2264309008Sdelphij	dsa = EVP_PKEY_get0_DSA(iffkey_info->pkey);
2265309008Sdelphij	DSA_get0_pqg(dsa, &p, &q, &g);
2266309008Sdelphij	DSA_get0_key(dsa, NULL, &priv_key);
2267132451Sroberto
2268132451Sroberto	/*
2269132451Sroberto	 * Extract r from the challenge.
2270132451Sroberto	 */
2271289997Sglebius	len = exten_payload_size(ep);
2272289997Sglebius	if (len == 0 || len > MAX_VALLEN)
2273289997Sglebius		return (XEVNT_LEN);
2274289997Sglebius	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2275285612Sdelphij		msyslog(LOG_ERR, "crypto_bob: %s",
2276132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2277182007Sroberto		return (XEVNT_ERR);
2278132451Sroberto	}
2279132451Sroberto
2280132451Sroberto	/*
2281132451Sroberto	 * Bob rolls random k (0 < k < q), computes y = k + b r mod q
2282132451Sroberto	 * and x = g^k mod p, then sends (y, hash(x)) to Alice.
2283132451Sroberto	 */
2284132451Sroberto	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
2285132451Sroberto	sdsa = DSA_SIG_new();
2286289997Sglebius	BN_rand(bk, len * 8, -1, 1);		/* k */
2287309008Sdelphij	BN_mod_mul(bn, priv_key, r, q, bctx); /* b r mod q */
2288132451Sroberto	BN_add(bn, bn, bk);
2289309008Sdelphij	BN_mod(bn, bn, q, bctx);		/* k + b r mod q */
2290309008Sdelphij	BN_mod_exp(bk, g, bk, p, bctx); /* g^k mod p */
2291132451Sroberto	bighash(bk, bk);
2292309008Sdelphij	DSA_SIG_set0(sdsa, bn, bk);
2293132451Sroberto	BN_CTX_free(bctx);
2294309008Sdelphij	BN_free(r);
2295285612Sdelphij#ifdef DEBUG
2296285612Sdelphij	if (debug > 1)
2297285612Sdelphij		DSA_print_fp(stdout, dsa, 0);
2298285612Sdelphij#endif
2299132451Sroberto
2300132451Sroberto	/*
2301285612Sdelphij	 * Encode the values in ASN.1 and sign. The filestamp is from
2302285612Sdelphij	 * the local file.
2303132451Sroberto	 */
2304289997Sglebius	len = i2d_DSA_SIG(sdsa, NULL);
2305289997Sglebius	if (len == 0) {
2306285612Sdelphij		msyslog(LOG_ERR, "crypto_bob: %s",
2307132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2308132451Sroberto		DSA_SIG_free(sdsa);
2309182007Sroberto		return (XEVNT_ERR);
2310132451Sroberto	}
2311289997Sglebius	if (len > MAX_VALLEN) {
2312289997Sglebius		msyslog(LOG_ERR, "crypto_bob: signature is too big: %u",
2313289997Sglebius		    len);
2314281230Sdelphij		DSA_SIG_free(sdsa);
2315281230Sdelphij		return (XEVNT_LEN);
2316281230Sdelphij	}
2317281230Sdelphij	memset(vp, 0, sizeof(struct value));
2318281230Sdelphij	tstamp = crypto_time();
2319281230Sdelphij	vp->tstamp = htonl(tstamp);
2320285612Sdelphij	vp->fstamp = htonl(iffkey_info->fstamp);
2321289997Sglebius	vp->vallen = htonl(len);
2322289997Sglebius	ptr = emalloc(len);
2323132451Sroberto	vp->ptr = ptr;
2324132451Sroberto	i2d_DSA_SIG(sdsa, &ptr);
2325132451Sroberto	DSA_SIG_free(sdsa);
2326132451Sroberto	if (tstamp == 0)
2327132451Sroberto		return (XEVNT_OK);
2328182007Sroberto
2329281230Sdelphij	/* XXX: more validation to make sure the sign fits... */
2330132451Sroberto	vp->sig = emalloc(sign_siglen);
2331309008Sdelphij	ctx = EVP_MD_CTX_new();
2332309008Sdelphij	EVP_SignInit(ctx, sign_digest);
2333309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
2334309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
2335309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
2336289997Sglebius		INSIST(len <= sign_siglen);
2337289997Sglebius		vp->siglen = htonl(len);
2338285612Sdelphij	}
2339309008Sdelphij	EVP_MD_CTX_free(ctx);
2340132451Sroberto	return (XEVNT_OK);
2341132451Sroberto}
2342132451Sroberto
2343132451Sroberto
2344132451Sroberto/*
2345132451Sroberto * crypto_iff - verify Bob's response to Alice's challenge
2346132451Sroberto *
2347132451Sroberto * Returns
2348132451Sroberto * XEVNT_OK	success
2349285612Sdelphij * XEVNT_FSP	bad filestamp
2350285612Sdelphij * XEVNT_ID	bad or missing group key
2351132451Sroberto * XEVNT_PUB	bad or missing public key
2352132451Sroberto */
2353132451Srobertoint
2354132451Srobertocrypto_iff(
2355132451Sroberto	struct exten *ep,	/* extension pointer */
2356132451Sroberto	struct peer *peer	/* peer structure pointer */
2357132451Sroberto	)
2358132451Sroberto{
2359132451Sroberto	DSA	*dsa;		/* IFF parameters */
2360132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2361132451Sroberto	DSA_SIG	*sdsa;		/* DSA parameters */
2362132451Sroberto	BIGNUM	*bn, *bk;
2363132451Sroberto	u_int	len;
2364285612Sdelphij	const u_char *ptr;
2365132451Sroberto	int	temp;
2366309008Sdelphij	const BIGNUM *p, *g;
2367309008Sdelphij	const BIGNUM *r, *s;
2368309008Sdelphij	const BIGNUM *pub_key;
2369132451Sroberto
2370132451Sroberto	/*
2371132451Sroberto	 * If the IFF parameters are not valid or no challenge was sent,
2372132451Sroberto	 * something awful happened or we are being tormented.
2373132451Sroberto	 */
2374132451Sroberto	if (peer->ident_pkey == NULL) {
2375285612Sdelphij		msyslog(LOG_NOTICE, "crypto_iff: scheme unavailable");
2376182007Sroberto		return (XEVNT_ID);
2377132451Sroberto	}
2378285612Sdelphij	if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) {
2379285612Sdelphij		msyslog(LOG_NOTICE, "crypto_iff: invalid filestamp %u",
2380132451Sroberto		    ntohl(ep->fstamp));
2381132451Sroberto		return (XEVNT_FSP);
2382132451Sroberto	}
2383309008Sdelphij	if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) {
2384285612Sdelphij		msyslog(LOG_NOTICE, "crypto_iff: defective key");
2385132451Sroberto		return (XEVNT_PUB);
2386132451Sroberto	}
2387132451Sroberto	if (peer->iffval == NULL) {
2388285612Sdelphij		msyslog(LOG_NOTICE, "crypto_iff: missing challenge");
2389182007Sroberto		return (XEVNT_ID);
2390132451Sroberto	}
2391132451Sroberto
2392132451Sroberto	/*
2393132451Sroberto	 * Extract the k + b r and g^k values from the response.
2394132451Sroberto	 */
2395132451Sroberto	bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
2396132451Sroberto	len = ntohl(ep->vallen);
2397285612Sdelphij	ptr = (u_char *)ep->pkt;
2398132451Sroberto	if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
2399285612Sdelphij		BN_free(bn); BN_free(bk); BN_CTX_free(bctx);
2400285612Sdelphij		msyslog(LOG_ERR, "crypto_iff: %s",
2401132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2402182007Sroberto		return (XEVNT_ERR);
2403132451Sroberto	}
2404132451Sroberto
2405132451Sroberto	/*
2406132451Sroberto	 * Compute g^(k + b r) g^(q - b)r mod p.
2407132451Sroberto	 */
2408309008Sdelphij	DSA_get0_key(dsa, &pub_key, NULL);
2409309008Sdelphij	DSA_get0_pqg(dsa, &p, NULL, &g);
2410309008Sdelphij	DSA_SIG_get0(sdsa, &r, &s);
2411309008Sdelphij	BN_mod_exp(bn, pub_key, peer->iffval, p, bctx);
2412309008Sdelphij	BN_mod_exp(bk, g, r, p, bctx);
2413309008Sdelphij	BN_mod_mul(bn, bn, bk, p, bctx);
2414132451Sroberto
2415132451Sroberto	/*
2416132451Sroberto	 * Verify the hash of the result matches hash(x).
2417132451Sroberto	 */
2418132451Sroberto	bighash(bn, bn);
2419309008Sdelphij	temp = BN_cmp(bn, s);
2420132451Sroberto	BN_free(bn); BN_free(bk); BN_CTX_free(bctx);
2421132451Sroberto	BN_free(peer->iffval);
2422132451Sroberto	peer->iffval = NULL;
2423132451Sroberto	DSA_SIG_free(sdsa);
2424132451Sroberto	if (temp == 0)
2425132451Sroberto		return (XEVNT_OK);
2426182007Sroberto
2427285612Sdelphij	msyslog(LOG_NOTICE, "crypto_iff: identity not verified");
2428285612Sdelphij	return (XEVNT_ID);
2429132451Sroberto}
2430132451Sroberto
2431132451Sroberto
2432132451Sroberto/*
2433132451Sroberto ***********************************************************************
2434132451Sroberto *								       *
2435132451Sroberto * The following routines implement the Guillou-Quisquater (GQ)        *
2436132451Sroberto * identity scheme                                                     *
2437132451Sroberto *								       *
2438132451Sroberto ***********************************************************************
2439132451Sroberto *
2440132451Sroberto * The Guillou-Quisquater (GQ) identity scheme is intended for use when
2441285612Sdelphij * the certificate can be used to convey public parameters. The scheme
2442285612Sdelphij * uses a X509v3 certificate extension field do convey the public key of
2443285612Sdelphij * a private key known only to servers. There are two kinds of files:
2444285612Sdelphij * encrypted server files that contain private and public values and
2445285612Sdelphij * nonencrypted client files that contain only public values. New
2446285612Sdelphij * generations of server files must be securely transmitted to all
2447285612Sdelphij * servers of the group; client files can be distributed by any means.
2448285612Sdelphij * The scheme is self contained and independent of new generations of
2449285612Sdelphij * host keys and sign keys. The scheme is self contained and independent
2450285612Sdelphij * of new generations of host keys and sign keys.
2451132451Sroberto *
2452285612Sdelphij * The GQ parameters hide in a RSA cuckoo structure which uses the same
2453285612Sdelphij * parameters. The values are used by an identity scheme based on RSA
2454285612Sdelphij * cryptography and described in Stimson p. 300 (with errors). The 512-
2455285612Sdelphij * bit public modulus is n = p q, where p and q are secret large primes.
2456285612Sdelphij * The TA rolls private random group key b as RSA exponent. These values
2457285612Sdelphij * are known to all group members.
2458132451Sroberto *
2459285612Sdelphij * When rolling new certificates, a server recomputes the private and
2460132451Sroberto * public keys. The private key u is a random roll, while the public key
2461132451Sroberto * is the inverse obscured by the group key v = (u^-1)^b. These values
2462132451Sroberto * replace the private and public keys normally generated by the RSA
2463132451Sroberto * scheme. Alice challenges Bob to confirm identity using the protocol
2464132451Sroberto * described below.
2465132451Sroberto *
2466132451Sroberto * How it works
2467132451Sroberto *
2468132451Sroberto * The scheme goes like this. Both Alice and Bob have the same modulus n
2469132451Sroberto * and some random b as the group key. These values are computed and
2470132451Sroberto * distributed in advance via secret means, although only the group key
2471132451Sroberto * b is truly secret. Each has a private random private key u and public
2472132451Sroberto * key (u^-1)^b, although not necessarily the same ones. Bob and Alice
2473132451Sroberto * can regenerate the key pair from time to time without affecting
2474132451Sroberto * operations. The public key is conveyed on the certificate in an
2475132451Sroberto * extension field; the private key is never revealed.
2476132451Sroberto *
2477132451Sroberto * Alice rolls new random challenge r and sends to Bob in the GQ
2478132451Sroberto * request message. Bob rolls new random k, then computes y = k u^r mod
2479132451Sroberto * n and x = k^b mod n and sends (y, hash(x)) to Alice in the response
2480132451Sroberto * message. Besides making the response shorter, the hash makes it
2481132451Sroberto * effectivey impossible for an intruder to solve for b by observing
2482132451Sroberto * a number of these messages.
2483132451Sroberto *
2484132451Sroberto * Alice receives the response and computes y^b v^r mod n. After a bit
2485132451Sroberto * of algebra, this simplifies to k^b. If the hash of this result
2486132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed
2487132451Sroberto * response binds this knowledge to Bob's private key and the public key
2488132451Sroberto * previously received in his certificate.
2489132451Sroberto *
2490132451Sroberto * crypto_alice2 - construct Alice's challenge in GQ scheme
2491132451Sroberto *
2492132451Sroberto * Returns
2493132451Sroberto * XEVNT_OK	success
2494285612Sdelphij * XEVNT_ID	bad or missing group key
2495132451Sroberto * XEVNT_PUB	bad or missing public key
2496132451Sroberto */
2497132451Srobertostatic int
2498132451Srobertocrypto_alice2(
2499132451Sroberto	struct peer *peer,	/* peer pointer */
2500132451Sroberto	struct value *vp	/* value pointer */
2501132451Sroberto	)
2502132451Sroberto{
2503132451Sroberto	RSA	*rsa;		/* GQ parameters */
2504132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2505309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2506132451Sroberto	tstamp_t tstamp;
2507132451Sroberto	u_int	len;
2508309008Sdelphij	const BIGNUM *n;
2509132451Sroberto
2510132451Sroberto	/*
2511132451Sroberto	 * The identity parameters must have correct format and content.
2512132451Sroberto	 */
2513132451Sroberto	if (peer->ident_pkey == NULL)
2514132451Sroberto		return (XEVNT_ID);
2515182007Sroberto
2516309008Sdelphij	if ((rsa = EVP_PKEY_get0_RSA(peer->ident_pkey->pkey)) == NULL) {
2517285612Sdelphij		msyslog(LOG_NOTICE, "crypto_alice2: defective key");
2518132451Sroberto		return (XEVNT_PUB);
251982498Sroberto	}
252082498Sroberto
252182498Sroberto	/*
2522285612Sdelphij	 * Roll new random r (0 < r < n).
252382498Sroberto	 */
2524132451Sroberto	if (peer->iffval != NULL)
2525132451Sroberto		BN_free(peer->iffval);
2526132451Sroberto	peer->iffval = BN_new();
2527309008Sdelphij	RSA_get0_key(rsa, &n, NULL, NULL);
2528309008Sdelphij	len = BN_num_bytes(n);
2529132451Sroberto	BN_rand(peer->iffval, len * 8, -1, 1);	/* r mod n */
2530285612Sdelphij	bctx = BN_CTX_new();
2531309008Sdelphij	BN_mod(peer->iffval, peer->iffval, n, bctx);
2532132451Sroberto	BN_CTX_free(bctx);
2533132451Sroberto
2534132451Sroberto	/*
2535132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2536132451Sroberto	 */
2537285612Sdelphij	memset(vp, 0, sizeof(struct value));
2538132451Sroberto	tstamp = crypto_time();
2539132451Sroberto	vp->tstamp = htonl(tstamp);
2540285612Sdelphij	vp->fstamp = htonl(peer->ident_pkey->fstamp);
2541132451Sroberto	vp->vallen = htonl(len);
2542132451Sroberto	vp->ptr = emalloc(len);
2543132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2544132451Sroberto	if (tstamp == 0)
2545132451Sroberto		return (XEVNT_OK);
2546182007Sroberto
2547132451Sroberto	vp->sig = emalloc(sign_siglen);
2548309008Sdelphij	ctx = EVP_MD_CTX_new();
2549309008Sdelphij	EVP_SignInit(ctx, sign_digest);
2550309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
2551309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
2552309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
2553289997Sglebius		INSIST(len <= sign_siglen);
2554132451Sroberto		vp->siglen = htonl(len);
2555285612Sdelphij	}
2556309008Sdelphij	EVP_MD_CTX_free(ctx);
2557132451Sroberto	return (XEVNT_OK);
2558132451Sroberto}
2559132451Sroberto
2560132451Sroberto
2561132451Sroberto/*
2562132451Sroberto * crypto_bob2 - construct Bob's response to Alice's challenge
2563132451Sroberto *
2564132451Sroberto * Returns
2565132451Sroberto * XEVNT_OK	success
2566285612Sdelphij * XEVNT_ERR	protocol error
2567182007Sroberto * XEVNT_ID	bad or missing group key
2568132451Sroberto */
2569132451Srobertostatic int
2570132451Srobertocrypto_bob2(
2571132451Sroberto	struct exten *ep,	/* extension pointer */
2572132451Sroberto	struct value *vp	/* value pointer */
2573132451Sroberto	)
2574132451Sroberto{
2575132451Sroberto	RSA	*rsa;		/* GQ parameters */
2576132451Sroberto	DSA_SIG	*sdsa;		/* DSA parameters */
2577132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2578309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2579132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2580132451Sroberto	BIGNUM	*r, *k, *g, *y;
2581132451Sroberto	u_char	*ptr;
2582132451Sroberto	u_int	len;
2583285612Sdelphij	int	s_len;
2584309008Sdelphij	const BIGNUM *n, *p, *e;
2585132451Sroberto
2586132451Sroberto	/*
2587132451Sroberto	 * If the GQ parameters are not valid, something awful
2588132451Sroberto	 * happened or we are being tormented.
2589132451Sroberto	 */
2590285612Sdelphij	if (gqkey_info == NULL) {
2591285612Sdelphij		msyslog(LOG_NOTICE, "crypto_bob2: scheme unavailable");
2592182007Sroberto		return (XEVNT_ID);
259382498Sroberto	}
2594309008Sdelphij	rsa = EVP_PKEY_get0_RSA(gqkey_info->pkey);
2595309008Sdelphij	RSA_get0_key(rsa, &n, &p, &e);
259682498Sroberto
259782498Sroberto	/*
2598132451Sroberto	 * Extract r from the challenge.
259982498Sroberto	 */
2600289997Sglebius	len = exten_payload_size(ep);
2601289997Sglebius	if (len == 0 || len > MAX_VALLEN)
2602289997Sglebius		return (XEVNT_LEN);
2603132451Sroberto	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2604285612Sdelphij		msyslog(LOG_ERR, "crypto_bob2: %s",
2605132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2606182007Sroberto		return (XEVNT_ERR);
2607132451Sroberto	}
2608132451Sroberto
2609132451Sroberto	/*
2610132451Sroberto	 * Bob rolls random k (0 < k < n), computes y = k u^r mod n and
2611132451Sroberto	 * x = k^b mod n, then sends (y, hash(x)) to Alice.
2612132451Sroberto	 */
2613132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); g = BN_new(); y = BN_new();
2614132451Sroberto	sdsa = DSA_SIG_new();
2615132451Sroberto	BN_rand(k, len * 8, -1, 1);		/* k */
2616309008Sdelphij	BN_mod(k, k, n, bctx);
2617309008Sdelphij	BN_mod_exp(y, p, r, n, bctx); /* u^r mod n */
2618309008Sdelphij	BN_mod_mul(y, k, y, n, bctx);	/* k u^r mod n */
2619309008Sdelphij	BN_mod_exp(g, k, e, n, bctx); /* k^b mod n */
2620132451Sroberto	bighash(g, g);
2621309008Sdelphij	DSA_SIG_set0(sdsa, y, g);
2622132451Sroberto	BN_CTX_free(bctx);
2623309008Sdelphij	BN_free(r); BN_free(k);
2624285612Sdelphij#ifdef DEBUG
2625285612Sdelphij	if (debug > 1)
2626285612Sdelphij		RSA_print_fp(stdout, rsa, 0);
2627285612Sdelphij#endif
2628132451Sroberto
2629132451Sroberto	/*
2630285612Sdelphij	 * Encode the values in ASN.1 and sign. The filestamp is from
2631285612Sdelphij	 * the local file.
2632132451Sroberto	 */
2633285612Sdelphij	len = s_len = i2d_DSA_SIG(sdsa, NULL);
2634285612Sdelphij	if (s_len <= 0) {
2635285612Sdelphij		msyslog(LOG_ERR, "crypto_bob2: %s",
2636132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2637132451Sroberto		DSA_SIG_free(sdsa);
2638182007Sroberto		return (XEVNT_ERR);
2639132451Sroberto	}
2640285612Sdelphij	memset(vp, 0, sizeof(struct value));
2641285612Sdelphij	tstamp = crypto_time();
2642285612Sdelphij	vp->tstamp = htonl(tstamp);
2643285612Sdelphij	vp->fstamp = htonl(gqkey_info->fstamp);
2644132451Sroberto	vp->vallen = htonl(len);
2645132451Sroberto	ptr = emalloc(len);
2646132451Sroberto	vp->ptr = ptr;
2647132451Sroberto	i2d_DSA_SIG(sdsa, &ptr);
2648132451Sroberto	DSA_SIG_free(sdsa);
2649132451Sroberto	if (tstamp == 0)
2650132451Sroberto		return (XEVNT_OK);
2651182007Sroberto
2652132451Sroberto	vp->sig = emalloc(sign_siglen);
2653309008Sdelphij	ctx = EVP_MD_CTX_new();
2654309008Sdelphij	EVP_SignInit(ctx, sign_digest);
2655309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
2656309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
2657309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
2658289997Sglebius		INSIST(len <= sign_siglen);
2659132451Sroberto		vp->siglen = htonl(len);
2660285612Sdelphij	}
2661309008Sdelphij	EVP_MD_CTX_free(ctx);
2662132451Sroberto	return (XEVNT_OK);
2663132451Sroberto}
2664132451Sroberto
2665132451Sroberto
2666132451Sroberto/*
2667132451Sroberto * crypto_gq - verify Bob's response to Alice's challenge
2668132451Sroberto *
2669132451Sroberto * Returns
2670132451Sroberto * XEVNT_OK	success
2671182007Sroberto * XEVNT_ERR	protocol error
2672132451Sroberto * XEVNT_FSP	bad filestamp
2673285612Sdelphij * XEVNT_ID	bad or missing group keys
2674285612Sdelphij * XEVNT_PUB	bad or missing public key
2675132451Sroberto */
2676132451Srobertoint
2677132451Srobertocrypto_gq(
2678132451Sroberto	struct exten *ep,	/* extension pointer */
2679132451Sroberto	struct peer *peer	/* peer structure pointer */
2680132451Sroberto	)
2681132451Sroberto{
2682132451Sroberto	RSA	*rsa;		/* GQ parameters */
2683132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2684132451Sroberto	DSA_SIG	*sdsa;		/* RSA signature context fake */
2685132451Sroberto	BIGNUM	*y, *v;
2686285612Sdelphij	const u_char *ptr;
2687285612Sdelphij	long	len;
2688285612Sdelphij	u_int	temp;
2689309008Sdelphij	const BIGNUM *n, *e;
2690309008Sdelphij	const BIGNUM *r, *s;
2691132451Sroberto
2692132451Sroberto	/*
2693132451Sroberto	 * If the GQ parameters are not valid or no challenge was sent,
2694285612Sdelphij	 * something awful happened or we are being tormented. Note that
2695285612Sdelphij	 * the filestamp on the local key file can be greater than on
2696285612Sdelphij	 * the remote parameter file if the keys have been refreshed.
2697132451Sroberto	 */
2698132451Sroberto	if (peer->ident_pkey == NULL) {
2699285612Sdelphij		msyslog(LOG_NOTICE, "crypto_gq: scheme unavailable");
2700182007Sroberto		return (XEVNT_ID);
2701132451Sroberto	}
2702285612Sdelphij	if (ntohl(ep->fstamp) < peer->ident_pkey->fstamp) {
2703285612Sdelphij		msyslog(LOG_NOTICE, "crypto_gq: invalid filestamp %u",
2704132451Sroberto		    ntohl(ep->fstamp));
2705132451Sroberto		return (XEVNT_FSP);
2706132451Sroberto	}
2707309008Sdelphij	if ((rsa = EVP_PKEY_get0_RSA(peer->ident_pkey->pkey)) == NULL) {
2708285612Sdelphij		msyslog(LOG_NOTICE, "crypto_gq: defective key");
2709132451Sroberto		return (XEVNT_PUB);
2710132451Sroberto	}
2711309008Sdelphij	RSA_get0_key(rsa, &n, NULL, &e);
2712132451Sroberto	if (peer->iffval == NULL) {
2713285612Sdelphij		msyslog(LOG_NOTICE, "crypto_gq: missing challenge");
2714182007Sroberto		return (XEVNT_ID);
2715132451Sroberto	}
2716132451Sroberto
2717132451Sroberto	/*
2718132451Sroberto	 * Extract the y = k u^r and hash(x = k^b) values from the
2719132451Sroberto	 * response.
2720132451Sroberto	 */
2721132451Sroberto	bctx = BN_CTX_new(); y = BN_new(); v = BN_new();
2722132451Sroberto	len = ntohl(ep->vallen);
2723285612Sdelphij	ptr = (u_char *)ep->pkt;
2724132451Sroberto	if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
2725285612Sdelphij		BN_CTX_free(bctx); BN_free(y); BN_free(v);
2726285612Sdelphij		msyslog(LOG_ERR, "crypto_gq: %s",
2727132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2728182007Sroberto		return (XEVNT_ERR);
2729132451Sroberto	}
2730309008Sdelphij	DSA_SIG_get0(sdsa, &r, &s);
2731132451Sroberto
2732132451Sroberto	/*
2733132451Sroberto	 * Compute v^r y^b mod n.
2734132451Sroberto	 */
2735285612Sdelphij	if (peer->grpkey == NULL) {
2736285612Sdelphij		msyslog(LOG_NOTICE, "crypto_gq: missing group key");
2737285612Sdelphij		return (XEVNT_ID);
2738285612Sdelphij	}
2739309008Sdelphij	BN_mod_exp(v, peer->grpkey, peer->iffval, n, bctx);
2740132451Sroberto						/* v^r mod n */
2741309008Sdelphij	BN_mod_exp(y, r, e, n, bctx); /* y^b mod n */
2742309008Sdelphij	BN_mod_mul(y, v, y, n, bctx);	/* v^r y^b mod n */
2743132451Sroberto
2744132451Sroberto	/*
2745132451Sroberto	 * Verify the hash of the result matches hash(x).
2746132451Sroberto	 */
2747132451Sroberto	bighash(y, y);
2748309008Sdelphij	temp = BN_cmp(y, s);
2749132451Sroberto	BN_CTX_free(bctx); BN_free(y); BN_free(v);
2750132451Sroberto	BN_free(peer->iffval);
2751132451Sroberto	peer->iffval = NULL;
2752132451Sroberto	DSA_SIG_free(sdsa);
2753132451Sroberto	if (temp == 0)
2754132451Sroberto		return (XEVNT_OK);
2755182007Sroberto
2756285612Sdelphij	msyslog(LOG_NOTICE, "crypto_gq: identity not verified");
2757285612Sdelphij	return (XEVNT_ID);
2758132451Sroberto}
2759132451Sroberto
2760132451Sroberto
2761132451Sroberto/*
2762132451Sroberto ***********************************************************************
2763132451Sroberto *								       *
2764132451Sroberto * The following routines implement the Mu-Varadharajan (MV) identity  *
2765132451Sroberto * scheme                                                              *
2766132451Sroberto *								       *
2767132451Sroberto ***********************************************************************
2768285612Sdelphij *
2769132451Sroberto * The Mu-Varadharajan (MV) cryptosystem was originally intended when
2770132451Sroberto * servers broadcast messages to clients, but clients never send
2771132451Sroberto * messages to servers. There is one encryption key for the server and a
2772132451Sroberto * separate decryption key for each client. It operated something like a
2773132451Sroberto * pay-per-view satellite broadcasting system where the session key is
2774132451Sroberto * encrypted by the broadcaster and the decryption keys are held in a
2775132451Sroberto * tamperproof set-top box.
2776132451Sroberto *
2777132451Sroberto * The MV parameters and private encryption key hide in a DSA cuckoo
2778132451Sroberto * structure which uses the same parameters, but generated in a
2779132451Sroberto * different way. The values are used in an encryption scheme similar to
2780132451Sroberto * El Gamal cryptography and a polynomial formed from the expansion of
2781132451Sroberto * product terms (x - x[j]), as described in Mu, Y., and V.
2782132451Sroberto * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001,
2783132451Sroberto * 223-231. The paper has significant errors and serious omissions.
2784132451Sroberto *
2785285612Sdelphij * Let q be the product of n distinct primes s1[j] (j = 1...n), where
2786285612Sdelphij * each s1[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
2787285612Sdelphij * that q and each s1[j] divide p - 1 and p has M = n * m + 1
2788285612Sdelphij * significant bits. Let g be a generator of Zp; that is, gcd(g, p - 1)
2789285612Sdelphij * = 1 and g^q = 1 mod p. We do modular arithmetic over Zq and then
2790285612Sdelphij * project into Zp* as exponents of g. Sometimes we have to compute an
2791285612Sdelphij * inverse b^-1 of random b in Zq, but for that purpose we require
2792285612Sdelphij * gcd(b, q) = 1. We expect M to be in the 500-bit range and n
2793285612Sdelphij * relatively small, like 30. These are the parameters of the scheme and
2794285612Sdelphij * they are expensive to compute.
2795132451Sroberto *
2796132451Sroberto * We set up an instance of the scheme as follows. A set of random
2797132451Sroberto * values x[j] mod q (j = 1...n), are generated as the zeros of a
2798132451Sroberto * polynomial of order n. The product terms (x - x[j]) are expanded to
2799132451Sroberto * form coefficients a[i] mod q (i = 0...n) in powers of x. These are
2800132451Sroberto * used as exponents of the generator g mod p to generate the private
2801132451Sroberto * encryption key A. The pair (gbar, ghat) of public server keys and the
2802132451Sroberto * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used
2803132451Sroberto * to construct the decryption keys. The devil is in the details.
2804132451Sroberto *
2805285612Sdelphij * This routine generates a private server encryption file including the
2806285612Sdelphij * private encryption key E and partial decryption keys gbar and ghat.
2807285612Sdelphij * It then generates public client decryption files including the public
2808285612Sdelphij * keys xbar[j] and xhat[j] for each client j. The partial decryption
2809285612Sdelphij * files are used to compute the inverse of E. These values are suitably
2810285612Sdelphij * blinded so secrets are not revealed.
2811285612Sdelphij *
2812132451Sroberto * The distinguishing characteristic of this scheme is the capability to
2813132451Sroberto * revoke keys. Included in the calculation of E, gbar and ghat is the
2814285612Sdelphij * product s = prod(s1[j]) (j = 1...n) above. If the factor s1[j] is
2815132451Sroberto * subsequently removed from the product and E, gbar and ghat
2816132451Sroberto * recomputed, the jth client will no longer be able to compute E^-1 and
2817285612Sdelphij * thus unable to decrypt the messageblock.
2818132451Sroberto *
2819132451Sroberto * How it works
2820132451Sroberto *
2821285612Sdelphij * The scheme goes like this. Bob has the server values (p, E, q, gbar,
2822285612Sdelphij * ghat) and Alice has the client values (p, xbar, xhat).
2823132451Sroberto *
2824285612Sdelphij * Alice rolls new random nonce r mod p and sends to Bob in the MV
2825285612Sdelphij * request message. Bob rolls random nonce k mod q, encrypts y = r E^k
2826285612Sdelphij * mod p and sends (y, gbar^k, ghat^k) to Alice.
2827132451Sroberto *
2828285612Sdelphij * Alice receives the response and computes the inverse (E^k)^-1 from
2829285612Sdelphij * the partial decryption keys gbar^k, ghat^k, xbar and xhat. She then
2830285612Sdelphij * decrypts y and verifies it matches the original r. The signed
2831285612Sdelphij * response binds this knowledge to Bob's private key and the public key
2832285612Sdelphij * previously received in his certificate.
2833132451Sroberto *
2834132451Sroberto * crypto_alice3 - construct Alice's challenge in MV scheme
2835132451Sroberto *
2836132451Sroberto * Returns
2837132451Sroberto * XEVNT_OK	success
2838285612Sdelphij * XEVNT_ID	bad or missing group key
2839132451Sroberto * XEVNT_PUB	bad or missing public key
2840132451Sroberto */
2841132451Srobertostatic int
2842132451Srobertocrypto_alice3(
2843132451Sroberto	struct peer *peer,	/* peer pointer */
2844132451Sroberto	struct value *vp	/* value pointer */
2845132451Sroberto	)
2846132451Sroberto{
2847132451Sroberto	DSA	*dsa;		/* MV parameters */
2848132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2849309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2850132451Sroberto	tstamp_t tstamp;
2851132451Sroberto	u_int	len;
2852309008Sdelphij	const BIGNUM *p;
2853132451Sroberto
2854132451Sroberto	/*
2855132451Sroberto	 * The identity parameters must have correct format and content.
2856132451Sroberto	 */
2857132451Sroberto	if (peer->ident_pkey == NULL)
2858132451Sroberto		return (XEVNT_ID);
2859182007Sroberto
2860309008Sdelphij	if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) {
2861285612Sdelphij		msyslog(LOG_NOTICE, "crypto_alice3: defective key");
2862132451Sroberto		return (XEVNT_PUB);
286382498Sroberto	}
2864309008Sdelphij	DSA_get0_pqg(dsa, &p, NULL, NULL);
286582498Sroberto
286682498Sroberto	/*
2867285612Sdelphij	 * Roll new random r (0 < r < q).
286882498Sroberto	 */
2869132451Sroberto	if (peer->iffval != NULL)
2870132451Sroberto		BN_free(peer->iffval);
2871132451Sroberto	peer->iffval = BN_new();
2872309008Sdelphij	len = BN_num_bytes(p);
2873285612Sdelphij	BN_rand(peer->iffval, len * 8, -1, 1);	/* r mod p */
2874285612Sdelphij	bctx = BN_CTX_new();
2875309008Sdelphij	BN_mod(peer->iffval, peer->iffval, p, bctx);
2876132451Sroberto	BN_CTX_free(bctx);
2877132451Sroberto
2878132451Sroberto	/*
2879132451Sroberto	 * Sign and send to Bob. The filestamp is from the local file.
2880132451Sroberto	 */
2881285612Sdelphij	memset(vp, 0, sizeof(struct value));
2882132451Sroberto	tstamp = crypto_time();
2883132451Sroberto	vp->tstamp = htonl(tstamp);
2884285612Sdelphij	vp->fstamp = htonl(peer->ident_pkey->fstamp);
2885132451Sroberto	vp->vallen = htonl(len);
2886132451Sroberto	vp->ptr = emalloc(len);
2887132451Sroberto	BN_bn2bin(peer->iffval, vp->ptr);
2888132451Sroberto	if (tstamp == 0)
2889132451Sroberto		return (XEVNT_OK);
2890182007Sroberto
2891132451Sroberto	vp->sig = emalloc(sign_siglen);
2892309008Sdelphij	ctx = EVP_MD_CTX_new();
2893309008Sdelphij	EVP_SignInit(ctx, sign_digest);
2894309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
2895309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
2896309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
2897289997Sglebius		INSIST(len <= sign_siglen);
2898132451Sroberto		vp->siglen = htonl(len);
2899285612Sdelphij	}
2900309008Sdelphij	EVP_MD_CTX_free(ctx);
2901132451Sroberto	return (XEVNT_OK);
2902132451Sroberto}
2903132451Sroberto
2904132451Sroberto
2905132451Sroberto/*
2906132451Sroberto * crypto_bob3 - construct Bob's response to Alice's challenge
2907132451Sroberto *
2908132451Sroberto * Returns
2909132451Sroberto * XEVNT_OK	success
2910182007Sroberto * XEVNT_ERR	protocol error
2911132451Sroberto */
2912132451Srobertostatic int
2913132451Srobertocrypto_bob3(
2914132451Sroberto	struct exten *ep,	/* extension pointer */
2915132451Sroberto	struct value *vp	/* value pointer */
2916132451Sroberto	)
2917132451Sroberto{
2918132451Sroberto	DSA	*dsa;		/* MV parameters */
2919132451Sroberto	DSA	*sdsa;		/* DSA signature context fake */
2920132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
2921309008Sdelphij	EVP_MD_CTX *ctx;	/* signature context */
2922132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
2923132451Sroberto	BIGNUM	*r, *k, *u;
2924132451Sroberto	u_char	*ptr;
2925132451Sroberto	u_int	len;
2926309008Sdelphij	const BIGNUM *p, *q, *g;
2927309008Sdelphij	const BIGNUM *pub_key, *priv_key;
2928309008Sdelphij	BIGNUM *sp, *sq, *sg;
2929132451Sroberto
2930132451Sroberto	/*
2931132451Sroberto	 * If the MV parameters are not valid, something awful
2932132451Sroberto	 * happened or we are being tormented.
2933132451Sroberto	 */
2934285612Sdelphij	if (mvkey_info == NULL) {
2935285612Sdelphij		msyslog(LOG_NOTICE, "crypto_bob3: scheme unavailable");
2936182007Sroberto		return (XEVNT_ID);
293782498Sroberto	}
2938309008Sdelphij	dsa = EVP_PKEY_get0_DSA(mvkey_info->pkey);
2939309008Sdelphij	DSA_get0_pqg(dsa, &p, &q, &g);
2940309008Sdelphij	DSA_get0_key(dsa, &pub_key, &priv_key);
2941132451Sroberto
2942132451Sroberto	/*
2943132451Sroberto	 * Extract r from the challenge.
2944132451Sroberto	 */
2945289997Sglebius	len = exten_payload_size(ep);
2946289997Sglebius	if (len == 0 || len > MAX_VALLEN)
2947289997Sglebius		return (XEVNT_LEN);
2948132451Sroberto	if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
2949285612Sdelphij		msyslog(LOG_ERR, "crypto_bob3: %s",
2950132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2951182007Sroberto		return (XEVNT_ERR);
2952132451Sroberto	}
2953132451Sroberto
2954132451Sroberto	/*
2955132451Sroberto	 * Bob rolls random k (0 < k < q), making sure it is not a
2956285612Sdelphij	 * factor of q. He then computes y = r A^k and sends (y, gbar^k,
2957285612Sdelphij	 * and ghat^k) to Alice.
2958132451Sroberto	 */
2959132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); u = BN_new();
2960132451Sroberto	sdsa = DSA_new();
2961309008Sdelphij	sp = BN_new(); sq = BN_new(); sg = BN_new();
2962132451Sroberto	while (1) {
2963309008Sdelphij		BN_rand(k, BN_num_bits(q), 0, 0);
2964309008Sdelphij		BN_mod(k, k, q, bctx);
2965309008Sdelphij		BN_gcd(u, k, q, bctx);
2966132451Sroberto		if (BN_is_one(u))
2967132451Sroberto			break;
2968132451Sroberto	}
2969309008Sdelphij	BN_mod_exp(u, g, k, p, bctx); /* A^k r */
2970309008Sdelphij	BN_mod_mul(sp, u, r, p, bctx);
2971309008Sdelphij	BN_mod_exp(sq, priv_key, k, p, bctx); /* gbar */
2972309008Sdelphij	BN_mod_exp(sg, pub_key, k, p, bctx); /* ghat */
2973309008Sdelphij	DSA_set0_key(sdsa, BN_dup(pub_key), NULL);
2974309008Sdelphij	DSA_set0_pqg(sdsa, sp, sq, sg);
2975132451Sroberto	BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u);
2976285612Sdelphij#ifdef DEBUG
2977285612Sdelphij	if (debug > 1)
2978285612Sdelphij		DSA_print_fp(stdout, sdsa, 0);
2979285612Sdelphij#endif
2980132451Sroberto
2981132451Sroberto	/*
2982285612Sdelphij	 * Encode the values in ASN.1 and sign. The filestamp is from
2983285612Sdelphij	 * the local file.
2984132451Sroberto	 */
2985285612Sdelphij	memset(vp, 0, sizeof(struct value));
2986132451Sroberto	tstamp = crypto_time();
2987132451Sroberto	vp->tstamp = htonl(tstamp);
2988285612Sdelphij	vp->fstamp = htonl(mvkey_info->fstamp);
2989132451Sroberto	len = i2d_DSAparams(sdsa, NULL);
2990285612Sdelphij	if (len == 0) {
2991285612Sdelphij		msyslog(LOG_ERR, "crypto_bob3: %s",
2992132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
2993132451Sroberto		DSA_free(sdsa);
2994182007Sroberto		return (XEVNT_ERR);
2995132451Sroberto	}
2996132451Sroberto	vp->vallen = htonl(len);
2997132451Sroberto	ptr = emalloc(len);
2998132451Sroberto	vp->ptr = ptr;
2999132451Sroberto	i2d_DSAparams(sdsa, &ptr);
3000132451Sroberto	DSA_free(sdsa);
3001132451Sroberto	if (tstamp == 0)
3002132451Sroberto		return (XEVNT_OK);
3003182007Sroberto
3004132451Sroberto	vp->sig = emalloc(sign_siglen);
3005309008Sdelphij	ctx = EVP_MD_CTX_new();
3006309008Sdelphij	EVP_SignInit(ctx, sign_digest);
3007309008Sdelphij	EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12);
3008309008Sdelphij	EVP_SignUpdate(ctx, vp->ptr, len);
3009309008Sdelphij	if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
3010289997Sglebius		INSIST(len <= sign_siglen);
3011132451Sroberto		vp->siglen = htonl(len);
3012285612Sdelphij	}
3013309008Sdelphij	EVP_MD_CTX_free(ctx);
3014132451Sroberto	return (XEVNT_OK);
3015132451Sroberto}
3016132451Sroberto
3017132451Sroberto
3018132451Sroberto/*
3019132451Sroberto * crypto_mv - verify Bob's response to Alice's challenge
3020132451Sroberto *
3021132451Sroberto * Returns
3022132451Sroberto * XEVNT_OK	success
3023182007Sroberto * XEVNT_ERR	protocol error
3024132451Sroberto * XEVNT_FSP	bad filestamp
3025285612Sdelphij * XEVNT_ID	bad or missing group key
3026285612Sdelphij * XEVNT_PUB	bad or missing public key
3027132451Sroberto */
3028132451Srobertoint
3029132451Srobertocrypto_mv(
3030132451Sroberto	struct exten *ep,	/* extension pointer */
3031132451Sroberto	struct peer *peer	/* peer structure pointer */
3032132451Sroberto	)
3033132451Sroberto{
3034132451Sroberto	DSA	*dsa;		/* MV parameters */
3035132451Sroberto	DSA	*sdsa;		/* DSA parameters */
3036132451Sroberto	BN_CTX	*bctx;		/* BIGNUM context */
3037132451Sroberto	BIGNUM	*k, *u, *v;
3038132451Sroberto	u_int	len;
3039285612Sdelphij	const u_char *ptr;
3040132451Sroberto	int	temp;
3041309008Sdelphij	const BIGNUM *p;
3042309008Sdelphij	const BIGNUM *pub_key, *priv_key;
3043309008Sdelphij	const BIGNUM *sp, *sq, *sg;
3044132451Sroberto
3045132451Sroberto	/*
3046132451Sroberto	 * If the MV parameters are not valid or no challenge was sent,
3047132451Sroberto	 * something awful happened or we are being tormented.
3048132451Sroberto	 */
3049132451Sroberto	if (peer->ident_pkey == NULL) {
3050285612Sdelphij		msyslog(LOG_NOTICE, "crypto_mv: scheme unavailable");
3051182007Sroberto		return (XEVNT_ID);
3052132451Sroberto	}
3053285612Sdelphij	if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) {
3054285612Sdelphij		msyslog(LOG_NOTICE, "crypto_mv: invalid filestamp %u",
3055132451Sroberto		    ntohl(ep->fstamp));
3056132451Sroberto		return (XEVNT_FSP);
3057132451Sroberto	}
3058309008Sdelphij	if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) {
3059285612Sdelphij		msyslog(LOG_NOTICE, "crypto_mv: defective key");
3060132451Sroberto		return (XEVNT_PUB);
3061132451Sroberto	}
3062309008Sdelphij	DSA_get0_pqg(dsa, &p, NULL, NULL);
3063309008Sdelphij	DSA_get0_key(dsa, &pub_key, &priv_key);
3064132451Sroberto	if (peer->iffval == NULL) {
3065285612Sdelphij		msyslog(LOG_NOTICE, "crypto_mv: missing challenge");
3066182007Sroberto		return (XEVNT_ID);
3067132451Sroberto	}
3068132451Sroberto
3069132451Sroberto	/*
3070285612Sdelphij	 * Extract the y, gbar and ghat values from the response.
3071132451Sroberto	 */
3072132451Sroberto	bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); v = BN_new();
3073132451Sroberto	len = ntohl(ep->vallen);
3074285612Sdelphij	ptr = (u_char *)ep->pkt;
3075132451Sroberto	if ((sdsa = d2i_DSAparams(NULL, &ptr, len)) == NULL) {
3076285612Sdelphij		msyslog(LOG_ERR, "crypto_mv: %s",
3077132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3078182007Sroberto		return (XEVNT_ERR);
3079132451Sroberto	}
3080309008Sdelphij	DSA_get0_pqg(sdsa, &sp, &sq, &sg);
3081132451Sroberto
3082132451Sroberto	/*
3083285612Sdelphij	 * Compute (gbar^xhat ghat^xbar) mod p.
3084132451Sroberto	 */
3085309008Sdelphij	BN_mod_exp(u, sq, pub_key, p, bctx);
3086309008Sdelphij	BN_mod_exp(v, sg, priv_key, p, bctx);
3087309008Sdelphij	BN_mod_mul(u, u, v, p, bctx);
3088309008Sdelphij	BN_mod_mul(u, u, sp, p, bctx);
3089132451Sroberto
3090132451Sroberto	/*
3091285612Sdelphij	 * The result should match r.
3092132451Sroberto	 */
3093285612Sdelphij	temp = BN_cmp(u, peer->iffval);
3094132451Sroberto	BN_CTX_free(bctx); BN_free(k); BN_free(u); BN_free(v);
3095132451Sroberto	BN_free(peer->iffval);
3096132451Sroberto	peer->iffval = NULL;
3097132451Sroberto	DSA_free(sdsa);
3098132451Sroberto	if (temp == 0)
3099132451Sroberto		return (XEVNT_OK);
3100182007Sroberto
3101285612Sdelphij	msyslog(LOG_NOTICE, "crypto_mv: identity not verified");
3102285612Sdelphij	return (XEVNT_ID);
3103132451Sroberto}
3104132451Sroberto
3105132451Sroberto
3106132451Sroberto/*
3107132451Sroberto ***********************************************************************
3108132451Sroberto *								       *
3109132451Sroberto * The following routines are used to manipulate certificates          *
3110132451Sroberto *								       *
3111132451Sroberto ***********************************************************************
3112132451Sroberto */
3113132451Sroberto/*
3114182007Sroberto * cert_sign - sign x509 certificate equest and update value structure.
3115132451Sroberto *
3116182007Sroberto * The certificate request includes a copy of the host certificate,
3117182007Sroberto * which includes the version number, subject name and public key of the
3118182007Sroberto * host. The resulting certificate includes these values plus the
3119182007Sroberto * serial number, issuer name and valid interval of the server. The
3120182007Sroberto * valid interval extends from the current time to the same time one
3121182007Sroberto * year hence. This may extend the life of the signed certificate beyond
3122182007Sroberto * that of the signer certificate.
3123132451Sroberto *
3124182007Sroberto * It is convenient to use the NTP seconds of the current time as the
3125182007Sroberto * serial number. In the value structure the timestamp is the current
3126182007Sroberto * time and the filestamp is taken from the extension field. Note this
3127182007Sroberto * routine is called only when the client clock is synchronized to a
3128182007Sroberto * proventic source, so timestamp comparisons are valid.
3129182007Sroberto *
3130182007Sroberto * The host certificate is valid from the time it was generated for a
3131182007Sroberto * period of one year. A signed certificate is valid from the time of
3132182007Sroberto * signature for a period of one year, but only the host certificate (or
3133182007Sroberto * sign certificate if used) is actually used to encrypt and decrypt
3134182007Sroberto * signatures. The signature trail is built from the client via the
3135182007Sroberto * intermediate servers to the trusted server. Each signature on the
3136182007Sroberto * trail must be valid at the time of signature, but it could happen
3137182007Sroberto * that a signer certificate expire before the signed certificate, which
3138182007Sroberto * remains valid until its expiration.
3139182007Sroberto *
3140132451Sroberto * Returns
3141132451Sroberto * XEVNT_OK	success
3142285612Sdelphij * XEVNT_CRT	bad or missing certificate
3143285612Sdelphij * XEVNT_PER	host certificate expired
3144132451Sroberto * XEVNT_PUB	bad or missing public key
3145132451Sroberto * XEVNT_VFY	certificate not verified
314682498Sroberto */
3147132451Srobertostatic int
3148132451Srobertocert_sign(
3149132451Sroberto	struct exten *ep,	/* extension field pointer */
3150132451Sroberto	struct value *vp	/* value pointer */
315182498Sroberto	)
315282498Sroberto{
3153132451Sroberto	X509	*req;		/* X509 certificate request */
3154132451Sroberto	X509	*cert;		/* X509 certificate */
3155132451Sroberto	X509_EXTENSION *ext;	/* certificate extension */
3156132451Sroberto	ASN1_INTEGER *serial;	/* serial number */
3157132451Sroberto	X509_NAME *subj;	/* distinguished (common) name */
3158132451Sroberto	EVP_PKEY *pkey;		/* public key */
3159309008Sdelphij	EVP_MD_CTX *ctx;	/* message digest context */
3160132451Sroberto	tstamp_t tstamp;	/* NTP timestamp */
3161285612Sdelphij	struct calendar tscal;
3162132451Sroberto	u_int	len;
3163285612Sdelphij	const u_char *cptr;
3164285612Sdelphij	u_char *ptr;
3165132451Sroberto	int	i, temp;
316682498Sroberto
316782498Sroberto	/*
3168132451Sroberto	 * Decode ASN.1 objects and construct certificate structure.
3169182007Sroberto	 * Make sure the system clock is synchronized to a proventic
3170182007Sroberto	 * source.
317182498Sroberto	 */
3172132451Sroberto	tstamp = crypto_time();
3173132451Sroberto	if (tstamp == 0)
3174132451Sroberto		return (XEVNT_TSP);
3175132451Sroberto
3176289997Sglebius	len = exten_payload_size(ep);
3177289997Sglebius	if (len == 0 || len > MAX_VALLEN)
3178289997Sglebius		return (XEVNT_LEN);
3179285612Sdelphij	cptr = (void *)ep->pkt;
3180289997Sglebius	if ((req = d2i_X509(NULL, &cptr, len)) == NULL) {
3181285612Sdelphij		msyslog(LOG_ERR, "cert_sign: %s",
3182132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3183132451Sroberto		return (XEVNT_CRT);
318482498Sroberto	}
3185132451Sroberto	/*
3186132451Sroberto	 * Extract public key and check for errors.
3187132451Sroberto	 */
3188132451Sroberto	if ((pkey = X509_get_pubkey(req)) == NULL) {
3189285612Sdelphij		msyslog(LOG_ERR, "cert_sign: %s",
3190132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3191132451Sroberto		X509_free(req);
3192132451Sroberto		return (XEVNT_PUB);
3193132451Sroberto	}
319482498Sroberto
319582498Sroberto	/*
3196285612Sdelphij	 * Generate X509 certificate signed by this server. If this is a
3197285612Sdelphij	 * trusted host, the issuer name is the group name; otherwise,
3198285612Sdelphij	 * it is the host name. Also copy any extensions that might be
3199285612Sdelphij	 * present.
320082498Sroberto	 */
3201132451Sroberto	cert = X509_new();
3202132451Sroberto	X509_set_version(cert, X509_get_version(req));
3203132451Sroberto	serial = ASN1_INTEGER_new();
3204132451Sroberto	ASN1_INTEGER_set(serial, tstamp);
3205132451Sroberto	X509_set_serialNumber(cert, serial);
3206316069Sdelphij	X509_gmtime_adj(X509_getm_notBefore(cert), 0L);
3207316069Sdelphij	X509_gmtime_adj(X509_getm_notAfter(cert), YEAR);
3208132451Sroberto	subj = X509_get_issuer_name(cert);
3209132451Sroberto	X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
3210285612Sdelphij	    hostval.ptr, strlen((const char *)hostval.ptr), -1, 0);
3211132451Sroberto	subj = X509_get_subject_name(req);
3212132451Sroberto	X509_set_subject_name(cert, subj);
3213132451Sroberto	X509_set_pubkey(cert, pkey);
3214132451Sroberto	temp = X509_get_ext_count(req);
3215132451Sroberto	for (i = 0; i < temp; i++) {
3216132451Sroberto		ext = X509_get_ext(req, i);
3217285612Sdelphij		INSIST(X509_add_ext(cert, ext, -1));
321882498Sroberto	}
3219132451Sroberto	X509_free(req);
322082498Sroberto
322182498Sroberto	/*
3222285612Sdelphij	 * Sign and verify the client certificate, but only if the host
3223285612Sdelphij	 * certificate has not expired.
322482498Sroberto	 */
3225285612Sdelphij	(void)ntpcal_ntp_to_date(&tscal, tstamp, NULL);
3226285612Sdelphij	if ((calcomp(&tscal, &(cert_host->first)) < 0)
3227285612Sdelphij	|| (calcomp(&tscal, &(cert_host->last)) > 0)) {
3228285612Sdelphij		X509_free(cert);
3229285612Sdelphij		return (XEVNT_PER);
3230285612Sdelphij	}
3231132451Sroberto	X509_sign(cert, sign_pkey, sign_digest);
3232285612Sdelphij	if (X509_verify(cert, sign_pkey) <= 0) {
3233285612Sdelphij		msyslog(LOG_ERR, "cert_sign: %s",
3234132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3235132451Sroberto		X509_free(cert);
3236132451Sroberto		return (XEVNT_VFY);
3237132451Sroberto	}
3238132451Sroberto	len = i2d_X509(cert, NULL);
323982498Sroberto
324082498Sroberto	/*
3241132451Sroberto	 * Build and sign the value structure. We have to sign it here,
3242132451Sroberto	 * since the response has to be returned right away. This is a
3243132451Sroberto	 * clogging hazard.
324482498Sroberto	 */
3245132451Sroberto	memset(vp, 0, sizeof(struct value));
3246132451Sroberto	vp->tstamp = htonl(tstamp);
3247132451Sroberto	vp->fstamp = ep->fstamp;
3248132451Sroberto	vp->vallen = htonl(len);
3249132451Sroberto	vp->ptr = emalloc(len);
3250132451Sroberto	ptr = vp->ptr;
3251285612Sdelphij	i2d_X509(cert, (unsigned char **)(intptr_t)&ptr);
3252132451Sroberto	vp->siglen = 0;
3253285612Sdelphij	if (tstamp != 0) {
3254285612Sdelphij		vp->sig = emalloc(sign_siglen);
3255309008Sdelphij		ctx = EVP_MD_CTX_new();
3256309008Sdelphij		EVP_SignInit(ctx, sign_digest);
3257309008Sdelphij		EVP_SignUpdate(ctx, (u_char *)vp, 12);
3258309008Sdelphij		EVP_SignUpdate(ctx, vp->ptr, len);
3259309008Sdelphij		if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) {
3260289997Sglebius			INSIST(len <= sign_siglen);
3261285612Sdelphij			vp->siglen = htonl(len);
3262285612Sdelphij		}
3263309008Sdelphij		EVP_MD_CTX_free(ctx);
3264285612Sdelphij	}
326582498Sroberto#ifdef DEBUG
3266132451Sroberto	if (debug > 1)
3267132451Sroberto		X509_print_fp(stdout, cert);
326882498Sroberto#endif
3269132451Sroberto	X509_free(cert);
3270132451Sroberto	return (XEVNT_OK);
327182498Sroberto}
327282498Sroberto
327382498Sroberto
327482498Sroberto/*
3275285612Sdelphij * cert_install - install certificate in certificate cache
3276132451Sroberto *
3277132451Sroberto * This routine encodes an extension field into a certificate info/value
3278132451Sroberto * structure. It searches the certificate list for duplicates and
3279285612Sdelphij * expunges whichever is older. Finally, it inserts this certificate
3280285612Sdelphij * first on the list.
3281132451Sroberto *
3282285612Sdelphij * Returns certificate info pointer if valid, NULL if not.
3283132451Sroberto */
3284285612Sdelphijstruct cert_info *
3285132451Srobertocert_install(
3286132451Sroberto	struct exten *ep,	/* cert info/value */
3287132451Sroberto	struct peer *peer	/* peer structure */
3288132451Sroberto	)
3289132451Sroberto{
3290285612Sdelphij	struct cert_info *cp, *xp, **zp;
3291132451Sroberto
329282498Sroberto	/*
3293132451Sroberto	 * Parse and validate the signed certificate. If valid,
3294285612Sdelphij	 * construct the info/value structure; otherwise, scamper home
3295285612Sdelphij	 * empty handed.
329682498Sroberto	 */
3297285612Sdelphij	if ((cp = cert_parse((u_char *)ep->pkt, (long)ntohl(ep->vallen),
3298285612Sdelphij	    (tstamp_t)ntohl(ep->fstamp))) == NULL)
3299285612Sdelphij		return (NULL);
3300132451Sroberto
3301132451Sroberto	/*
3302132451Sroberto	 * Scan certificate list looking for another certificate with
3303132451Sroberto	 * the same subject and issuer. If another is found with the
3304132451Sroberto	 * same or older filestamp, unlink it and return the goodies to
3305182007Sroberto	 * the heap. If another is found with a later filestamp, discard
3306285612Sdelphij	 * the new one and leave the building with the old one.
3307182007Sroberto	 *
3308182007Sroberto	 * Make a note to study this issue again. An earlier certificate
3309182007Sroberto	 * with a long lifetime might be overtaken by a later
3310182007Sroberto	 * certificate with a short lifetime, thus invalidating the
3311182007Sroberto	 * earlier signature. However, we gotta find a way to leak old
3312182007Sroberto	 * stuff from the cache, so we do it anyway.
3313132451Sroberto	 */
3314132451Sroberto	zp = &cinfo;
3315132451Sroberto	for (xp = cinfo; xp != NULL; xp = xp->link) {
3316132451Sroberto		if (strcmp(cp->subject, xp->subject) == 0 &&
3317132451Sroberto		    strcmp(cp->issuer, xp->issuer) == 0) {
3318132451Sroberto			if (ntohl(cp->cert.fstamp) <=
3319132451Sroberto			    ntohl(xp->cert.fstamp)) {
3320285612Sdelphij				cert_free(cp);
3321285612Sdelphij				cp = xp;
3322285612Sdelphij			} else {
3323285612Sdelphij				*zp = xp->link;
3324132451Sroberto				cert_free(xp);
3325285612Sdelphij				xp = NULL;
3326132451Sroberto			}
3327132451Sroberto			break;
3328132451Sroberto		}
3329132451Sroberto		zp = &xp->link;
3330132451Sroberto	}
3331285612Sdelphij	if (xp == NULL) {
3332285612Sdelphij		cp->link = cinfo;
3333285612Sdelphij		cinfo = cp;
3334285612Sdelphij	}
3335285612Sdelphij	cp->flags |= CERT_VALID;
3336285612Sdelphij	crypto_update();
3337285612Sdelphij	return (cp);
3338285612Sdelphij}
3339132451Sroberto
3340285612Sdelphij
3341285612Sdelphij/*
3342285612Sdelphij * cert_hike - verify the signature using the issuer public key
3343285612Sdelphij *
3344285612Sdelphij * Returns
3345285612Sdelphij * XEVNT_OK	success
3346285612Sdelphij * XEVNT_CRT	bad or missing certificate
3347285612Sdelphij * XEVNT_PER	host certificate expired
3348285612Sdelphij * XEVNT_VFY	certificate not verified
3349285612Sdelphij */
3350285612Sdelphijint
3351285612Sdelphijcert_hike(
3352285612Sdelphij	struct peer *peer,	/* peer structure pointer */
3353285612Sdelphij	struct cert_info *yp	/* issuer certificate */
3354285612Sdelphij	)
3355285612Sdelphij{
3356285612Sdelphij	struct cert_info *xp;	/* subject certificate */
3357285612Sdelphij	X509	*cert;		/* X509 certificate */
3358285612Sdelphij	const u_char *ptr;
3359285612Sdelphij
3360132451Sroberto	/*
3361285612Sdelphij	 * Save the issuer on the new certificate, but remember the old
3362285612Sdelphij	 * one.
3363132451Sroberto	 */
3364285612Sdelphij	if (peer->issuer != NULL)
3365285612Sdelphij		free(peer->issuer);
3366285612Sdelphij	peer->issuer = estrdup(yp->issuer);
3367285612Sdelphij	xp = peer->xinfo;
3368285612Sdelphij	peer->xinfo = yp;
3369132451Sroberto
3370285612Sdelphij	/*
3371285612Sdelphij	 * If subject Y matches issuer Y, then the certificate trail is
3372285612Sdelphij	 * complete. If Y is not trusted, the server certificate has yet
3373285612Sdelphij	 * been signed, so keep trying. Otherwise, save the group key
3374285612Sdelphij	 * and light the valid bit. If the host certificate is trusted,
3375285612Sdelphij	 * do not execute a sign exchange. If no identity scheme is in
3376285612Sdelphij	 * use, light the identity and proventic bits.
3377285612Sdelphij	 */
3378285612Sdelphij	if (strcmp(yp->subject, yp->issuer) == 0) {
3379285612Sdelphij		if (!(yp->flags & CERT_TRUST))
3380285612Sdelphij			return (XEVNT_OK);
3381132451Sroberto
3382285612Sdelphij		/*
3383285612Sdelphij		 * If the server has an an identity scheme, fetch the
3384285612Sdelphij		 * identity credentials. If not, the identity is
3385285612Sdelphij		 * verified only by the trusted certificate. The next
3386285612Sdelphij		 * signature will set the server proventic.
3387285612Sdelphij		 */
3388285612Sdelphij		peer->crypto |= CRYPTO_FLAG_CERT;
3389285612Sdelphij		peer->grpkey = yp->grpkey;
3390285612Sdelphij		if (peer->ident == NULL || !(peer->crypto &
3391285612Sdelphij		    CRYPTO_FLAG_MASK))
3392285612Sdelphij			peer->crypto |= CRYPTO_FLAG_VRFY;
3393285612Sdelphij	}
3394132451Sroberto
3395285612Sdelphij	/*
3396285612Sdelphij	 * If X exists, verify signature X using public key Y.
3397285612Sdelphij	 */
3398285612Sdelphij	if (xp == NULL)
3399285612Sdelphij		return (XEVNT_OK);
3400182007Sroberto
3401285612Sdelphij	ptr = (u_char *)xp->cert.ptr;
3402285612Sdelphij	cert = d2i_X509(NULL, &ptr, ntohl(xp->cert.vallen));
3403285612Sdelphij	if (cert == NULL) {
3404285612Sdelphij		xp->flags |= CERT_ERROR;
3405285612Sdelphij		return (XEVNT_CRT);
3406285612Sdelphij	}
3407285612Sdelphij	if (X509_verify(cert, yp->pkey) <= 0) {
3408285612Sdelphij		X509_free(cert);
3409285612Sdelphij		xp->flags |= CERT_ERROR;
3410285612Sdelphij		return (XEVNT_VFY);
3411285612Sdelphij	}
3412285612Sdelphij	X509_free(cert);
3413182007Sroberto
3414285612Sdelphij	/*
3415285612Sdelphij	 * Signature X is valid only if it begins during the
3416285612Sdelphij	 * lifetime of Y.
3417285612Sdelphij	 */
3418285612Sdelphij	if ((calcomp(&(xp->first), &(yp->first)) < 0)
3419285612Sdelphij	|| (calcomp(&(xp->first), &(yp->last)) > 0)) {
3420285612Sdelphij		xp->flags |= CERT_ERROR;
3421285612Sdelphij		return (XEVNT_PER);
3422285612Sdelphij	}
3423285612Sdelphij	xp->flags |= CERT_SIGN;
3424285612Sdelphij	return (XEVNT_OK);
3425285612Sdelphij}
3426132451Sroberto
3427132451Sroberto
3428285612Sdelphij/*
3429285612Sdelphij * cert_parse - parse x509 certificate and create info/value structures.
3430285612Sdelphij *
3431285612Sdelphij * The server certificate includes the version number, issuer name,
3432285612Sdelphij * subject name, public key and valid date interval. If the issuer name
3433285612Sdelphij * is the same as the subject name, the certificate is self signed and
3434285612Sdelphij * valid only if the server is configured as trustable. If the names are
3435285612Sdelphij * different, another issuer has signed the server certificate and
3436285612Sdelphij * vouched for it. In this case the server certificate is valid if
3437285612Sdelphij * verified by the issuer public key.
3438285612Sdelphij *
3439285612Sdelphij * Returns certificate info/value pointer if valid, NULL if not.
3440285612Sdelphij */
3441285612Sdelphijstruct cert_info *		/* certificate information structure */
3442285612Sdelphijcert_parse(
3443285612Sdelphij	const u_char *asn1cert,	/* X509 certificate */
3444285612Sdelphij	long	len,		/* certificate length */
3445285612Sdelphij	tstamp_t fstamp		/* filestamp */
3446285612Sdelphij	)
3447285612Sdelphij{
3448285612Sdelphij	X509	*cert;		/* X509 certificate */
3449285612Sdelphij	struct cert_info *ret;	/* certificate info/value */
3450285612Sdelphij	BIO	*bp;
3451285612Sdelphij	char	pathbuf[MAXFILENAME];
3452285612Sdelphij	const u_char *ptr;
3453285612Sdelphij	char	*pch;
3454309008Sdelphij	int	cnt, i;
3455285612Sdelphij	struct calendar fscal;
3456132451Sroberto
3457285612Sdelphij	/*
3458285612Sdelphij	 * Decode ASN.1 objects and construct certificate structure.
3459285612Sdelphij	 */
3460285612Sdelphij	ptr = asn1cert;
3461285612Sdelphij	if ((cert = d2i_X509(NULL, &ptr, len)) == NULL) {
3462285612Sdelphij		msyslog(LOG_ERR, "cert_parse: %s",
3463285612Sdelphij		    ERR_error_string(ERR_get_error(), NULL));
3464285612Sdelphij		return (NULL);
3465285612Sdelphij	}
3466285612Sdelphij#ifdef DEBUG
3467285612Sdelphij	if (debug > 1)
3468285612Sdelphij		X509_print_fp(stdout, cert);
3469285612Sdelphij#endif
3470132451Sroberto
3471285612Sdelphij	/*
3472285612Sdelphij	 * Extract version, subject name and public key.
3473285612Sdelphij	 */
3474285612Sdelphij	ret = emalloc_zero(sizeof(*ret));
3475285612Sdelphij	if ((ret->pkey = X509_get_pubkey(cert)) == NULL) {
3476285612Sdelphij		msyslog(LOG_ERR, "cert_parse: %s",
3477285612Sdelphij		    ERR_error_string(ERR_get_error(), NULL));
3478285612Sdelphij		cert_free(ret);
3479285612Sdelphij		X509_free(cert);
3480285612Sdelphij		return (NULL);
3481285612Sdelphij	}
3482285612Sdelphij	ret->version = X509_get_version(cert);
3483285612Sdelphij	X509_NAME_oneline(X509_get_subject_name(cert), pathbuf,
3484285612Sdelphij	    sizeof(pathbuf));
3485285612Sdelphij	pch = strstr(pathbuf, "CN=");
3486285612Sdelphij	if (NULL == pch) {
3487285612Sdelphij		msyslog(LOG_NOTICE, "cert_parse: invalid subject %s",
3488285612Sdelphij		    pathbuf);
3489285612Sdelphij		cert_free(ret);
3490285612Sdelphij		X509_free(cert);
3491285612Sdelphij		return (NULL);
3492285612Sdelphij	}
3493285612Sdelphij	ret->subject = estrdup(pch + 3);
3494132451Sroberto
3495285612Sdelphij	/*
3496285612Sdelphij	 * Extract remaining objects. Note that the NTP serial number is
3497285612Sdelphij	 * the NTP seconds at the time of signing, but this might not be
3498285612Sdelphij	 * the case for other authority. We don't bother to check the
3499285612Sdelphij	 * objects at this time, since the real crunch can happen only
3500285612Sdelphij	 * when the time is valid but not yet certificated.
3501285612Sdelphij	 */
3502309008Sdelphij	ret->nid = X509_get_signature_nid(cert);
3503285612Sdelphij	ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid);
3504285612Sdelphij	ret->serial =
3505285612Sdelphij	    (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert));
3506285612Sdelphij	X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf,
3507285612Sdelphij	    sizeof(pathbuf));
3508285612Sdelphij	if ((pch = strstr(pathbuf, "CN=")) == NULL) {
3509285612Sdelphij		msyslog(LOG_NOTICE, "cert_parse: invalid issuer %s",
3510285612Sdelphij		    pathbuf);
3511285612Sdelphij		cert_free(ret);
3512285612Sdelphij		X509_free(cert);
3513285612Sdelphij		return (NULL);
3514285612Sdelphij	}
3515285612Sdelphij	ret->issuer = estrdup(pch + 3);
3516316069Sdelphij	asn_to_calendar(X509_get0_notBefore(cert), &(ret->first));
3517316069Sdelphij	asn_to_calendar(X509_get0_notAfter(cert), &(ret->last));
3518285612Sdelphij
3519285612Sdelphij	/*
3520285612Sdelphij	 * Extract extension fields. These are ad hoc ripoffs of
3521285612Sdelphij	 * currently assigned functions and will certainly be changed
3522285612Sdelphij	 * before prime time.
3523285612Sdelphij	 */
3524285612Sdelphij	cnt = X509_get_ext_count(cert);
3525285612Sdelphij	for (i = 0; i < cnt; i++) {
3526309008Sdelphij		X509_EXTENSION *ext;
3527309008Sdelphij		ASN1_OBJECT *obj;
3528309008Sdelphij		int nid;
3529309008Sdelphij		ASN1_OCTET_STRING *data;
3530309008Sdelphij
3531285612Sdelphij		ext = X509_get_ext(cert, i);
3532309008Sdelphij		obj = X509_EXTENSION_get_object(ext);
3533309008Sdelphij		nid = OBJ_obj2nid(obj);
3534285612Sdelphij
3535309008Sdelphij		switch (nid) {
3536309008Sdelphij
3537285612Sdelphij		/*
3538285612Sdelphij		 * If a key_usage field is present, we decode whether
3539285612Sdelphij		 * this is a trusted or private certificate. This is
3540285612Sdelphij		 * dorky; all we want is to compare NIDs, but OpenSSL
3541285612Sdelphij		 * insists on BIO text strings.
3542285612Sdelphij		 */
3543285612Sdelphij		case NID_ext_key_usage:
3544285612Sdelphij			bp = BIO_new(BIO_s_mem());
3545285612Sdelphij			X509V3_EXT_print(bp, ext, 0, 0);
3546285612Sdelphij			BIO_gets(bp, pathbuf, sizeof(pathbuf));
3547285612Sdelphij			BIO_free(bp);
3548285612Sdelphij			if (strcmp(pathbuf, "Trust Root") == 0)
3549285612Sdelphij				ret->flags |= CERT_TRUST;
3550285612Sdelphij			else if (strcmp(pathbuf, "Private") == 0)
3551285612Sdelphij				ret->flags |= CERT_PRIV;
3552285612Sdelphij			DPRINTF(1, ("cert_parse: %s: %s\n",
3553309008Sdelphij				    OBJ_nid2ln(nid), pathbuf));
3554285612Sdelphij			break;
3555285612Sdelphij
3556285612Sdelphij		/*
3557285612Sdelphij		 * If a NID_subject_key_identifier field is present, it
3558285612Sdelphij		 * contains the GQ public key.
3559285612Sdelphij		 */
3560285612Sdelphij		case NID_subject_key_identifier:
3561309008Sdelphij			data = X509_EXTENSION_get_data(ext);
3562309008Sdelphij			ret->grpkey = BN_bin2bn(&data->data[2],
3563309008Sdelphij			    data->length - 2, NULL);
3564285612Sdelphij			/* fall through */
3565285612Sdelphij		default:
3566285612Sdelphij			DPRINTF(1, ("cert_parse: %s\n",
3567309008Sdelphij				    OBJ_nid2ln(nid)));
3568285612Sdelphij			break;
3569132451Sroberto		}
3570132451Sroberto	}
3571285612Sdelphij	if (strcmp(ret->subject, ret->issuer) == 0) {
3572132451Sroberto
3573285612Sdelphij		/*
3574285612Sdelphij		 * If certificate is self signed, verify signature.
3575285612Sdelphij		 */
3576285612Sdelphij		if (X509_verify(cert, ret->pkey) <= 0) {
3577285612Sdelphij			msyslog(LOG_NOTICE,
3578285612Sdelphij			    "cert_parse: signature not verified %s",
3579285612Sdelphij			    ret->subject);
3580285612Sdelphij			cert_free(ret);
3581285612Sdelphij			X509_free(cert);
3582285612Sdelphij			return (NULL);
3583285612Sdelphij		}
3584285612Sdelphij	} else {
3585285612Sdelphij
3586285612Sdelphij		/*
3587285612Sdelphij		 * Check for a certificate loop.
3588285612Sdelphij		 */
3589285612Sdelphij		if (strcmp((const char *)hostval.ptr, ret->issuer) == 0) {
3590285612Sdelphij			msyslog(LOG_NOTICE,
3591285612Sdelphij			    "cert_parse: certificate trail loop %s",
3592285612Sdelphij			    ret->subject);
3593285612Sdelphij			cert_free(ret);
3594285612Sdelphij			X509_free(cert);
3595285612Sdelphij			return (NULL);
3596285612Sdelphij		}
3597285612Sdelphij	}
3598285612Sdelphij
3599132451Sroberto	/*
3600285612Sdelphij	 * Verify certificate valid times. Note that certificates cannot
3601285612Sdelphij	 * be retroactive.
3602132451Sroberto	 */
3603285612Sdelphij	(void)ntpcal_ntp_to_date(&fscal, fstamp, NULL);
3604285612Sdelphij	if ((calcomp(&(ret->first), &(ret->last)) > 0)
3605285612Sdelphij	|| (calcomp(&(ret->first), &fscal) < 0)) {
3606285612Sdelphij		msyslog(LOG_NOTICE,
3607285612Sdelphij		    "cert_parse: invalid times %s first %u-%02u-%02uT%02u:%02u:%02u last %u-%02u-%02uT%02u:%02u:%02u fstamp %u-%02u-%02uT%02u:%02u:%02u",
3608285612Sdelphij		    ret->subject,
3609285612Sdelphij		    ret->first.year, ret->first.month, ret->first.monthday,
3610285612Sdelphij		    ret->first.hour, ret->first.minute, ret->first.second,
3611285612Sdelphij		    ret->last.year, ret->last.month, ret->last.monthday,
3612285612Sdelphij		    ret->last.hour, ret->last.minute, ret->last.second,
3613285612Sdelphij		    fscal.year, fscal.month, fscal.monthday,
3614285612Sdelphij		    fscal.hour, fscal.minute, fscal.second);
3615285612Sdelphij		cert_free(ret);
3616285612Sdelphij		X509_free(cert);
3617285612Sdelphij		return (NULL);
3618285612Sdelphij	}
3619285612Sdelphij
3620285612Sdelphij	/*
3621285612Sdelphij	 * Build the value structure to sign and send later.
3622285612Sdelphij	 */
3623285612Sdelphij	ret->cert.fstamp = htonl(fstamp);
3624285612Sdelphij	ret->cert.vallen = htonl(len);
3625285612Sdelphij	ret->cert.ptr = emalloc(len);
3626285612Sdelphij	memcpy(ret->cert.ptr, asn1cert, len);
3627285612Sdelphij	X509_free(cert);
3628285612Sdelphij	return (ret);
3629132451Sroberto}
3630132451Sroberto
3631132451Sroberto
3632132451Sroberto/*
3633132451Sroberto * cert_free - free certificate information structure
3634132451Sroberto */
3635132451Srobertovoid
3636132451Srobertocert_free(
3637132451Sroberto	struct cert_info *cinf	/* certificate info/value structure */
3638132451Sroberto	)
3639132451Sroberto{
3640132451Sroberto	if (cinf->pkey != NULL)
3641132451Sroberto		EVP_PKEY_free(cinf->pkey);
3642132451Sroberto	if (cinf->subject != NULL)
3643132451Sroberto		free(cinf->subject);
3644132451Sroberto	if (cinf->issuer != NULL)
3645132451Sroberto		free(cinf->issuer);
3646132451Sroberto	if (cinf->grpkey != NULL)
3647285612Sdelphij		BN_free(cinf->grpkey);
3648132451Sroberto	value_free(&cinf->cert);
3649132451Sroberto	free(cinf);
3650132451Sroberto}
3651132451Sroberto
3652132451Sroberto
3653132451Sroberto/*
3654285612Sdelphij * crypto_key - load cryptographic parameters and keys
3655132451Sroberto *
3656285612Sdelphij * This routine searches the key cache for matching name in the form
3657285612Sdelphij * ntpkey_<key>_<name>, where <key> is one of host, sign, iff, gq, mv,
3658285612Sdelphij * and <name> is the host/group name. If not found, it tries to load a
3659285612Sdelphij * PEM-encoded file of the same name and extracts the filestamp from
3660285612Sdelphij * the first line of the file name. It returns the key pointer if valid,
3661285612Sdelphij * NULL if not.
3662132451Sroberto */
3663285612Sdelphijstatic struct pkey_info *
3664132451Srobertocrypto_key(
3665132451Sroberto	char	*cp,		/* file name */
3666285612Sdelphij	char	*passwd1,	/* password */
3667285612Sdelphij	sockaddr_u *addr 	/* IP address */
3668132451Sroberto	)
3669132451Sroberto{
3670132451Sroberto	FILE	*str;		/* file handle */
3671285612Sdelphij	struct pkey_info *pkp;	/* generic key */
3672132451Sroberto	EVP_PKEY *pkey = NULL;	/* public/private key */
3673285612Sdelphij	tstamp_t fstamp;
3674132451Sroberto	char	filename[MAXFILENAME]; /* name of key file */
3675132451Sroberto	char	linkname[MAXFILENAME]; /* filestamp buffer) */
3676132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3677132451Sroberto	char	*ptr;
3678132451Sroberto
3679132451Sroberto	/*
3680285612Sdelphij	 * Search the key cache for matching key and name.
3681285612Sdelphij	 */
3682285612Sdelphij	for (pkp = pkinfo; pkp != NULL; pkp = pkp->link) {
3683285612Sdelphij		if (strcmp(cp, pkp->name) == 0)
3684285612Sdelphij			return (pkp);
3685285612Sdelphij	}
3686285612Sdelphij
3687285612Sdelphij	/*
3688132451Sroberto	 * Open the key file. If the first character of the file name is
3689132451Sroberto	 * not '/', prepend the keys directory string. If something goes
3690132451Sroberto	 * wrong, abandon ship.
3691132451Sroberto	 */
369282498Sroberto	if (*cp == '/')
3693285612Sdelphij		strlcpy(filename, cp, sizeof(filename));
369482498Sroberto	else
3695285612Sdelphij		snprintf(filename, sizeof(filename), "%s/%s", keysdir,
3696285612Sdelphij		    cp);
369782498Sroberto	str = fopen(filename, "r");
3698132451Sroberto	if (str == NULL)
3699132451Sroberto		return (NULL);
3700132451Sroberto
3701132451Sroberto	/*
3702132451Sroberto	 * Read the filestamp, which is contained in the first line.
3703132451Sroberto	 */
3704285612Sdelphij	if ((ptr = fgets(linkname, sizeof(linkname), str)) == NULL) {
3705285612Sdelphij		msyslog(LOG_ERR, "crypto_key: empty file %s",
3706132451Sroberto		    filename);
3707285612Sdelphij		fclose(str);
3708132451Sroberto		return (NULL);
370982498Sroberto	}
3710132451Sroberto	if ((ptr = strrchr(ptr, '.')) == NULL) {
3711285612Sdelphij		msyslog(LOG_ERR, "crypto_key: no filestamp %s",
3712132451Sroberto		    filename);
3713285612Sdelphij		fclose(str);
3714132451Sroberto		return (NULL);
3715132451Sroberto	}
3716285612Sdelphij	if (sscanf(++ptr, "%u", &fstamp) != 1) {
3717285612Sdelphij		msyslog(LOG_ERR, "crypto_key: invalid filestamp %s",
3718132451Sroberto		    filename);
3719285612Sdelphij		fclose(str);
3720132451Sroberto		return (NULL);
3721132451Sroberto	}
372282498Sroberto
372382498Sroberto	/*
3724285612Sdelphij	 * Read and decrypt PEM-encoded private key. If it fails to
3725285612Sdelphij	 * decrypt, game over.
372682498Sroberto	 */
3727285612Sdelphij	pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd1);
3728132451Sroberto	fclose(str);
3729132451Sroberto	if (pkey == NULL) {
3730285612Sdelphij		msyslog(LOG_ERR, "crypto_key: %s",
3731132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3732285612Sdelphij		exit (-1);
373382498Sroberto	}
373482498Sroberto
373582498Sroberto	/*
3736285612Sdelphij	 * Make a new entry in the key cache.
3737285612Sdelphij	 */
3738285612Sdelphij	pkp = emalloc(sizeof(struct pkey_info));
3739285612Sdelphij	pkp->link = pkinfo;
3740285612Sdelphij	pkinfo = pkp;
3741285612Sdelphij	pkp->pkey = pkey;
3742285612Sdelphij	pkp->name = estrdup(cp);
3743285612Sdelphij	pkp->fstamp = fstamp;
3744285612Sdelphij
3745285612Sdelphij	/*
3746132451Sroberto	 * Leave tracks in the cryptostats.
374782498Sroberto	 */
3748132451Sroberto	if ((ptr = strrchr(linkname, '\n')) != NULL)
3749132451Sroberto		*ptr = '\0';
3750285612Sdelphij	snprintf(statstr, sizeof(statstr), "%s mod %d", &linkname[2],
3751132451Sroberto	    EVP_PKEY_size(pkey) * 8);
3752285612Sdelphij	record_crypto_stats(addr, statstr);
3753285612Sdelphij
3754285612Sdelphij	DPRINTF(1, ("crypto_key: %s\n", statstr));
3755132451Sroberto#ifdef DEBUG
3756132451Sroberto	if (debug > 1) {
3757309008Sdelphij		if (EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA)
3758309008Sdelphij			DSA_print_fp(stdout, EVP_PKEY_get0_DSA(pkey), 0);
3759309008Sdelphij		else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA)
3760309008Sdelphij			RSA_print_fp(stdout, EVP_PKEY_get0_RSA(pkey), 0);
376182498Sroberto	}
3762132451Sroberto#endif
3763285612Sdelphij	return (pkp);
3764132451Sroberto}
376582498Sroberto
3766132451Sroberto
3767132451Sroberto/*
3768285612Sdelphij ***********************************************************************
3769285612Sdelphij *								       *
3770285612Sdelphij * The following routines are used only at initialization time         *
3771285612Sdelphij *								       *
3772285612Sdelphij ***********************************************************************
3773285612Sdelphij */
3774285612Sdelphij/*
3775132451Sroberto * crypto_cert - load certificate from file
3776132451Sroberto *
3777285612Sdelphij * This routine loads an X.509 RSA or DSA certificate from a file and
3778132451Sroberto * constructs a info/cert value structure for this machine. The
3779132451Sroberto * structure includes a filestamp extracted from the file name. Later
3780285612Sdelphij * the certificate can be sent to another machine on request.
3781132451Sroberto *
3782132451Sroberto * Returns certificate info/value pointer if valid, NULL if not.
3783132451Sroberto */
3784132451Srobertostatic struct cert_info *	/* certificate information */
3785132451Srobertocrypto_cert(
3786132451Sroberto	char	*cp		/* file name */
3787132451Sroberto	)
3788132451Sroberto{
3789132451Sroberto	struct cert_info *ret; /* certificate information */
3790132451Sroberto	FILE	*str;		/* file handle */
3791132451Sroberto	char	filename[MAXFILENAME]; /* name of certificate file */
3792132451Sroberto	char	linkname[MAXFILENAME]; /* filestamp buffer */
3793132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3794132451Sroberto	tstamp_t fstamp;	/* filestamp */
3795132451Sroberto	long	len;
3796132451Sroberto	char	*ptr;
3797132451Sroberto	char	*name, *header;
3798132451Sroberto	u_char	*data;
3799132451Sroberto
380082498Sroberto	/*
3801132451Sroberto	 * Open the certificate file. If the first character of the file
3802132451Sroberto	 * name is not '/', prepend the keys directory string. If
3803132451Sroberto	 * something goes wrong, abandon ship.
380482498Sroberto	 */
3805132451Sroberto	if (*cp == '/')
3806285612Sdelphij		strlcpy(filename, cp, sizeof(filename));
3807132451Sroberto	else
3808285612Sdelphij		snprintf(filename, sizeof(filename), "%s/%s", keysdir,
3809285612Sdelphij		    cp);
3810132451Sroberto	str = fopen(filename, "r");
3811132451Sroberto	if (str == NULL)
3812132451Sroberto		return (NULL);
381382498Sroberto
3814132451Sroberto	/*
3815132451Sroberto	 * Read the filestamp, which is contained in the first line.
3816132451Sroberto	 */
3817285612Sdelphij	if ((ptr = fgets(linkname, sizeof(linkname), str)) == NULL) {
3818285612Sdelphij		msyslog(LOG_ERR, "crypto_cert: empty file %s",
3819132451Sroberto		    filename);
3820285612Sdelphij		fclose(str);
3821132451Sroberto		return (NULL);
3822132451Sroberto	}
3823132451Sroberto	if ((ptr = strrchr(ptr, '.')) == NULL) {
3824285612Sdelphij		msyslog(LOG_ERR, "crypto_cert: no filestamp %s",
3825132451Sroberto		    filename);
3826285612Sdelphij		fclose(str);
3827132451Sroberto		return (NULL);
3828132451Sroberto	}
3829132451Sroberto	if (sscanf(++ptr, "%u", &fstamp) != 1) {
3830285612Sdelphij		msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s",
3831132451Sroberto		    filename);
3832285612Sdelphij		fclose(str);
3833132451Sroberto		return (NULL);
3834132451Sroberto	}
383582498Sroberto
383682498Sroberto	/*
3837132451Sroberto	 * Read PEM-encoded certificate and install.
383882498Sroberto	 */
3839132451Sroberto	if (!PEM_read(str, &name, &header, &data, &len)) {
3840285612Sdelphij		msyslog(LOG_ERR, "crypto_cert: %s",
3841132451Sroberto		    ERR_error_string(ERR_get_error(), NULL));
3842285612Sdelphij		fclose(str);
3843132451Sroberto		return (NULL);
3844132451Sroberto	}
3845285612Sdelphij	fclose(str);
3846132451Sroberto	free(header);
3847285612Sdelphij	if (strcmp(name, "CERTIFICATE") != 0) {
3848285612Sdelphij		msyslog(LOG_NOTICE, "crypto_cert: wrong PEM type %s",
3849132451Sroberto		    name);
3850132451Sroberto		free(name);
3851132451Sroberto		free(data);
3852132451Sroberto		return (NULL);
3853132451Sroberto	}
3854132451Sroberto	free(name);
385582498Sroberto
385682498Sroberto	/*
3857285612Sdelphij	 * Parse certificate and generate info/value structure. The
3858285612Sdelphij	 * pointer and copy nonsense is due something broken in Solaris.
385982498Sroberto	 */
3860132451Sroberto	ret = cert_parse(data, len, fstamp);
3861132451Sroberto	free(data);
3862132451Sroberto	if (ret == NULL)
3863132451Sroberto		return (NULL);
3864182007Sroberto
3865132451Sroberto	if ((ptr = strrchr(linkname, '\n')) != NULL)
3866132451Sroberto		*ptr = '\0';
3867285612Sdelphij	snprintf(statstr, sizeof(statstr), "%s 0x%x len %lu",
3868285612Sdelphij	    &linkname[2], ret->flags, len);
3869132451Sroberto	record_crypto_stats(NULL, statstr);
3870285612Sdelphij	DPRINTF(1, ("crypto_cert: %s\n", statstr));
3871132451Sroberto	return (ret);
387282498Sroberto}
387382498Sroberto
387482498Sroberto
387582498Sroberto/*
3876285612Sdelphij * crypto_setup - load keys, certificate and identity parameters
3877132451Sroberto *
3878285612Sdelphij * This routine loads the public/private host key and certificate. If
3879285612Sdelphij * available, it loads the public/private sign key, which defaults to
3880285612Sdelphij * the host key. The host key must be RSA, but the sign key can be
3881285612Sdelphij * either RSA or DSA. If a trusted certificate, it loads the identity
3882285612Sdelphij * parameters. In either case, the public key on the certificate must
3883285612Sdelphij * agree with the sign key.
3884285612Sdelphij *
3885285612Sdelphij * Required but missing files and inconsistent data and errors are
3886285612Sdelphij * fatal. Allowing configuration to continue would be hazardous and
3887285612Sdelphij * require really messy error checks.
388882498Sroberto */
3889285612Sdelphijvoid
3890285612Sdelphijcrypto_setup(void)
389182498Sroberto{
3892285612Sdelphij	struct pkey_info *pinfo; /* private/public key */
3893285612Sdelphij	char	filename[MAXFILENAME]; /* file name buffer */
3894285612Sdelphij	char	hostname[MAXFILENAME]; /* host name buffer */
3895285612Sdelphij	char	*randfile;
3896132451Sroberto	char	statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
3897285612Sdelphij	l_fp	seed;		/* crypto PRNG seed as NTP timestamp */
3898132451Sroberto	u_int	len;
3899285612Sdelphij	int	bytes;
3900285612Sdelphij	u_char	*ptr;
390182498Sroberto
390282498Sroberto	/*
3903285612Sdelphij	 * Check for correct OpenSSL version and avoid initialization in
3904285612Sdelphij	 * the case of multiple crypto commands.
390582498Sroberto	 */
3906285612Sdelphij	if (crypto_flags & CRYPTO_FLAG_ENAB) {
3907285612Sdelphij		msyslog(LOG_NOTICE,
3908285612Sdelphij		    "crypto_setup: spurious crypto command");
390982498Sroberto		return;
391082498Sroberto	}
3911285612Sdelphij	ssl_check_version();
391282498Sroberto
391382498Sroberto	/*
3914285612Sdelphij	 * Load required random seed file and seed the random number
3915285612Sdelphij	 * generator. Be default, it is found as .rnd in the user home
3916285612Sdelphij	 * directory. The root home directory may be / or /root,
3917285612Sdelphij	 * depending on the system. Wiggle the contents a bit and write
3918285612Sdelphij	 * it back so the sequence does not repeat when we next restart.
391982498Sroberto	 */
3920285612Sdelphij	if (!RAND_status()) {
3921285612Sdelphij		if (rand_file == NULL) {
3922285612Sdelphij			RAND_file_name(filename, sizeof(filename));
3923285612Sdelphij			randfile = filename;
3924285612Sdelphij		} else if (*rand_file != '/') {
3925285612Sdelphij			snprintf(filename, sizeof(filename), "%s/%s",
3926285612Sdelphij			    keysdir, rand_file);
3927285612Sdelphij			randfile = filename;
3928285612Sdelphij		} else
3929285612Sdelphij			randfile = rand_file;
3930182007Sroberto
3931285612Sdelphij		if ((bytes = RAND_load_file(randfile, -1)) == 0) {
3932285612Sdelphij			msyslog(LOG_ERR,
3933285612Sdelphij			    "crypto_setup: random seed file %s missing",
3934285612Sdelphij			    randfile);
3935285612Sdelphij			exit (-1);
3936285612Sdelphij		}
3937285612Sdelphij		arc4random_buf(&seed, sizeof(l_fp));
3938285612Sdelphij		RAND_seed(&seed, sizeof(l_fp));
3939285612Sdelphij		RAND_write_file(randfile);
3940285612Sdelphij		DPRINTF(1, ("crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
3941316069Sdelphij			    OpenSSL_version_num(), randfile, bytes));
3942316069Sdelphij
394382498Sroberto	}
394482498Sroberto
394582498Sroberto	/*
3946132451Sroberto	 * Initialize structures.
394782498Sroberto	 */
3948285612Sdelphij	gethostname(hostname, sizeof(hostname));
3949285612Sdelphij	if (host_filename != NULL)
3950285612Sdelphij		strlcpy(hostname, host_filename, sizeof(hostname));
3951132451Sroberto	if (passwd == NULL)
3952285612Sdelphij		passwd = estrdup(hostname);
3953132451Sroberto	memset(&hostval, 0, sizeof(hostval));
3954132451Sroberto	memset(&pubkey, 0, sizeof(pubkey));
3955132451Sroberto	memset(&tai_leap, 0, sizeof(tai_leap));
3956132451Sroberto
3957132451Sroberto	/*
3958285612Sdelphij	 * Load required host key from file "ntpkey_host_<hostname>". If
3959285612Sdelphij	 * no host key file is not found or has invalid password, life
3960285612Sdelphij	 * as we know it ends. The host key also becomes the default
3961285612Sdelphij	 * sign key.
3962132451Sroberto	 */
3963285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_host_%s", hostname);
3964285612Sdelphij	pinfo = crypto_key(filename, passwd, NULL);
3965285612Sdelphij	if (pinfo == NULL) {
3966132451Sroberto		msyslog(LOG_ERR,
3967132451Sroberto		    "crypto_setup: host key file %s not found or corrupt",
3968285612Sdelphij		    filename);
3969132451Sroberto		exit (-1);
3970132451Sroberto	}
3971309008Sdelphij	if (EVP_PKEY_base_id(pinfo->pkey) != EVP_PKEY_RSA) {
3972132451Sroberto		msyslog(LOG_ERR,
3973132451Sroberto		    "crypto_setup: host key is not RSA key type");
3974132451Sroberto		exit (-1);
3975132451Sroberto	}
3976285612Sdelphij	host_pkey = pinfo->pkey;
3977285612Sdelphij	sign_pkey = host_pkey;
3978285612Sdelphij	hostval.fstamp = htonl(pinfo->fstamp);
3979132451Sroberto
3980132451Sroberto	/*
3981132451Sroberto	 * Construct public key extension field for agreement scheme.
3982132451Sroberto	 */
3983132451Sroberto	len = i2d_PublicKey(host_pkey, NULL);
3984132451Sroberto	ptr = emalloc(len);
3985132451Sroberto	pubkey.ptr = ptr;
3986132451Sroberto	i2d_PublicKey(host_pkey, &ptr);
3987285612Sdelphij	pubkey.fstamp = hostval.fstamp;
3988132451Sroberto	pubkey.vallen = htonl(len);
3989132451Sroberto
3990132451Sroberto	/*
3991132451Sroberto	 * Load optional sign key from file "ntpkey_sign_<hostname>". If
3992285612Sdelphij	 * available, it becomes the sign key.
3993132451Sroberto	 */
3994285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_sign_%s", hostname);
3995285612Sdelphij	pinfo = crypto_key(filename, passwd, NULL);
3996285612Sdelphij	if (pinfo != NULL)
3997285612Sdelphij		sign_pkey = pinfo->pkey;
3998132451Sroberto
3999132451Sroberto	/*
4000285612Sdelphij	 * Load required certificate from file "ntpkey_cert_<hostname>".
4001132451Sroberto	 */
4002285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_cert_%s", hostname);
4003285612Sdelphij	cinfo = crypto_cert(filename);
4004285612Sdelphij	if (cinfo == NULL) {
4005285612Sdelphij		msyslog(LOG_ERR,
4006285612Sdelphij		    "crypto_setup: certificate file %s not found or corrupt",
4007285612Sdelphij		    filename);
4008285612Sdelphij		exit (-1);
4009132451Sroberto	}
4010285612Sdelphij	cert_host = cinfo;
4011285612Sdelphij	sign_digest = cinfo->digest;
4012285612Sdelphij	sign_siglen = EVP_PKEY_size(sign_pkey);
4013285612Sdelphij	if (cinfo->flags & CERT_PRIV)
4014285612Sdelphij		crypto_flags |= CRYPTO_FLAG_PRIV;
4015132451Sroberto
4016132451Sroberto	/*
4017285612Sdelphij	 * The certificate must be self-signed.
4018132451Sroberto	 */
4019285612Sdelphij	if (strcmp(cinfo->subject, cinfo->issuer) != 0) {
4020285612Sdelphij		msyslog(LOG_ERR,
4021285612Sdelphij		    "crypto_setup: certificate %s is not self-signed",
4022285612Sdelphij		    filename);
4023285612Sdelphij		exit (-1);
4024132451Sroberto	}
4025285612Sdelphij	hostval.ptr = estrdup(cinfo->subject);
4026285612Sdelphij	hostval.vallen = htonl(strlen(cinfo->subject));
4027285612Sdelphij	sys_hostname = hostval.ptr;
4028285612Sdelphij	ptr = (u_char *)strchr(sys_hostname, '@');
4029285612Sdelphij	if (ptr != NULL)
4030285612Sdelphij		sys_groupname = estrdup((char *)++ptr);
4031285612Sdelphij	if (ident_filename != NULL)
4032285612Sdelphij		strlcpy(hostname, ident_filename, sizeof(hostname));
4033132451Sroberto
4034132451Sroberto	/*
4035285612Sdelphij	 * Load optional IFF parameters from file
4036285612Sdelphij	 * "ntpkey_iffkey_<hostname>".
4037132451Sroberto	 */
4038285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_iffkey_%s",
4039285612Sdelphij	    hostname);
4040285612Sdelphij	iffkey_info = crypto_key(filename, passwd, NULL);
4041285612Sdelphij	if (iffkey_info != NULL)
4042285612Sdelphij		crypto_flags |= CRYPTO_FLAG_IFF;
4043132451Sroberto
4044132451Sroberto	/*
4045285612Sdelphij	 * Load optional GQ parameters from file
4046285612Sdelphij	 * "ntpkey_gqkey_<hostname>".
4047132451Sroberto	 */
4048285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_gqkey_%s",
4049285612Sdelphij	    hostname);
4050285612Sdelphij	gqkey_info = crypto_key(filename, passwd, NULL);
4051285612Sdelphij	if (gqkey_info != NULL)
4052285612Sdelphij		crypto_flags |= CRYPTO_FLAG_GQ;
4053132451Sroberto
4054132451Sroberto	/*
4055285612Sdelphij	 * Load optional MV parameters from file
4056285612Sdelphij	 * "ntpkey_mvkey_<hostname>".
4057132451Sroberto	 */
4058285612Sdelphij	snprintf(filename, sizeof(filename), "ntpkey_mvkey_%s",
4059285612Sdelphij	    hostname);
4060285612Sdelphij	mvkey_info = crypto_key(filename, passwd, NULL);
4061285612Sdelphij	if (mvkey_info != NULL)
4062285612Sdelphij		crypto_flags |= CRYPTO_FLAG_MV;
4063132451Sroberto
4064132451Sroberto	/*
4065285612Sdelphij	 * We met the enemy and he is us. Now strike up the dance.
4066132451Sroberto	 */
4067285612Sdelphij	crypto_flags |= CRYPTO_FLAG_ENAB | (cinfo->nid << 16);
4068285612Sdelphij	snprintf(statstr, sizeof(statstr), "setup 0x%x host %s %s",
4069285612Sdelphij	    crypto_flags, hostname, OBJ_nid2ln(cinfo->nid));
4070285612Sdelphij	record_crypto_stats(NULL, statstr);
4071285612Sdelphij	DPRINTF(1, ("crypto_setup: %s\n", statstr));
407282498Sroberto}
407382498Sroberto
407482498Sroberto
407582498Sroberto/*
4076285612Sdelphij * crypto_config - configure data from the crypto command.
407782498Sroberto */
407882498Srobertovoid
407982498Srobertocrypto_config(
4080132451Sroberto	int	item,		/* configuration item */
4081285612Sdelphij	char	*cp		/* item name */
408282498Sroberto	)
408382498Sroberto{
4084285612Sdelphij	int	nid;
408582498Sroberto
4086285612Sdelphij	DPRINTF(1, ("crypto_config: item %d %s\n", item, cp));
408782498Sroberto
4088285612Sdelphij	switch (item) {
4089132451Sroberto
4090132451Sroberto	/*
4091285612Sdelphij	 * Set host name (host).
4092132451Sroberto	 */
409382498Sroberto	case CRYPTO_CONF_PRIV:
4094285612Sdelphij		if (NULL != host_filename)
4095285612Sdelphij			free(host_filename);
4096285612Sdelphij		host_filename = estrdup(cp);
409782498Sroberto		break;
409882498Sroberto
409982498Sroberto	/*
4100285612Sdelphij	 * Set group name (ident).
410182498Sroberto	 */
4102285612Sdelphij	case CRYPTO_CONF_IDENT:
4103285612Sdelphij		if (NULL != ident_filename)
4104285612Sdelphij			free(ident_filename);
4105285612Sdelphij		ident_filename = estrdup(cp);
410682498Sroberto		break;
410782498Sroberto
410882498Sroberto	/*
4109285612Sdelphij	 * Set private key password (pw).
411082498Sroberto	 */
4111285612Sdelphij	case CRYPTO_CONF_PW:
4112285612Sdelphij		if (NULL != passwd)
4113285612Sdelphij			free(passwd);
4114285612Sdelphij		passwd = estrdup(cp);
411582498Sroberto		break;
411682498Sroberto
411782498Sroberto	/*
4118285612Sdelphij	 * Set random seed file name (randfile).
411982498Sroberto	 */
4120285612Sdelphij	case CRYPTO_CONF_RAND:
4121285612Sdelphij		if (NULL != rand_file)
4122285612Sdelphij			free(rand_file);
4123285612Sdelphij		rand_file = estrdup(cp);
412482498Sroberto		break;
412582498Sroberto
412682498Sroberto	/*
4127285612Sdelphij	 * Set message digest NID.
412882498Sroberto	 */
4129285612Sdelphij	case CRYPTO_CONF_NID:
4130285612Sdelphij		nid = OBJ_sn2nid(cp);
4131285612Sdelphij		if (nid == 0)
4132285612Sdelphij			msyslog(LOG_ERR,
4133285612Sdelphij			    "crypto_config: invalid digest name %s", cp);
4134285612Sdelphij		else
4135285612Sdelphij			crypto_nid = nid;
413682498Sroberto		break;
413782498Sroberto	}
413882498Sroberto}
4139289997Sglebius
4140289997Sglebius/*
4141289997Sglebius * Get the  payload size (internal value length) of an extension packet.
4142289997Sglebius * If the inner value size does not match the outer packet size (that
4143289997Sglebius * is, the value would end behind the frame given by the opcode/size
4144289997Sglebius * field) the function will effectively return UINT_MAX. If the frame is
4145289997Sglebius * too short to hold a variable-sized value, the return value is zero.
4146289997Sglebius */
4147289997Sglebiusstatic u_int
4148289997Sglebiusexten_payload_size(
4149289997Sglebius	const struct exten * ep)
4150289997Sglebius{
4151289997Sglebius	typedef const u_char *BPTR;
4152289997Sglebius
4153289997Sglebius	size_t extn_size;
4154289997Sglebius	size_t data_size;
4155289997Sglebius	size_t head_size;
4156289997Sglebius
4157289997Sglebius	data_size = 0;
4158289997Sglebius	if (NULL != ep) {
4159289997Sglebius		head_size = (BPTR)(&ep->vallen + 1) - (BPTR)ep;
4160289997Sglebius		extn_size = (uint16_t)(ntohl(ep->opcode) & 0x0000ffff);
4161289997Sglebius		if (extn_size >= head_size) {
4162289997Sglebius			data_size = (uint32_t)ntohl(ep->vallen);
4163289997Sglebius			if (data_size > extn_size - head_size)
4164289997Sglebius				data_size = ~(size_t)0u;
4165289997Sglebius		}
4166289997Sglebius	}
4167289997Sglebius	return (u_int)data_size;
4168289997Sglebius}
4169285612Sdelphij# else	/* !AUTOKEY follows */
417082498Srobertoint ntp_crypto_bs_pubkey;
4171285612Sdelphij# endif	/* !AUTOKEY */
4172