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