182498Sroberto/* 282498Sroberto * ntp_crypto.c - NTP version 4 public key routines 382498Sroberto */ 482498Sroberto#ifdef HAVE_CONFIG_H 582498Sroberto#include <config.h> 682498Sroberto#endif 782498Sroberto 8280849Scy#ifdef AUTOKEY 982498Sroberto#include <stdio.h> 10280849Scy#include <stdlib.h> /* strtoul */ 1182498Sroberto#include <sys/types.h> 12132451Sroberto#include <sys/param.h> 1382498Sroberto#include <unistd.h> 1482498Sroberto#include <fcntl.h> 1582498Sroberto 1682498Sroberto#include "ntpd.h" 1782498Sroberto#include "ntp_stdlib.h" 18132451Sroberto#include "ntp_unixtime.h" 1982498Sroberto#include "ntp_string.h" 20280849Scy#include "ntp_random.h" 21280849Scy#include "ntp_assert.h" 22280849Scy#include "ntp_calendar.h" 23280849Scy#include "ntp_leapsec.h" 2482498Sroberto 25316068Sdelphij#include "openssl/asn1.h" 26132451Sroberto#include "openssl/bn.h" 27316068Sdelphij#include "openssl/crypto.h" 28132451Sroberto#include "openssl/err.h" 29132451Sroberto#include "openssl/evp.h" 30316068Sdelphij#include "openssl/opensslv.h" 31132451Sroberto#include "openssl/pem.h" 32132451Sroberto#include "openssl/rand.h" 33316068Sdelphij#include "openssl/x509.h" 34132451Sroberto#include "openssl/x509v3.h" 35309007Sdelphij#include "libssl_compat.h" 36132451Sroberto 3782498Sroberto#ifdef KERNEL_PLL 3882498Sroberto#include "ntp_syscall.h" 3982498Sroberto#endif /* KERNEL_PLL */ 4082498Sroberto 4182498Sroberto/* 42280849Scy * calcomp - compare two calendar structures, ignoring yearday and weekday; like strcmp 43280849Scy * No, it's not a plotter. If you don't understand that, you're too young. 44280849Scy */ 45280849Scystatic int calcomp(struct calendar *pjd1, struct calendar *pjd2) 46280849Scy{ 47280849Scy int32_t diff; /* large enough to hold the signed difference between two uint16_t values */ 48280849Scy 49280849Scy diff = pjd1->year - pjd2->year; 50280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 51280849Scy /* same year; compare months */ 52280849Scy diff = pjd1->month - pjd2->month; 53280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 54280849Scy /* same year and month; compare monthday */ 55280849Scy diff = pjd1->monthday - pjd2->monthday; 56280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 57280849Scy /* same year and month and monthday; compare time */ 58280849Scy diff = pjd1->hour - pjd2->hour; 59280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 60280849Scy diff = pjd1->minute - pjd2->minute; 61280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 62280849Scy diff = pjd1->second - pjd2->second; 63280849Scy if (diff < 0) return -1; else if (diff > 0) return 1; 64280849Scy /* identical */ 65280849Scy return 0; 66280849Scy} 67280849Scy 68280849Scy/* 69132451Sroberto * Extension field message format 7082498Sroberto * 71132451Sroberto * These are always signed and saved before sending in network byte 72132451Sroberto * order. They must be converted to and from host byte order for 73132451Sroberto * processing. 7482498Sroberto * 75132451Sroberto * +-------+-------+ 76132451Sroberto * | op | len | <- extension pointer 77132451Sroberto * +-------+-------+ 78280849Scy * | associd | 79132451Sroberto * +---------------+ 80132451Sroberto * | timestamp | <- value pointer 81132451Sroberto * +---------------+ 82132451Sroberto * | filestamp | 83132451Sroberto * +---------------+ 84132451Sroberto * | value len | 85132451Sroberto * +---------------+ 86132451Sroberto * | | 87132451Sroberto * = value = 88132451Sroberto * | | 89132451Sroberto * +---------------+ 90132451Sroberto * | signature len | 91132451Sroberto * +---------------+ 92132451Sroberto * | | 93132451Sroberto * = signature = 94132451Sroberto * | | 95132451Sroberto * +---------------+ 9682498Sroberto * 97132451Sroberto * The CRYPTO_RESP bit is set to 0 for requests, 1 for responses. 98132451Sroberto * Requests carry the association ID of the receiver; responses carry 99132451Sroberto * the association ID of the sender. Some messages include only the 100132451Sroberto * operation/length and association ID words and so have length 8 101132451Sroberto * octets. Ohers include the value structure and associated value and 102132451Sroberto * signature fields. These messages include the timestamp, filestamp, 103132451Sroberto * value and signature words and so have length at least 24 octets. The 104132451Sroberto * signature and/or value fields can be empty, in which case the 105132451Sroberto * respective length words are zero. An empty value with nonempty 106132451Sroberto * signature is syntactically valid, but semantically questionable. 107132451Sroberto * 108132451Sroberto * The filestamp represents the time when a cryptographic data file such 109132451Sroberto * as a public/private key pair is created. It follows every reference 110132451Sroberto * depending on that file and serves as a means to obsolete earlier data 111132451Sroberto * of the same type. The timestamp represents the time when the 112132451Sroberto * cryptographic data of the message were last signed. Creation of a 113132451Sroberto * cryptographic data file or signing a message can occur only when the 114132451Sroberto * creator or signor is synchronized to an authoritative source and 115132451Sroberto * proventicated to a trusted authority. 116132451Sroberto * 117280849Scy * Note there are several conditions required for server trust. First, 118280849Scy * the public key on the server certificate must be verified, which can 119280849Scy * involve a hike along the certificate trail to a trusted host. Next, 120280849Scy * the server trust must be confirmed by one of several identity 121280849Scy * schemes. Valid cryptographic values are signed with attached 122280849Scy * timestamp and filestamp. Individual packet trust is confirmed 123280849Scy * relative to these values by a message digest with keys generated by a 124280849Scy * reverse-order pseudorandom hash. 125280849Scy * 126280849Scy * State decomposition. These flags are lit in the order given. They are 127280849Scy * dim only when the association is demobilized. 128280849Scy * 129280849Scy * CRYPTO_FLAG_ENAB Lit upon acceptance of a CRYPTO_ASSOC message 130280849Scy * CRYPTO_FLAG_CERT Lit when a self-digned trusted certificate is 131280849Scy * accepted. 132280849Scy * CRYPTO_FLAG_VRFY Lit when identity is confirmed. 133280849Scy * CRYPTO_FLAG_PROV Lit when the first signature is verified. 134280849Scy * CRYPTO_FLAG_COOK Lit when a valid cookie is accepted. 135280849Scy * CRYPTO_FLAG_AUTO Lit when valid autokey values are accepted. 136280849Scy * CRYPTO_FLAG_SIGN Lit when the server signed certificate is 137280849Scy * accepted. 138280849Scy * CRYPTO_FLAG_LEAP Lit when the leapsecond values are accepted. 13982498Sroberto */ 14082498Sroberto/* 141132451Sroberto * Cryptodefines 14282498Sroberto */ 143132451Sroberto#define TAI_1972 10 /* initial TAI offset (s) */ 144132451Sroberto#define MAX_LEAP 100 /* max UTC leapseconds (s) */ 145132451Sroberto#define VALUE_LEN (6 * 4) /* min response field length */ 146280849Scy#define MAX_VALLEN (65535 - VALUE_LEN) 147132451Sroberto#define YEAR (60 * 60 * 24 * 365) /* seconds in year */ 14882498Sroberto 14982498Sroberto/* 150132451Sroberto * Global cryptodata in host byte order 15182498Sroberto */ 152132451Srobertou_int32 crypto_flags = 0x0; /* status word */ 153280849Scyint crypto_nid = KEY_TYPE_MD5; /* digest nid */ 154280849Scychar *sys_hostname = NULL; 155280849Scychar *sys_groupname = NULL; 156280849Scystatic char *host_filename = NULL; /* host file name */ 157280849Scystatic char *ident_filename = NULL; /* group file name */ 15882498Sroberto 15982498Sroberto/* 160132451Sroberto * Global cryptodata in network byte order 16182498Sroberto */ 162280849Scystruct cert_info *cinfo = NULL; /* certificate info/value cache */ 163280849Scystruct cert_info *cert_host = NULL; /* host certificate */ 164280849Scystruct pkey_info *pkinfo = NULL; /* key info/value cache */ 165132451Srobertostruct value hostval; /* host value */ 166132451Srobertostruct value pubkey; /* public key */ 167280849Scystruct value tai_leap; /* leapseconds values */ 168280849Scystruct pkey_info *iffkey_info = NULL; /* IFF keys */ 169280849Scystruct pkey_info *gqkey_info = NULL; /* GQ keys */ 170280849Scystruct pkey_info *mvkey_info = NULL; /* MV keys */ 17182498Sroberto 17282498Sroberto/* 173132451Sroberto * Private cryptodata in host byte order 17482498Sroberto */ 175132451Srobertostatic char *passwd = NULL; /* private key password */ 176132451Srobertostatic EVP_PKEY *host_pkey = NULL; /* host key */ 177132451Srobertostatic EVP_PKEY *sign_pkey = NULL; /* sign key */ 178132451Srobertostatic const EVP_MD *sign_digest = NULL; /* sign digest */ 179132451Srobertostatic u_int sign_siglen; /* sign key length */ 180132451Srobertostatic char *rand_file = NULL; /* random seed file */ 18182498Sroberto 18282498Sroberto/* 18382498Sroberto * Cryptotypes 18482498Sroberto */ 185280849Scystatic int crypto_verify (struct exten *, struct value *, 186280849Scy struct peer *); 187280849Scystatic int crypto_encrypt (const u_char *, u_int, keyid_t *, 188280849Scy struct value *); 189280849Scystatic int crypto_alice (struct peer *, struct value *); 190280849Scystatic int crypto_alice2 (struct peer *, struct value *); 191280849Scystatic int crypto_alice3 (struct peer *, struct value *); 192280849Scystatic int crypto_bob (struct exten *, struct value *); 193280849Scystatic int crypto_bob2 (struct exten *, struct value *); 194280849Scystatic int crypto_bob3 (struct exten *, struct value *); 195280849Scystatic int crypto_iff (struct exten *, struct peer *); 196280849Scystatic int crypto_gq (struct exten *, struct peer *); 197280849Scystatic int crypto_mv (struct exten *, struct peer *); 198280849Scystatic int crypto_send (struct exten *, struct value *, int); 199280849Scystatic tstamp_t crypto_time (void); 200316068Sdelphijstatic void asn_to_calendar (const ASN1_TIME *, struct calendar*); 201280849Scystatic struct cert_info *cert_parse (const u_char *, long, tstamp_t); 202280849Scystatic int cert_sign (struct exten *, struct value *); 203280849Scystatic struct cert_info *cert_install (struct exten *, struct peer *); 204280849Scystatic int cert_hike (struct peer *, struct cert_info *); 205280849Scystatic void cert_free (struct cert_info *); 206280849Scystatic struct pkey_info *crypto_key (char *, char *, sockaddr_u *); 207280849Scystatic void bighash (BIGNUM *, BIGNUM *); 208280849Scystatic struct cert_info *crypto_cert (char *); 209289764Sglebiusstatic u_int exten_payload_size(const struct exten *); 21082498Sroberto 211132451Sroberto#ifdef SYS_WINNT 212132451Srobertoint 213132451Srobertoreadlink(char * link, char * file, int len) { 214132451Sroberto return (-1); 215132451Sroberto} 216132451Sroberto#endif 21782498Sroberto 21882498Sroberto/* 21982498Sroberto * session_key - generate session key 22082498Sroberto * 22182498Sroberto * This routine generates a session key from the source address, 22282498Sroberto * destination address, key ID and private value. The value of the 22382498Sroberto * session key is the MD5 hash of these values, while the next key ID is 22482498Sroberto * the first four octets of the hash. 225132451Sroberto * 226280849Scy * Returns the next key ID or 0 if there is no destination address. 22782498Sroberto */ 228132451Srobertokeyid_t 22982498Srobertosession_key( 230280849Scy sockaddr_u *srcadr, /* source address */ 231280849Scy sockaddr_u *dstadr, /* destination address */ 232132451Sroberto keyid_t keyno, /* key ID */ 233132451Sroberto keyid_t private, /* private value */ 234132451Sroberto u_long lifetime /* key lifetime */ 23582498Sroberto ) 23682498Sroberto{ 237309007Sdelphij EVP_MD_CTX *ctx; /* message digest context */ 238132451Sroberto u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */ 239132451Sroberto keyid_t keyid; /* key identifer */ 240132451Sroberto u_int32 header[10]; /* data in network byte order */ 241132451Sroberto u_int hdlen, len; 24282498Sroberto 243182007Sroberto if (!dstadr) 244182007Sroberto return 0; 245182007Sroberto 24682498Sroberto /* 24782498Sroberto * Generate the session key and key ID. If the lifetime is 24882498Sroberto * greater than zero, install the key and call it trusted. 24982498Sroberto */ 250132451Sroberto hdlen = 0; 251280849Scy switch(AF(srcadr)) { 252132451Sroberto case AF_INET: 253280849Scy header[0] = NSRCADR(srcadr); 254280849Scy header[1] = NSRCADR(dstadr); 255132451Sroberto header[2] = htonl(keyno); 256132451Sroberto header[3] = htonl(private); 257132451Sroberto hdlen = 4 * sizeof(u_int32); 258132451Sroberto break; 259182007Sroberto 260132451Sroberto case AF_INET6: 261280849Scy memcpy(&header[0], PSOCK_ADDR6(srcadr), 262132451Sroberto sizeof(struct in6_addr)); 263280849Scy memcpy(&header[4], PSOCK_ADDR6(dstadr), 264132451Sroberto sizeof(struct in6_addr)); 265132451Sroberto header[8] = htonl(keyno); 266132451Sroberto header[9] = htonl(private); 267132451Sroberto hdlen = 10 * sizeof(u_int32); 268132451Sroberto break; 269132451Sroberto } 270309007Sdelphij ctx = EVP_MD_CTX_new(); 271330106Sdelphij# if defined(OPENSSL) && defined(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) 272330106Sdelphij /* [Bug 3457] set flags and don't kill them again */ 273330106Sdelphij EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 274330106Sdelphij EVP_DigestInit_ex(ctx, EVP_get_digestbynid(crypto_nid), NULL); 275330106Sdelphij# else 276309007Sdelphij EVP_DigestInit(ctx, EVP_get_digestbynid(crypto_nid)); 277330106Sdelphij# endif 278309007Sdelphij EVP_DigestUpdate(ctx, (u_char *)header, hdlen); 279309007Sdelphij EVP_DigestFinal(ctx, dgst, &len); 280309007Sdelphij EVP_MD_CTX_free(ctx); 281132451Sroberto memcpy(&keyid, dgst, 4); 28282498Sroberto keyid = ntohl(keyid); 28382498Sroberto if (lifetime != 0) { 284294554Sdelphij MD5auth_setkey(keyno, crypto_nid, dgst, len, NULL); 28582498Sroberto authtrust(keyno, lifetime); 28682498Sroberto } 287280849Scy DPRINTF(2, ("session_key: %s > %s %08x %08x hash %08x life %lu\n", 288132451Sroberto stoa(srcadr), stoa(dstadr), keyno, 289280849Scy private, keyid, lifetime)); 290280849Scy 29182498Sroberto return (keyid); 29282498Sroberto} 29382498Sroberto 29482498Sroberto 29582498Sroberto/* 29682498Sroberto * make_keylist - generate key list 29782498Sroberto * 298182007Sroberto * Returns 299182007Sroberto * XEVNT_OK success 300280849Scy * XEVNT_ERR protocol error 301182007Sroberto * 30282498Sroberto * This routine constructs a pseudo-random sequence by repeatedly 30382498Sroberto * hashing the session key starting from a given source address, 30482498Sroberto * destination address, private value and the next key ID of the 30582498Sroberto * preceeding session key. The last entry on the list is saved along 30682498Sroberto * with its sequence number and public signature. 30782498Sroberto */ 308182007Srobertoint 30982498Srobertomake_keylist( 31082498Sroberto struct peer *peer, /* peer structure pointer */ 31182498Sroberto struct interface *dstadr /* interface */ 31282498Sroberto ) 31382498Sroberto{ 314309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 315132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 31682498Sroberto struct autokey *ap; /* autokey pointer */ 317132451Sroberto struct value *vp; /* value pointer */ 318132451Sroberto keyid_t keyid = 0; /* next key ID */ 319132451Sroberto keyid_t cookie; /* private value */ 320280849Scy long lifetime; 321182007Sroberto u_int len, mpoll; 322132451Sroberto int i; 32382498Sroberto 324182007Sroberto if (!dstadr) 325280849Scy return XEVNT_ERR; 326182007Sroberto 32782498Sroberto /* 32882498Sroberto * Allocate the key list if necessary. 32982498Sroberto */ 330132451Sroberto tstamp = crypto_time(); 33182498Sroberto if (peer->keylist == NULL) 332285169Scy peer->keylist = eallocarray(NTP_MAXSESSION, 333285169Scy sizeof(keyid_t)); 33482498Sroberto 33582498Sroberto /* 33682498Sroberto * Generate an initial key ID which is unique and greater than 33782498Sroberto * NTP_MAXKEY. 33882498Sroberto */ 33982498Sroberto while (1) { 340280849Scy keyid = ntp_random() & 0xffffffff; 341280849Scy if (keyid <= NTP_MAXKEY) 342280849Scy continue; 343280849Scy 34482498Sroberto if (authhavekey(keyid)) 34582498Sroberto continue; 34682498Sroberto break; 34782498Sroberto } 34882498Sroberto 34982498Sroberto /* 35082498Sroberto * Generate up to NTP_MAXSESSION session keys. Stop if the 35182498Sroberto * next one would not be unique or not a session key ID or if 35282498Sroberto * it would expire before the next poll. The private value 35382498Sroberto * included in the hash is zero if broadcast mode, the peer 35482498Sroberto * cookie if client mode or the host cookie if symmetric modes. 35582498Sroberto */ 356344884Scy mpoll = 1U << min(peer->ppoll, peer->hpoll); 357344884Scy lifetime = min((1UL << sys_automax), NTP_MAXSESSION * mpoll); 35882498Sroberto if (peer->hmode == MODE_BROADCAST) 35982498Sroberto cookie = 0; 36082498Sroberto else 361132451Sroberto cookie = peer->pcookie; 36282498Sroberto for (i = 0; i < NTP_MAXSESSION; i++) { 36382498Sroberto peer->keylist[i] = keyid; 36482498Sroberto peer->keynumber = i; 36582498Sroberto keyid = session_key(&dstadr->sin, &peer->srcadr, keyid, 366280849Scy cookie, lifetime + mpoll); 367182007Sroberto lifetime -= mpoll; 36882498Sroberto if (auth_havekey(keyid) || keyid <= NTP_MAXKEY || 369280849Scy lifetime < 0 || tstamp == 0) 37082498Sroberto break; 37182498Sroberto } 37282498Sroberto 37382498Sroberto /* 37482498Sroberto * Save the last session key ID, sequence number and timestamp, 37582498Sroberto * then sign these values for later retrieval by the clients. Be 376132451Sroberto * careful not to use invalid key media. Use the public values 377132451Sroberto * timestamp as filestamp. 37882498Sroberto */ 379132451Sroberto vp = &peer->sndval; 380132451Sroberto if (vp->ptr == NULL) 381132451Sroberto vp->ptr = emalloc(sizeof(struct autokey)); 382132451Sroberto ap = (struct autokey *)vp->ptr; 38382498Sroberto ap->seq = htonl(peer->keynumber); 38482498Sroberto ap->key = htonl(keyid); 385132451Sroberto vp->tstamp = htonl(tstamp); 386132451Sroberto vp->fstamp = hostval.tstamp; 387132451Sroberto vp->vallen = htonl(sizeof(struct autokey)); 388132451Sroberto vp->siglen = 0; 389182007Sroberto if (tstamp != 0) { 390132451Sroberto if (vp->sig == NULL) 391132451Sroberto vp->sig = emalloc(sign_siglen); 392309007Sdelphij ctx = EVP_MD_CTX_new(); 393309007Sdelphij EVP_SignInit(ctx, sign_digest); 394309007Sdelphij EVP_SignUpdate(ctx, (u_char *)vp, 12); 395309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, sizeof(struct autokey)); 396309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 397289764Sglebius INSIST(len <= sign_siglen); 398285169Scy vp->siglen = htonl(len); 399280849Scy peer->flags |= FLAG_ASSOC; 400280849Scy } 401309007Sdelphij EVP_MD_CTX_free(ctx); 402132451Sroberto } 403285169Scy DPRINTF(1, ("make_keys: %d %08x %08x ts %u fs %u poll %d\n", 404280849Scy peer->keynumber, keyid, cookie, ntohl(vp->tstamp), 405285169Scy ntohl(vp->fstamp), peer->hpoll)); 406182007Sroberto return (XEVNT_OK); 40782498Sroberto} 40882498Sroberto 40982498Sroberto 41082498Sroberto/* 41182498Sroberto * crypto_recv - parse extension fields 41282498Sroberto * 41382498Sroberto * This routine is called when the packet has been matched to an 41482498Sroberto * association and passed sanity, format and MAC checks. We believe the 41582498Sroberto * extension field values only if the field has proper format and 41682498Sroberto * length, the timestamp and filestamp are valid and the signature has 41782498Sroberto * valid length and is verified. There are a few cases where some values 418132451Sroberto * are believed even if the signature fails, but only if the proventic 41982498Sroberto * bit is not set. 420280849Scy * 421280849Scy * Returns 422280849Scy * XEVNT_OK success 423280849Scy * XEVNT_ERR protocol error 424280849Scy * XEVNT_LEN bad field format or length 42582498Sroberto */ 426132451Srobertoint 42782498Srobertocrypto_recv( 42882498Sroberto struct peer *peer, /* peer structure pointer */ 42982498Sroberto struct recvbuf *rbufp /* packet buffer pointer */ 43082498Sroberto ) 43182498Sroberto{ 432132451Sroberto const EVP_MD *dp; /* message digest algorithm */ 433132451Sroberto u_int32 *pkt; /* receive packet pointer */ 434132451Sroberto struct autokey *ap, *bp; /* autokey pointer */ 435132451Sroberto struct exten *ep, *fp; /* extension pointers */ 436280849Scy struct cert_info *xinfo; /* certificate info pointer */ 437289764Sglebius int macbytes; /* length of MAC field, signed by intention */ 438132451Sroberto int authlen; /* offset of MAC field */ 439132451Sroberto associd_t associd; /* association ID */ 440132451Sroberto tstamp_t fstamp = 0; /* filestamp */ 441132451Sroberto u_int len; /* extension field length */ 442132451Sroberto u_int code; /* extension field opcode */ 443132451Sroberto u_int vallen = 0; /* value length */ 444132451Sroberto X509 *cert; /* X509 certificate */ 445132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 446132451Sroberto keyid_t cookie; /* crumbles */ 447182007Sroberto int hismode; /* packet mode */ 448132451Sroberto int rval = XEVNT_OK; 449280849Scy const u_char *puch; 450132451Sroberto u_int32 temp32; 45182498Sroberto 45282498Sroberto /* 45382498Sroberto * Initialize. Note that the packet has already been checked for 454132451Sroberto * valid format and extension field lengths. First extract the 455132451Sroberto * field length, command code and association ID in host byte 456132451Sroberto * order. These are used with all commands and modes. Then check 457132451Sroberto * the version number, which must be 2, and length, which must 458132451Sroberto * be at least 8 for requests and VALUE_LEN (24) for responses. 459132451Sroberto * Packets that fail either test sink without a trace. The 460132451Sroberto * association ID is saved only if nonzero. 46182498Sroberto */ 46282498Sroberto authlen = LEN_PKT_NOMAC; 463182007Sroberto hismode = (int)PKT_MODE((&rbufp->recv_pkt)->li_vn_mode); 464289764Sglebius while ((macbytes = rbufp->recv_length - authlen) > (int)MAX_MAC_LEN) { 465289764Sglebius /* We can be reasonably sure that we can read at least 466289764Sglebius * the opcode and the size field here. More stringent 467289764Sglebius * checks follow up shortly. 468289764Sglebius */ 469132451Sroberto pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4; 470132451Sroberto ep = (struct exten *)pkt; 471132451Sroberto code = ntohl(ep->opcode) & 0xffff0000; 472132451Sroberto len = ntohl(ep->opcode) & 0x0000ffff; 473280849Scy // HMS: Why pkt[1] instead of ep->associd ? 474280849Scy associd = (associd_t)ntohl(pkt[1]); 475132451Sroberto rval = XEVNT_OK; 476285169Scy DPRINTF(1, ("crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n", 477132451Sroberto peer->crypto, authlen, len, code >> 16, 478285169Scy associd)); 479132451Sroberto 480132451Sroberto /* 481132451Sroberto * Check version number and field length. If bad, 482132451Sroberto * quietly ignore the packet. 483132451Sroberto */ 484182007Sroberto if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8) { 485280849Scy sys_badlength++; 486132451Sroberto code |= CRYPTO_ERROR; 487132451Sroberto } 488132451Sroberto 489289764Sglebius /* Check if the declared size fits into the remaining 490293423Sdelphij * buffer. We *know* 'macbytes' > 0 here! 491289764Sglebius */ 492293423Sdelphij if (len > (u_int)macbytes) { 493289764Sglebius DPRINTF(1, ("crypto_recv: possible attack detected, associd %d\n", 494289764Sglebius associd)); 495289764Sglebius return XEVNT_LEN; 496289764Sglebius } 497289764Sglebius 498289764Sglebius /* Check if the paylod of the extension fits into the 499289764Sglebius * declared frame. 500289764Sglebius */ 501132451Sroberto if (len >= VALUE_LEN) { 502132451Sroberto fstamp = ntohl(ep->fstamp); 503132451Sroberto vallen = ntohl(ep->vallen); 504280849Scy /* 505280849Scy * Bug 2761: I hope this isn't too early... 506280849Scy */ 507280849Scy if ( vallen == 0 508280849Scy || len - VALUE_LEN < vallen) 509280849Scy return XEVNT_LEN; 510132451Sroberto } 51182498Sroberto switch (code) { 51282498Sroberto 51382498Sroberto /* 514132451Sroberto * Install status word, host name, signature scheme and 515132451Sroberto * association ID. In OpenSSL the signature algorithm is 516132451Sroberto * bound to the digest algorithm, so the NID completely 517132451Sroberto * defines the signature scheme. Note the request and 518132451Sroberto * response are identical, but neither is validated by 519132451Sroberto * signature. The request is processed here only in 520182007Sroberto * symmetric modes. The server name field might be 521132451Sroberto * useful to implement access controls in future. 52282498Sroberto */ 523132451Sroberto case CRYPTO_ASSOC: 524132451Sroberto 525132451Sroberto /* 526280849Scy * If our state machine is running when this 527280849Scy * message arrives, the other fellow might have 528280849Scy * restarted. However, this could be an 529280849Scy * intruder, so just clamp the poll interval and 530280849Scy * find out for ourselves. Otherwise, pass the 531280849Scy * extension field to the transmit side. 532132451Sroberto */ 533280849Scy if (peer->crypto & CRYPTO_FLAG_CERT) { 534182007Sroberto rval = XEVNT_ERR; 535182007Sroberto break; 536182007Sroberto } 537280849Scy if (peer->cmmd) { 538280849Scy if (peer->assoc != associd) { 539280849Scy rval = XEVNT_ERR; 540280849Scy break; 541280849Scy } 542289764Sglebius free(peer->cmmd); /* will be set again! */ 543280849Scy } 544132451Sroberto fp = emalloc(len); 545132451Sroberto memcpy(fp, ep, len); 546280849Scy fp->associd = htonl(peer->associd); 547132451Sroberto peer->cmmd = fp; 548132451Sroberto /* fall through */ 549132451Sroberto 55082498Sroberto case CRYPTO_ASSOC | CRYPTO_RESP: 551132451Sroberto 552132451Sroberto /* 553132451Sroberto * Discard the message if it has already been 554182007Sroberto * stored or the message has been amputated. 555132451Sroberto */ 556280849Scy if (peer->crypto) { 557280849Scy if (peer->assoc != associd) 558280849Scy rval = XEVNT_ERR; 559132451Sroberto break; 560280849Scy } 561280849Scy INSIST(len >= VALUE_LEN); 562182007Sroberto if (vallen == 0 || vallen > MAXHOSTNAME || 563280849Scy len - VALUE_LEN < vallen) { 564132451Sroberto rval = XEVNT_LEN; 565132451Sroberto break; 56682498Sroberto } 567285169Scy DPRINTF(1, ("crypto_recv: ident host 0x%x %d server 0x%x %d\n", 568280849Scy crypto_flags, peer->associd, fstamp, 569285169Scy peer->assoc)); 570280849Scy temp32 = crypto_flags & CRYPTO_FLAG_MASK; 571280849Scy 572280849Scy /* 573280849Scy * If the client scheme is PC, the server scheme 574280849Scy * must be PC. The public key and identity are 575280849Scy * presumed valid, so we skip the certificate 576280849Scy * and identity exchanges and move immediately 577280849Scy * to the cookie exchange which confirms the 578280849Scy * server signature. 579280849Scy */ 580132451Sroberto if (crypto_flags & CRYPTO_FLAG_PRIV) { 581182007Sroberto if (!(fstamp & CRYPTO_FLAG_PRIV)) { 582132451Sroberto rval = XEVNT_KEY; 583182007Sroberto break; 584280849Scy } 585280849Scy fstamp |= CRYPTO_FLAG_CERT | 586280849Scy CRYPTO_FLAG_VRFY | CRYPTO_FLAG_SIGN; 587182007Sroberto 588182007Sroberto /* 589280849Scy * It is an error if either peer supports 590280849Scy * identity, but the other does not. 591182007Sroberto */ 592280849Scy } else if (hismode == MODE_ACTIVE || hismode == 593280849Scy MODE_PASSIVE) { 594280849Scy if ((temp32 && !(fstamp & 595280849Scy CRYPTO_FLAG_MASK)) || 596280849Scy (!temp32 && (fstamp & 597280849Scy CRYPTO_FLAG_MASK))) { 598280849Scy rval = XEVNT_KEY; 599280849Scy break; 600280849Scy } 601132451Sroberto } 602132451Sroberto 603132451Sroberto /* 604182007Sroberto * Discard the message if the signature digest 605182007Sroberto * NID is not supported. 606132451Sroberto */ 607132451Sroberto temp32 = (fstamp >> 16) & 0xffff; 608132451Sroberto dp = 609132451Sroberto (const EVP_MD *)EVP_get_digestbynid(temp32); 610182007Sroberto if (dp == NULL) { 611132451Sroberto rval = XEVNT_MD; 612132451Sroberto break; 613182007Sroberto } 614132451Sroberto 615132451Sroberto /* 616132451Sroberto * Save status word, host name and message 617280849Scy * digest/signature type. If this is from a 618280849Scy * broadcast and the association ID has changed, 619280849Scy * request the autokey values. 620132451Sroberto */ 621280849Scy peer->assoc = associd; 622280849Scy if (hismode == MODE_SERVER) 623280849Scy fstamp |= CRYPTO_FLAG_AUTO; 624280849Scy if (!(fstamp & CRYPTO_FLAG_TAI)) 625280849Scy fstamp |= CRYPTO_FLAG_LEAP; 626280849Scy RAND_bytes((u_char *)&peer->hcookie, 4); 627132451Sroberto peer->crypto = fstamp; 628132451Sroberto peer->digest = dp; 629280849Scy if (peer->subject != NULL) 630280849Scy free(peer->subject); 631132451Sroberto peer->subject = emalloc(vallen + 1); 632132451Sroberto memcpy(peer->subject, ep->pkt, vallen); 633132451Sroberto peer->subject[vallen] = '\0'; 634280849Scy if (peer->issuer != NULL) 635280849Scy free(peer->issuer); 636280849Scy peer->issuer = estrdup(peer->subject); 637280849Scy snprintf(statstr, sizeof(statstr), 638280849Scy "assoc %d %d host %s %s", peer->associd, 639280849Scy peer->assoc, peer->subject, 640280849Scy OBJ_nid2ln(temp32)); 641132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 642285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 64382498Sroberto break; 64482498Sroberto 64582498Sroberto /* 646132451Sroberto * Decode X509 certificate in ASN.1 format and extract 647132451Sroberto * the data containing, among other things, subject 648132451Sroberto * name and public key. In the default identification 649132451Sroberto * scheme, the certificate trail is followed to a self 650132451Sroberto * signed trusted certificate. 65182498Sroberto */ 652132451Sroberto case CRYPTO_CERT | CRYPTO_RESP: 653132451Sroberto 654132451Sroberto /* 655280849Scy * Discard the message if empty or invalid. 656132451Sroberto */ 657280849Scy if (len < VALUE_LEN) 658280849Scy break; 659280849Scy 660132451Sroberto if ((rval = crypto_verify(ep, NULL, peer)) != 661132451Sroberto XEVNT_OK) 662132451Sroberto break; 663132451Sroberto 664132451Sroberto /* 665132451Sroberto * Scan the certificate list to delete old 666132451Sroberto * versions and link the newest version first on 667280849Scy * the list. Then, verify the signature. If the 668280849Scy * certificate is bad or missing, just ignore 669280849Scy * it. 670132451Sroberto */ 671280849Scy if ((xinfo = cert_install(ep, peer)) == NULL) { 672280849Scy rval = XEVNT_CRT; 673132451Sroberto break; 674280849Scy } 675280849Scy if ((rval = cert_hike(peer, xinfo)) != XEVNT_OK) 676280849Scy break; 677132451Sroberto 678132451Sroberto /* 679182007Sroberto * We plug in the public key and lifetime from 680132451Sroberto * the first certificate received. However, note 681132451Sroberto * that this certificate might not be signed by 682132451Sroberto * the server, so we can't check the 683132451Sroberto * signature/digest NID. 684132451Sroberto */ 685132451Sroberto if (peer->pkey == NULL) { 686280849Scy puch = xinfo->cert.ptr; 687280849Scy cert = d2i_X509(NULL, &puch, 688280849Scy ntohl(xinfo->cert.vallen)); 689132451Sroberto peer->pkey = X509_get_pubkey(cert); 690132451Sroberto X509_free(cert); 69182498Sroberto } 692182007Sroberto peer->flash &= ~TEST8; 693280849Scy temp32 = xinfo->nid; 694280849Scy snprintf(statstr, sizeof(statstr), 695280849Scy "cert %s %s 0x%x %s (%u) fs %u", 696280849Scy xinfo->subject, xinfo->issuer, xinfo->flags, 697132451Sroberto OBJ_nid2ln(temp32), temp32, 698132451Sroberto ntohl(ep->fstamp)); 699132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 700285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 70182498Sroberto break; 70282498Sroberto 70382498Sroberto /* 704280849Scy * Schnorr (IFF) identity scheme. This scheme is 705280849Scy * designed for use with shared secret server group keys 706280849Scy * and where the certificate may be generated by a third 707280849Scy * party. The client sends a challenge to the server, 708280849Scy * which performs a calculation and returns the result. 709280849Scy * A positive result is possible only if both client and 710132451Sroberto * server contain the same secret group key. 71182498Sroberto */ 712132451Sroberto case CRYPTO_IFF | CRYPTO_RESP: 71382498Sroberto 714132451Sroberto /* 715280849Scy * Discard the message if invalid. 716132451Sroberto */ 717132451Sroberto if ((rval = crypto_verify(ep, NULL, peer)) != 718132451Sroberto XEVNT_OK) 719132451Sroberto break; 720132451Sroberto 72182498Sroberto /* 722280849Scy * If the challenge matches the response, the 723280849Scy * server public key, signature and identity are 724132451Sroberto * all verified at the same time. The server is 725132451Sroberto * declared trusted, so we skip further 726280849Scy * certificate exchanges and move immediately to 727280849Scy * the cookie exchange. 72882498Sroberto */ 729132451Sroberto if ((rval = crypto_iff(ep, peer)) != XEVNT_OK) 730132451Sroberto break; 731132451Sroberto 732280849Scy peer->crypto |= CRYPTO_FLAG_VRFY; 733182007Sroberto peer->flash &= ~TEST8; 734280849Scy snprintf(statstr, sizeof(statstr), "iff %s fs %u", 735280849Scy peer->issuer, ntohl(ep->fstamp)); 736132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 737285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 73882498Sroberto break; 73982498Sroberto 74082498Sroberto /* 741132451Sroberto * Guillou-Quisquater (GQ) identity scheme. This scheme 742132451Sroberto * is designed for use with public certificates carrying 743132451Sroberto * the GQ public key in an extension field. The client 744132451Sroberto * sends a challenge to the server, which performs a 745132451Sroberto * calculation and returns the result. A positive result 746132451Sroberto * is possible only if both client and server contain 747132451Sroberto * the same group key and the server has the matching GQ 748132451Sroberto * private key. 74982498Sroberto */ 750132451Sroberto case CRYPTO_GQ | CRYPTO_RESP: 751132451Sroberto 752132451Sroberto /* 753280849Scy * Discard the message if invalid 754132451Sroberto */ 755132451Sroberto if ((rval = crypto_verify(ep, NULL, peer)) != 756132451Sroberto XEVNT_OK) 757132451Sroberto break; 758132451Sroberto 759132451Sroberto /* 760280849Scy * If the challenge matches the response, the 761280849Scy * server public key, signature and identity are 762132451Sroberto * all verified at the same time. The server is 763132451Sroberto * declared trusted, so we skip further 764280849Scy * certificate exchanges and move immediately to 765280849Scy * the cookie exchange. 766132451Sroberto */ 767132451Sroberto if ((rval = crypto_gq(ep, peer)) != XEVNT_OK) 768132451Sroberto break; 769132451Sroberto 770280849Scy peer->crypto |= CRYPTO_FLAG_VRFY; 771182007Sroberto peer->flash &= ~TEST8; 772280849Scy snprintf(statstr, sizeof(statstr), "gq %s fs %u", 773280849Scy peer->issuer, ntohl(ep->fstamp)); 774132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 775285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 77682498Sroberto break; 77782498Sroberto 77882498Sroberto /* 779280849Scy * Mu-Varadharajan (MV) identity scheme. This scheme is 780280849Scy * designed for use with three levels of trust, trusted 781280849Scy * host, server and client. The trusted host key is 782280849Scy * opaque to servers and clients; the server keys are 783280849Scy * opaque to clients and each client key is different. 784280849Scy * Client keys can be revoked without requiring new key 785280849Scy * generations. 78682498Sroberto */ 787132451Sroberto case CRYPTO_MV | CRYPTO_RESP: 788132451Sroberto 789132451Sroberto /* 790280849Scy * Discard the message if invalid. 791132451Sroberto */ 792132451Sroberto if ((rval = crypto_verify(ep, NULL, peer)) != 793132451Sroberto XEVNT_OK) 794132451Sroberto break; 795132451Sroberto 796132451Sroberto /* 797280849Scy * If the challenge matches the response, the 798280849Scy * server public key, signature and identity are 799132451Sroberto * all verified at the same time. The server is 800132451Sroberto * declared trusted, so we skip further 801280849Scy * certificate exchanges and move immediately to 802280849Scy * the cookie exchange. 803132451Sroberto */ 804132451Sroberto if ((rval = crypto_mv(ep, peer)) != XEVNT_OK) 805132451Sroberto break; 806132451Sroberto 807280849Scy peer->crypto |= CRYPTO_FLAG_VRFY; 808182007Sroberto peer->flash &= ~TEST8; 809280849Scy snprintf(statstr, sizeof(statstr), "mv %s fs %u", 810280849Scy peer->issuer, ntohl(ep->fstamp)); 811132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 812285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 813132451Sroberto break; 81482498Sroberto 815132451Sroberto 816132451Sroberto /* 817132451Sroberto * Cookie response in client and symmetric modes. If the 818132451Sroberto * cookie bit is set, the working cookie is the EXOR of 819132451Sroberto * the current and new values. 820132451Sroberto */ 821132451Sroberto case CRYPTO_COOK | CRYPTO_RESP: 822132451Sroberto 82382498Sroberto /* 824280849Scy * Discard the message if invalid or signature 825280849Scy * not verified with respect to the cookie 826280849Scy * values. 82782498Sroberto */ 828132451Sroberto if ((rval = crypto_verify(ep, &peer->cookval, 829132451Sroberto peer)) != XEVNT_OK) 830132451Sroberto break; 831132451Sroberto 83282498Sroberto /* 833132451Sroberto * Decrypt the cookie, hunting all the time for 834132451Sroberto * errors. 83582498Sroberto */ 836281016Scy if (vallen == (u_int)EVP_PKEY_size(host_pkey)) { 837309007Sdelphij RSA *rsa = EVP_PKEY_get0_RSA(host_pkey); 838309007Sdelphij u_int32 *cookiebuf = malloc(RSA_size(rsa)); 839281016Scy if (!cookiebuf) { 840276071Sdelphij rval = XEVNT_CKY; 841276071Sdelphij break; 842276071Sdelphij } 843280849Scy 844276071Sdelphij if (RSA_private_decrypt(vallen, 845132451Sroberto (u_char *)ep->pkt, 846276071Sdelphij (u_char *)cookiebuf, 847309007Sdelphij rsa, 848276071Sdelphij RSA_PKCS1_OAEP_PADDING) != 4) { 849276071Sdelphij rval = XEVNT_CKY; 850276071Sdelphij free(cookiebuf); 851276071Sdelphij break; 852276071Sdelphij } else { 853276071Sdelphij cookie = ntohl(*cookiebuf); 854276071Sdelphij free(cookiebuf); 855276071Sdelphij } 856132451Sroberto } else { 857132451Sroberto rval = XEVNT_CKY; 858132451Sroberto break; 859132451Sroberto } 86082498Sroberto 86182498Sroberto /* 862132451Sroberto * Install cookie values and light the cookie 863132451Sroberto * bit. If this is not broadcast client mode, we 864132451Sroberto * are done here. 86582498Sroberto */ 866132451Sroberto key_expire(peer); 867280849Scy if (hismode == MODE_ACTIVE || hismode == 868280849Scy MODE_PASSIVE) 869280849Scy peer->pcookie = peer->hcookie ^ cookie; 870132451Sroberto else 871132451Sroberto peer->pcookie = cookie; 872280849Scy peer->crypto |= CRYPTO_FLAG_COOK; 873182007Sroberto peer->flash &= ~TEST8; 874280849Scy snprintf(statstr, sizeof(statstr), 875280849Scy "cook %x ts %u fs %u", peer->pcookie, 876280849Scy ntohl(ep->tstamp), ntohl(ep->fstamp)); 877132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 878285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 87982498Sroberto break; 88082498Sroberto 88182498Sroberto /* 882132451Sroberto * Install autokey values in broadcast client and 883132451Sroberto * symmetric modes. We have to do this every time the 884132451Sroberto * sever/peer cookie changes or a new keylist is 885132451Sroberto * rolled. Ordinarily, this is automatic as this message 886132451Sroberto * is piggybacked on the first NTP packet sent upon 887132451Sroberto * either of these events. Note that a broadcast client 888132451Sroberto * or symmetric peer can receive this response without a 889132451Sroberto * matching request. 89082498Sroberto */ 891132451Sroberto case CRYPTO_AUTO | CRYPTO_RESP: 89282498Sroberto 893132451Sroberto /* 894280849Scy * Discard the message if invalid or signature 895280849Scy * not verified with respect to the receive 896280849Scy * autokey values. 897132451Sroberto */ 898132451Sroberto if ((rval = crypto_verify(ep, &peer->recval, 899280849Scy peer)) != XEVNT_OK) 900132451Sroberto break; 901132451Sroberto 90282498Sroberto /* 903280849Scy * Discard the message if a broadcast client and 904280849Scy * the association ID does not match. This might 905280849Scy * happen if a broacast server restarts the 906280849Scy * protocol. A protocol restart will occur at 907280849Scy * the next ASSOC message. 908280849Scy */ 909280849Scy if ((peer->cast_flags & MDF_BCLNT) && 910280849Scy peer->assoc != associd) 911280849Scy break; 912280849Scy 913280849Scy /* 914132451Sroberto * Install autokey values and light the 915132451Sroberto * autokey bit. This is not hard. 91682498Sroberto */ 917280849Scy if (ep->tstamp == 0) 918280849Scy break; 919280849Scy 920132451Sroberto if (peer->recval.ptr == NULL) 921132451Sroberto peer->recval.ptr = 922132451Sroberto emalloc(sizeof(struct autokey)); 923132451Sroberto bp = (struct autokey *)peer->recval.ptr; 924132451Sroberto peer->recval.tstamp = ep->tstamp; 925132451Sroberto peer->recval.fstamp = ep->fstamp; 926132451Sroberto ap = (struct autokey *)ep->pkt; 927132451Sroberto bp->seq = ntohl(ap->seq); 928132451Sroberto bp->key = ntohl(ap->key); 929132451Sroberto peer->pkeyid = bp->key; 930132451Sroberto peer->crypto |= CRYPTO_FLAG_AUTO; 931182007Sroberto peer->flash &= ~TEST8; 932280849Scy snprintf(statstr, sizeof(statstr), 933132451Sroberto "auto seq %d key %x ts %u fs %u", bp->seq, 934132451Sroberto bp->key, ntohl(ep->tstamp), 935132451Sroberto ntohl(ep->fstamp)); 936132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 937285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 93882498Sroberto break; 939182007Sroberto 940182007Sroberto /* 941182007Sroberto * X509 certificate sign response. Validate the 942182007Sroberto * certificate signed by the server and install. Later 943182007Sroberto * this can be provided to clients of this server in 944182007Sroberto * lieu of the self signed certificate in order to 945182007Sroberto * validate the public key. 946182007Sroberto */ 947182007Sroberto case CRYPTO_SIGN | CRYPTO_RESP: 94882498Sroberto 949182007Sroberto /* 950280849Scy * Discard the message if invalid. 951182007Sroberto */ 952182007Sroberto if ((rval = crypto_verify(ep, NULL, peer)) != 953182007Sroberto XEVNT_OK) 954182007Sroberto break; 955182007Sroberto 956182007Sroberto /* 957182007Sroberto * Scan the certificate list to delete old 958182007Sroberto * versions and link the newest version first on 959182007Sroberto * the list. 960182007Sroberto */ 961280849Scy if ((xinfo = cert_install(ep, peer)) == NULL) { 962280849Scy rval = XEVNT_CRT; 963182007Sroberto break; 964280849Scy } 965182007Sroberto peer->crypto |= CRYPTO_FLAG_SIGN; 966182007Sroberto peer->flash &= ~TEST8; 967280849Scy temp32 = xinfo->nid; 968280849Scy snprintf(statstr, sizeof(statstr), 969280849Scy "sign %s %s 0x%x %s (%u) fs %u", 970280849Scy xinfo->subject, xinfo->issuer, xinfo->flags, 971182007Sroberto OBJ_nid2ln(temp32), temp32, 972182007Sroberto ntohl(ep->fstamp)); 973182007Sroberto record_crypto_stats(&peer->srcadr, statstr); 974285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 975182007Sroberto break; 976182007Sroberto 97782498Sroberto /* 978280849Scy * Install leapseconds values. While the leapsecond 979280849Scy * values epoch, TAI offset and values expiration epoch 980280849Scy * are retained, only the current TAI offset is provided 981280849Scy * via the kernel to other applications. 98282498Sroberto */ 983280849Scy case CRYPTO_LEAP | CRYPTO_RESP: 984132451Sroberto /* 985280849Scy * Discard the message if invalid. We can't 986280849Scy * compare the value timestamps here, as they 987280849Scy * can be updated by different servers. 988132451Sroberto */ 989285169Scy rval = crypto_verify(ep, NULL, peer); 990285169Scy if ((rval != XEVNT_OK ) || 991285169Scy (vallen != 3*sizeof(uint32_t)) ) 992132451Sroberto break; 993132451Sroberto 994285169Scy /* Check if we can update the basic TAI offset 995285169Scy * for our current leap frame. This is a hack 996285169Scy * and ignores the time stamps in the autokey 997285169Scy * message. 998132451Sroberto */ 999285169Scy if (sys_leap != LEAP_NOTINSYNC) 1000285169Scy leapsec_autokey_tai(ntohl(ep->pkt[0]), 1001285169Scy rbufp->recv_time.l_ui, NULL); 1002285169Scy tai_leap.tstamp = ep->tstamp; 1003285169Scy tai_leap.fstamp = ep->fstamp; 1004285169Scy crypto_update(); 1005285169Scy mprintf_event(EVNT_TAI, peer, 1006285169Scy "%d seconds", ntohl(ep->pkt[0])); 1007132451Sroberto peer->crypto |= CRYPTO_FLAG_LEAP; 1008182007Sroberto peer->flash &= ~TEST8; 1009280849Scy snprintf(statstr, sizeof(statstr), 1010285169Scy "leap TAI offset %d at %u expire %u fs %u", 1011285169Scy ntohl(ep->pkt[0]), ntohl(ep->pkt[1]), 1012285169Scy ntohl(ep->pkt[2]), ntohl(ep->fstamp)); 1013132451Sroberto record_crypto_stats(&peer->srcadr, statstr); 1014285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 101582498Sroberto break; 101682498Sroberto 101782498Sroberto /* 1018132451Sroberto * We come here in symmetric modes for miscellaneous 1019132451Sroberto * commands that have value fields but are processed on 1020132451Sroberto * the transmit side. All we need do here is check for 1021280849Scy * valid field length. Note that ASSOC is handled 1022280849Scy * separately. 102382498Sroberto */ 1024182007Sroberto case CRYPTO_CERT: 1025132451Sroberto case CRYPTO_IFF: 1026132451Sroberto case CRYPTO_GQ: 1027132451Sroberto case CRYPTO_MV: 1028280849Scy case CRYPTO_COOK: 1029132451Sroberto case CRYPTO_SIGN: 1030132451Sroberto if (len < VALUE_LEN) { 1031132451Sroberto rval = XEVNT_LEN; 103282498Sroberto break; 1033132451Sroberto } 1034132451Sroberto /* fall through */ 1035132451Sroberto 1036132451Sroberto /* 1037280849Scy * We come here in symmetric modes for requests 1038280849Scy * requiring a response (above plus AUTO and LEAP) and 1039280849Scy * for responses. If a request, save the extension field 1040280849Scy * for later; invalid requests will be caught on the 1041280849Scy * transmit side. If an error or invalid response, 1042280849Scy * declare a protocol error. 1043132451Sroberto */ 1044132451Sroberto default: 1045132451Sroberto if (code & (CRYPTO_RESP | CRYPTO_ERROR)) { 1046182007Sroberto rval = XEVNT_ERR; 1047280849Scy } else if (peer->cmmd == NULL) { 1048132451Sroberto fp = emalloc(len); 1049132451Sroberto memcpy(fp, ep, len); 1050132451Sroberto peer->cmmd = fp; 1051132451Sroberto } 105282498Sroberto } 1053132451Sroberto 1054132451Sroberto /* 1055132451Sroberto * The first error found terminates the extension field 1056280849Scy * scan and we return the laundry to the caller. 1057132451Sroberto */ 1058280849Scy if (rval != XEVNT_OK) { 1059280849Scy snprintf(statstr, sizeof(statstr), 1060280849Scy "%04x %d %02x %s", htonl(ep->opcode), 1061280849Scy associd, rval, eventstr(rval)); 1062182007Sroberto record_crypto_stats(&peer->srcadr, statstr); 1063285169Scy DPRINTF(1, ("crypto_recv: %s\n", statstr)); 1064280849Scy return (rval); 1065132451Sroberto } 1066280849Scy authlen += (len + 3) / 4 * 4; 106782498Sroberto } 1068132451Sroberto return (rval); 106982498Sroberto} 107082498Sroberto 107182498Sroberto 107282498Sroberto/* 107382498Sroberto * crypto_xmit - construct extension fields 107482498Sroberto * 107582498Sroberto * This routine is called both when an association is configured and 1076132451Sroberto * when one is not. The only case where this matters is to retrieve the 1077132451Sroberto * autokey information, in which case the caller has to provide the 107882498Sroberto * association ID to match the association. 1079132451Sroberto * 1080280849Scy * Side effect: update the packet offset. 1081280849Scy * 1082280849Scy * Errors 1083280849Scy * XEVNT_OK success 1084280849Scy * XEVNT_CRT bad or missing certificate 1085280849Scy * XEVNT_ERR protocol error 1086280849Scy * XEVNT_LEN bad field format or length 1087280849Scy * XEVNT_PER host certificate expired 108882498Sroberto */ 1089132451Srobertoint 109082498Srobertocrypto_xmit( 1091280849Scy struct peer *peer, /* peer structure pointer */ 1092132451Sroberto struct pkt *xpkt, /* transmit packet pointer */ 1093280849Scy struct recvbuf *rbufp, /* receive buffer pointer */ 1094132451Sroberto int start, /* offset to extension field */ 1095132451Sroberto struct exten *ep, /* extension pointer */ 1096132451Sroberto keyid_t cookie /* session cookie */ 109782498Sroberto ) 109882498Sroberto{ 1099280849Scy struct exten *fp; /* extension pointers */ 1100280849Scy struct cert_info *cp, *xp, *yp; /* cert info/value pointer */ 1101280849Scy sockaddr_u *srcadr_sin; /* source address */ 1102132451Sroberto u_int32 *pkt; /* packet pointer */ 1103132451Sroberto u_int opcode; /* extension field opcode */ 1104132451Sroberto char certname[MAXHOSTNAME + 1]; /* subject name buffer */ 1105132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 1106182007Sroberto tstamp_t tstamp; 1107280849Scy struct calendar tscal; 1108132451Sroberto u_int vallen; 1109132451Sroberto struct value vtemp; 1110132451Sroberto associd_t associd; 1111132451Sroberto int rval; 1112280849Scy int len; 1113132451Sroberto keyid_t tcookie; 111482498Sroberto 111582498Sroberto /* 111682498Sroberto * Generate the requested extension field request code, length 1117132451Sroberto * and association ID. If this is a response and the host is not 1118132451Sroberto * synchronized, light the error bit and go home. 111982498Sroberto */ 1120132451Sroberto pkt = (u_int32 *)xpkt + start / 4; 1121132451Sroberto fp = (struct exten *)pkt; 1122132451Sroberto opcode = ntohl(ep->opcode); 1123280849Scy if (peer != NULL) { 1124280849Scy srcadr_sin = &peer->srcadr; 1125280849Scy if (!(opcode & CRYPTO_RESP)) 1126280849Scy peer->opcode = ep->opcode; 1127280849Scy } else { 1128280849Scy srcadr_sin = &rbufp->recv_srcadr; 1129280849Scy } 1130132451Sroberto associd = (associd_t) ntohl(ep->associd); 113182498Sroberto len = 8; 1132280849Scy fp->opcode = htonl((opcode & 0xffff0000) | len); 1133280849Scy fp->associd = ep->associd; 1134132451Sroberto rval = XEVNT_OK; 1135182007Sroberto tstamp = crypto_time(); 1136132451Sroberto switch (opcode & 0xffff0000) { 113782498Sroberto 113882498Sroberto /* 1139132451Sroberto * Send association request and response with status word and 1140132451Sroberto * host name. Note, this message is not signed and the filestamp 1141182007Sroberto * contains only the status word. 114282498Sroberto */ 1143280849Scy case CRYPTO_ASSOC: 114482498Sroberto case CRYPTO_ASSOC | CRYPTO_RESP: 1145280849Scy len = crypto_send(fp, &hostval, start); 1146182007Sroberto fp->fstamp = htonl(crypto_flags); 1147182007Sroberto break; 1148182007Sroberto 114982498Sroberto /* 1150132451Sroberto * Send certificate request. Use the values from the extension 1151132451Sroberto * field. 115282498Sroberto */ 1153132451Sroberto case CRYPTO_CERT: 1154132451Sroberto memset(&vtemp, 0, sizeof(vtemp)); 1155132451Sroberto vtemp.tstamp = ep->tstamp; 1156132451Sroberto vtemp.fstamp = ep->fstamp; 1157132451Sroberto vtemp.vallen = ep->vallen; 1158182007Sroberto vtemp.ptr = (u_char *)ep->pkt; 1159280849Scy len = crypto_send(fp, &vtemp, start); 1160132451Sroberto break; 1161132451Sroberto 1162132451Sroberto /* 1163280849Scy * Send sign request. Use the host certificate, which is self- 1164280849Scy * signed and may or may not be trusted. 1165132451Sroberto */ 1166132451Sroberto case CRYPTO_SIGN: 1167280849Scy (void)ntpcal_ntp_to_date(&tscal, tstamp, NULL); 1168280849Scy if ((calcomp(&tscal, &(cert_host->first)) < 0) 1169280849Scy || (calcomp(&tscal, &(cert_host->last)) > 0)) 1170280849Scy rval = XEVNT_PER; 1171280849Scy else 1172280849Scy len = crypto_send(fp, &cert_host->cert, start); 1173280849Scy break; 1174280849Scy 1175280849Scy /* 1176280849Scy * Send certificate response. Use the name in the extension 1177280849Scy * field to find the certificate in the cache. If the request 1178280849Scy * contains no subject name, assume the name of this host. This 1179280849Scy * is for backwards compatibility. Private certificates are 1180280849Scy * never sent. 1181280849Scy * 1182280849Scy * There may be several certificates matching the request. First 1183280849Scy * choice is a self-signed trusted certificate; second choice is 1184280849Scy * any certificate signed by another host. There is no third 1185280849Scy * choice. 1186280849Scy */ 1187132451Sroberto case CRYPTO_CERT | CRYPTO_RESP: 1188289764Sglebius vallen = exten_payload_size(ep); /* Must be <64k */ 1189289764Sglebius if (vallen == 0 || vallen >= sizeof(certname) ) { 1190182007Sroberto rval = XEVNT_LEN; 119182498Sroberto break; 119282498Sroberto } 1193182007Sroberto 1194182007Sroberto /* 1195280849Scy * Find all public valid certificates with matching 1196280849Scy * subject. If a self-signed, trusted certificate is 1197280849Scy * found, use that certificate. If not, use the last non 1198280849Scy * self-signed certificate. 1199182007Sroberto */ 1200280849Scy memcpy(certname, ep->pkt, vallen); 1201280849Scy certname[vallen] = '\0'; 1202280849Scy xp = yp = NULL; 1203132451Sroberto for (cp = cinfo; cp != NULL; cp = cp->link) { 1204280849Scy if (cp->flags & (CERT_PRIV | CERT_ERROR)) 1205132451Sroberto continue; 1206182007Sroberto 1207280849Scy if (strcmp(certname, cp->subject) != 0) 1208280849Scy continue; 1209280849Scy 1210280849Scy if (strcmp(certname, cp->issuer) != 0) 1211280849Scy yp = cp; 1212280849Scy else if (cp ->flags & CERT_TRUST) 1213280849Scy xp = cp; 1214280849Scy continue; 1215132451Sroberto } 1216182007Sroberto 1217182007Sroberto /* 1218280849Scy * Be careful who you trust. If the certificate is not 1219280849Scy * found, return an empty response. Note that we dont 1220280849Scy * enforce lifetimes here. 1221182007Sroberto * 1222280849Scy * The timestamp and filestamp are taken from the 1223182007Sroberto * certificate value structure. For all certificates the 1224182007Sroberto * timestamp is the latest signature update time. For 1225182007Sroberto * host and imported certificates the filestamp is the 1226182007Sroberto * creation epoch. For signed certificates the filestamp 1227182007Sroberto * is the creation epoch of the trusted certificate at 1228280849Scy * the root of the certificate trail. In principle, this 1229182007Sroberto * allows strong checking for signature masquerade. 1230182007Sroberto */ 1231280849Scy if (xp == NULL) 1232280849Scy xp = yp; 1233280849Scy if (xp == NULL) 1234280849Scy break; 1235280849Scy 1236182007Sroberto if (tstamp == 0) 1237182007Sroberto break; 1238182007Sroberto 1239280849Scy len = crypto_send(fp, &xp->cert, start); 124082498Sroberto break; 124182498Sroberto 124282498Sroberto /* 1243132451Sroberto * Send challenge in Schnorr (IFF) identity scheme. 124482498Sroberto */ 1245132451Sroberto case CRYPTO_IFF: 1246280849Scy if (peer == NULL) 1247280849Scy break; /* hack attack */ 1248280849Scy 1249182007Sroberto if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) { 1250280849Scy len = crypto_send(fp, &vtemp, start); 1251182007Sroberto value_free(&vtemp); 1252182007Sroberto } 125382498Sroberto break; 125482498Sroberto 125582498Sroberto /* 1256132451Sroberto * Send response in Schnorr (IFF) identity scheme. 125782498Sroberto */ 1258132451Sroberto case CRYPTO_IFF | CRYPTO_RESP: 1259182007Sroberto if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) { 1260280849Scy len = crypto_send(fp, &vtemp, start); 1261182007Sroberto value_free(&vtemp); 1262182007Sroberto } 1263132451Sroberto break; 1264132451Sroberto 126582498Sroberto /* 1266132451Sroberto * Send challenge in Guillou-Quisquater (GQ) identity scheme. 126782498Sroberto */ 1268132451Sroberto case CRYPTO_GQ: 1269280849Scy if (peer == NULL) 1270280849Scy break; /* hack attack */ 1271280849Scy 1272182007Sroberto if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) { 1273280849Scy len = crypto_send(fp, &vtemp, start); 1274182007Sroberto value_free(&vtemp); 1275182007Sroberto } 127682498Sroberto break; 127782498Sroberto 127882498Sroberto /* 1279132451Sroberto * Send response in Guillou-Quisquater (GQ) identity scheme. 128082498Sroberto */ 1281132451Sroberto case CRYPTO_GQ | CRYPTO_RESP: 1282182007Sroberto if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) { 1283280849Scy len = crypto_send(fp, &vtemp, start); 1284182007Sroberto value_free(&vtemp); 1285182007Sroberto } 1286132451Sroberto break; 1287132451Sroberto 1288132451Sroberto /* 1289132451Sroberto * Send challenge in MV identity scheme. 1290132451Sroberto */ 1291132451Sroberto case CRYPTO_MV: 1292280849Scy if (peer == NULL) 1293280849Scy break; /* hack attack */ 1294280849Scy 1295182007Sroberto if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) { 1296280849Scy len = crypto_send(fp, &vtemp, start); 1297182007Sroberto value_free(&vtemp); 1298182007Sroberto } 129982498Sroberto break; 130082498Sroberto 130182498Sroberto /* 1302132451Sroberto * Send response in MV identity scheme. 130382498Sroberto */ 1304132451Sroberto case CRYPTO_MV | CRYPTO_RESP: 1305182007Sroberto if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) { 1306280849Scy len = crypto_send(fp, &vtemp, start); 1307182007Sroberto value_free(&vtemp); 1308182007Sroberto } 1309132451Sroberto break; 1310132451Sroberto 1311132451Sroberto /* 1312132451Sroberto * Send certificate sign response. The integrity of the request 1313132451Sroberto * certificate has already been verified on the receive side. 1314132451Sroberto * Sign the response using the local server key. Use the 1315132451Sroberto * filestamp from the request and use the timestamp as the 1316132451Sroberto * current time. Light the error bit if the certificate is 1317132451Sroberto * invalid or contains an unverified signature. 1318132451Sroberto */ 1319132451Sroberto case CRYPTO_SIGN | CRYPTO_RESP: 1320280849Scy if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK) { 1321280849Scy len = crypto_send(fp, &vtemp, start); 1322280849Scy value_free(&vtemp); 1323280849Scy } 1324132451Sroberto break; 1325132451Sroberto 1326132451Sroberto /* 1327132451Sroberto * Send public key and signature. Use the values from the public 1328132451Sroberto * key. 1329132451Sroberto */ 1330132451Sroberto case CRYPTO_COOK: 1331280849Scy len = crypto_send(fp, &pubkey, start); 1332132451Sroberto break; 1333132451Sroberto 1334132451Sroberto /* 1335132451Sroberto * Encrypt and send cookie and signature. Light the error bit if 1336132451Sroberto * anything goes wrong. 1337132451Sroberto */ 1338132451Sroberto case CRYPTO_COOK | CRYPTO_RESP: 1339280849Scy vallen = ntohl(ep->vallen); /* Must be <64k */ 1340280849Scy if ( vallen == 0 1341280849Scy || (vallen >= MAX_VALLEN) 1342280849Scy || (opcode & 0x0000ffff) < VALUE_LEN + vallen) { 1343182007Sroberto rval = XEVNT_LEN; 134482498Sroberto break; 134582498Sroberto } 1346280849Scy if (peer == NULL) 1347132451Sroberto tcookie = cookie; 1348280849Scy else 1349280849Scy tcookie = peer->hcookie; 1350280849Scy if ((rval = crypto_encrypt((const u_char *)ep->pkt, vallen, &tcookie, &vtemp)) 1351280849Scy == XEVNT_OK) { 1352280849Scy len = crypto_send(fp, &vtemp, start); 1353280849Scy value_free(&vtemp); 1354132451Sroberto } 135582498Sroberto break; 135682498Sroberto 135782498Sroberto /* 1358132451Sroberto * Find peer and send autokey data and signature in broadcast 1359132451Sroberto * server and symmetric modes. Use the values in the autokey 1360132451Sroberto * structure. If no association is found, either the server has 1361132451Sroberto * restarted with new associations or some perp has replayed an 1362132451Sroberto * old message, in which case light the error bit. 136382498Sroberto */ 1364132451Sroberto case CRYPTO_AUTO | CRYPTO_RESP: 1365280849Scy if (peer == NULL) { 1366280849Scy if ((peer = findpeerbyassoc(associd)) == NULL) { 1367280849Scy rval = XEVNT_ERR; 1368280849Scy break; 1369280849Scy } 137082498Sroberto } 1371132451Sroberto peer->flags &= ~FLAG_ASSOC; 1372280849Scy len = crypto_send(fp, &peer->sndval, start); 137382498Sroberto break; 137482498Sroberto 137582498Sroberto /* 1376280849Scy * Send leapseconds values and signature. Use the values from 1377280849Scy * the tai structure. If no table has been loaded, just send an 1378182007Sroberto * empty request. 137982498Sroberto */ 1380280849Scy case CRYPTO_LEAP | CRYPTO_RESP: 1381280849Scy len = crypto_send(fp, &tai_leap, start); 138282498Sroberto break; 138382498Sroberto 138482498Sroberto /* 1385280849Scy * Default - Send a valid command for unknown requests; send 1386280849Scy * an error response for unknown resonses. 138782498Sroberto */ 138882498Sroberto default: 138982498Sroberto if (opcode & CRYPTO_RESP) 1390182007Sroberto rval = XEVNT_ERR; 139182498Sroberto } 139282498Sroberto 139382498Sroberto /* 1394182007Sroberto * In case of error, flame the log. If a request, toss the 1395182007Sroberto * puppy; if a response, return so the sender can flame, too. 1396132451Sroberto */ 1397182007Sroberto if (rval != XEVNT_OK) { 1398280849Scy u_int32 uint32; 1399280849Scy 1400280849Scy uint32 = CRYPTO_ERROR; 1401280849Scy opcode |= uint32; 1402280849Scy fp->opcode |= htonl(uint32); 1403280849Scy snprintf(statstr, sizeof(statstr), 1404280849Scy "%04x %d %02x %s", opcode, associd, rval, 1405280849Scy eventstr(rval)); 1406132451Sroberto record_crypto_stats(srcadr_sin, statstr); 1407285169Scy DPRINTF(1, ("crypto_xmit: %s\n", statstr)); 1408182007Sroberto if (!(opcode & CRYPTO_RESP)) 1409182007Sroberto return (0); 1410132451Sroberto } 1411285169Scy DPRINTF(1, ("crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n", 1412285169Scy crypto_flags, start, len, opcode >> 16, associd)); 141382498Sroberto return (len); 141482498Sroberto} 141582498Sroberto 1416132451Sroberto 141782498Sroberto/* 1418280849Scy * crypto_verify - verify the extension field value and signature 1419132451Sroberto * 1420132451Sroberto * Returns 1421132451Sroberto * XEVNT_OK success 1422280849Scy * XEVNT_ERR protocol error 1423280849Scy * XEVNT_FSP bad filestamp 1424132451Sroberto * XEVNT_LEN bad field format or length 1425132451Sroberto * XEVNT_PUB bad or missing public key 1426132451Sroberto * XEVNT_SGL bad signature length 1427132451Sroberto * XEVNT_SIG signature not verified 1428280849Scy * XEVNT_TSP bad timestamp 142982498Sroberto */ 1430132451Srobertostatic int 1431132451Srobertocrypto_verify( 1432132451Sroberto struct exten *ep, /* extension pointer */ 1433132451Sroberto struct value *vp, /* value pointer */ 1434132451Sroberto struct peer *peer /* peer structure pointer */ 1435132451Sroberto ) 143682498Sroberto{ 1437132451Sroberto EVP_PKEY *pkey; /* server public key */ 1438309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 1439182007Sroberto tstamp_t tstamp, tstamp1 = 0; /* timestamp */ 1440182007Sroberto tstamp_t fstamp, fstamp1 = 0; /* filestamp */ 1441132451Sroberto u_int vallen; /* value length */ 1442132451Sroberto u_int siglen; /* signature length */ 1443132451Sroberto u_int opcode, len; 1444132451Sroberto int i; 144582498Sroberto 144682498Sroberto /* 1447280849Scy * We are extremely parannoyed. We require valid opcode, length, 1448280849Scy * association ID, timestamp, filestamp, public key, digest, 1449280849Scy * signature length and signature, where relevant. Note that 1450280849Scy * preliminary length checks are done in the main loop. 145182498Sroberto */ 1452132451Sroberto len = ntohl(ep->opcode) & 0x0000ffff; 1453132451Sroberto opcode = ntohl(ep->opcode) & 0xffff0000; 145482498Sroberto 145582498Sroberto /* 1456280849Scy * Check for valid value header, association ID and extension 1457280849Scy * field length. Remember, it is not an error to receive an 1458280849Scy * unsolicited response; however, the response ID must match 1459280849Scy * the association ID. 146082498Sroberto */ 1461132451Sroberto if (opcode & CRYPTO_ERROR) 1462182007Sroberto return (XEVNT_ERR); 1463182007Sroberto 1464280849Scy if (len < VALUE_LEN) 1465280849Scy return (XEVNT_LEN); 1466280849Scy 1467280849Scy if (opcode == (CRYPTO_AUTO | CRYPTO_RESP) && (peer->pmode == 1468280849Scy MODE_BROADCAST || (peer->cast_flags & MDF_BCLNT))) { 1469280849Scy if (ntohl(ep->associd) != peer->assoc) 1470280849Scy return (XEVNT_ERR); 1471132451Sroberto } else { 1472280849Scy if (ntohl(ep->associd) != peer->associd) 1473280849Scy return (XEVNT_ERR); 1474132451Sroberto } 1475182007Sroberto 1476132451Sroberto /* 1477280849Scy * We have a valid value header. Check for valid value and 1478280849Scy * signature field lengths. The extension field length must be 1479280849Scy * long enough to contain the value header, value and signature. 1480280849Scy * Note both the value and signature field lengths are rounded 1481280849Scy * up to the next word (4 octets). 1482132451Sroberto */ 1483132451Sroberto vallen = ntohl(ep->vallen); 1484280849Scy if ( vallen == 0 1485280849Scy || vallen > MAX_VALLEN) 1486280849Scy return (XEVNT_LEN); 1487280849Scy 1488132451Sroberto i = (vallen + 3) / 4; 1489344884Scy siglen = ntohl(ep->pkt[i]); 1490344884Scy ++i; 1491280849Scy if ( siglen > MAX_VALLEN 1492280849Scy || len - VALUE_LEN < ((vallen + 3) / 4) * 4 1493280849Scy || len - VALUE_LEN - ((vallen + 3) / 4) * 4 1494280849Scy < ((siglen + 3) / 4) * 4) 1495132451Sroberto return (XEVNT_LEN); 1496132451Sroberto 1497182007Sroberto /* 1498182007Sroberto * Check for valid timestamp and filestamp. If the timestamp is 1499182007Sroberto * zero, the sender is not synchronized and signatures are 1500280849Scy * not possible. If nonzero the timestamp must not precede the 1501182007Sroberto * filestamp. The timestamp and filestamp must not precede the 1502280849Scy * corresponding values in the value structure, if present. 1503280849Scy */ 1504182007Sroberto tstamp = ntohl(ep->tstamp); 1505182007Sroberto fstamp = ntohl(ep->fstamp); 1506182007Sroberto if (tstamp == 0) 1507280849Scy return (XEVNT_TSP); 1508182007Sroberto 1509182007Sroberto if (tstamp < fstamp) 1510182007Sroberto return (XEVNT_TSP); 1511182007Sroberto 1512182007Sroberto if (vp != NULL) { 1513182007Sroberto tstamp1 = ntohl(vp->tstamp); 1514182007Sroberto fstamp1 = ntohl(vp->fstamp); 1515280849Scy if (tstamp1 != 0 && fstamp1 != 0) { 1516280849Scy if (tstamp < tstamp1) 1517280849Scy return (XEVNT_TSP); 1518182007Sroberto 1519280849Scy if ((tstamp < fstamp1 || fstamp < fstamp1)) 1520280849Scy return (XEVNT_FSP); 1521280849Scy } 1522182007Sroberto } 1523182007Sroberto 1524182007Sroberto /* 1525280849Scy * At the time the certificate message is validated, the public 1526280849Scy * key in the message is not available. Thus, don't try to 1527280849Scy * verify the signature. 1528280849Scy */ 1529280849Scy if (opcode == (CRYPTO_CERT | CRYPTO_RESP)) 1530280849Scy return (XEVNT_OK); 1531280849Scy 1532280849Scy /* 1533182007Sroberto * Check for valid signature length, public key and digest 1534182007Sroberto * algorithm. 1535182007Sroberto */ 1536132451Sroberto if (crypto_flags & peer->crypto & CRYPTO_FLAG_PRIV) 1537132451Sroberto pkey = sign_pkey; 1538132451Sroberto else 1539132451Sroberto pkey = peer->pkey; 1540182007Sroberto if (siglen == 0 || pkey == NULL || peer->digest == NULL) 1541280849Scy return (XEVNT_ERR); 1542132451Sroberto 1543182007Sroberto if (siglen != (u_int)EVP_PKEY_size(pkey)) 1544182007Sroberto return (XEVNT_SGL); 1545182007Sroberto 1546132451Sroberto /* 1547182007Sroberto * Darn, I thought we would never get here. Verify the 1548182007Sroberto * signature. If the identity exchange is verified, light the 1549280849Scy * proventic bit. What a relief. 1550132451Sroberto */ 1551309007Sdelphij ctx = EVP_MD_CTX_new(); 1552309007Sdelphij EVP_VerifyInit(ctx, peer->digest); 1553280849Scy /* XXX: the "+ 12" needs to be at least documented... */ 1554309007Sdelphij EVP_VerifyUpdate(ctx, (u_char *)&ep->tstamp, vallen + 12); 1555309007Sdelphij if (EVP_VerifyFinal(ctx, (u_char *)&ep->pkt[i], siglen, 1556309007Sdelphij pkey) <= 0) { 1557309007Sdelphij EVP_MD_CTX_free(ctx); 1558182007Sroberto return (XEVNT_SIG); 1559309007Sdelphij } 1560309007Sdelphij EVP_MD_CTX_free(ctx); 1561182007Sroberto 1562280849Scy if (peer->crypto & CRYPTO_FLAG_VRFY) 1563182007Sroberto peer->crypto |= CRYPTO_FLAG_PROV; 1564182007Sroberto return (XEVNT_OK); 1565132451Sroberto} 1566132451Sroberto 1567132451Sroberto 1568132451Sroberto/* 1569280849Scy * crypto_encrypt - construct vp (encrypted cookie and signature) from 1570280849Scy * the public key and cookie. 1571132451Sroberto * 1572280849Scy * Returns: 1573132451Sroberto * XEVNT_OK success 1574280849Scy * XEVNT_CKY bad or missing cookie 1575132451Sroberto * XEVNT_PUB bad or missing public key 1576132451Sroberto */ 1577132451Srobertostatic int 1578132451Srobertocrypto_encrypt( 1579280849Scy const u_char *ptr, /* Public Key */ 1580280849Scy u_int vallen, /* Length of Public Key */ 1581280849Scy keyid_t *cookie, /* server cookie */ 1582280849Scy struct value *vp /* value pointer */ 1583132451Sroberto ) 1584132451Sroberto{ 1585132451Sroberto EVP_PKEY *pkey; /* public key */ 1586309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 1587132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 1588132451Sroberto u_int32 temp32; 1589280849Scy u_char *puch; 1590132451Sroberto 1591132451Sroberto /* 1592132451Sroberto * Extract the public key from the request. 1593132451Sroberto */ 1594280849Scy pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, vallen); 1595132451Sroberto if (pkey == NULL) { 1596280849Scy msyslog(LOG_ERR, "crypto_encrypt: %s", 1597132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 1598132451Sroberto return (XEVNT_PUB); 159982498Sroberto } 160082498Sroberto 160182498Sroberto /* 1602132451Sroberto * Encrypt the cookie, encode in ASN.1 and sign. 160382498Sroberto */ 1604280849Scy memset(vp, 0, sizeof(struct value)); 1605132451Sroberto tstamp = crypto_time(); 1606132451Sroberto vp->tstamp = htonl(tstamp); 1607132451Sroberto vp->fstamp = hostval.tstamp; 1608280849Scy vallen = EVP_PKEY_size(pkey); 1609280849Scy vp->vallen = htonl(vallen); 1610280849Scy vp->ptr = emalloc(vallen); 1611280849Scy puch = vp->ptr; 1612132451Sroberto temp32 = htonl(*cookie); 1613280849Scy if (RSA_public_encrypt(4, (u_char *)&temp32, puch, 1614309007Sdelphij EVP_PKEY_get0_RSA(pkey), RSA_PKCS1_OAEP_PADDING) <= 0) { 1615280849Scy msyslog(LOG_ERR, "crypto_encrypt: %s", 1616132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 1617280849Scy free(vp->ptr); 1618132451Sroberto EVP_PKEY_free(pkey); 1619132451Sroberto return (XEVNT_CKY); 1620132451Sroberto } 1621132451Sroberto EVP_PKEY_free(pkey); 1622132451Sroberto if (tstamp == 0) 1623132451Sroberto return (XEVNT_OK); 1624182007Sroberto 1625132451Sroberto vp->sig = emalloc(sign_siglen); 1626309007Sdelphij ctx = EVP_MD_CTX_new(); 1627309007Sdelphij EVP_SignInit(ctx, sign_digest); 1628309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 1629309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, vallen); 1630309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &vallen, sign_pkey)) { 1631289764Sglebius INSIST(vallen <= sign_siglen); 1632285169Scy vp->siglen = htonl(vallen); 1633285169Scy } 1634309007Sdelphij EVP_MD_CTX_free(ctx); 1635132451Sroberto return (XEVNT_OK); 1636132451Sroberto} 163782498Sroberto 1638132451Sroberto 1639132451Sroberto/* 1640132451Sroberto * crypto_ident - construct extension field for identity scheme 1641132451Sroberto * 1642132451Sroberto * This routine determines which identity scheme is in use and 1643132451Sroberto * constructs an extension field for that scheme. 1644280849Scy * 1645280849Scy * Returns 1646280849Scy * CRYTPO_IFF IFF scheme 1647280849Scy * CRYPTO_GQ GQ scheme 1648280849Scy * CRYPTO_MV MV scheme 1649280849Scy * CRYPTO_NULL no available scheme 1650132451Sroberto */ 1651132451Srobertou_int 1652132451Srobertocrypto_ident( 1653132451Sroberto struct peer *peer /* peer structure pointer */ 1654132451Sroberto ) 1655132451Sroberto{ 1656280849Scy char filename[MAXFILENAME]; 1657280849Scy const char * scheme_name; 1658280849Scy u_int scheme_id; 1659132451Sroberto 166082498Sroberto /* 1661280849Scy * We come here after the group trusted host has been found; its 1662280849Scy * name defines the group name. Search the key cache for all 1663280849Scy * keys matching the same group name in order IFF, GQ and MV. 1664280849Scy * Use the first one available. 166582498Sroberto */ 1666280849Scy scheme_name = NULL; 1667132451Sroberto if (peer->crypto & CRYPTO_FLAG_IFF) { 1668280849Scy scheme_name = "iff"; 1669280849Scy scheme_id = CRYPTO_IFF; 1670280849Scy } else if (peer->crypto & CRYPTO_FLAG_GQ) { 1671280849Scy scheme_name = "gq"; 1672280849Scy scheme_id = CRYPTO_GQ; 1673280849Scy } else if (peer->crypto & CRYPTO_FLAG_MV) { 1674280849Scy scheme_name = "mv"; 1675280849Scy scheme_id = CRYPTO_MV; 1676132451Sroberto } 1677132451Sroberto 1678280849Scy if (scheme_name != NULL) { 1679280849Scy snprintf(filename, sizeof(filename), "ntpkey_%spar_%s", 1680280849Scy scheme_name, peer->ident); 1681280849Scy peer->ident_pkey = crypto_key(filename, NULL, 1682280849Scy &peer->srcadr); 1683132451Sroberto if (peer->ident_pkey != NULL) 1684280849Scy return scheme_id; 1685132451Sroberto } 1686132451Sroberto 1687280849Scy msyslog(LOG_NOTICE, 1688280849Scy "crypto_ident: no identity parameters found for group %s", 1689280849Scy peer->ident); 1690280849Scy 1691280849Scy return CRYPTO_NULL; 1692132451Sroberto} 169382498Sroberto 1694132451Sroberto 1695132451Sroberto/* 1696132451Sroberto * crypto_args - construct extension field from arguments 1697132451Sroberto * 1698132451Sroberto * This routine creates an extension field with current timestamps and 1699132451Sroberto * specified opcode, association ID and optional string. Note that the 1700132451Sroberto * extension field is created here, but freed after the crypto_xmit() 1701132451Sroberto * call in the protocol module. 1702132451Sroberto * 1703280849Scy * Returns extension field pointer (no errors) 1704280849Scy * 1705280849Scy * XXX: opcode and len should really be 32-bit quantities and 1706280849Scy * we should make sure that str is not too big. 1707132451Sroberto */ 1708132451Srobertostruct exten * 1709132451Srobertocrypto_args( 1710132451Sroberto struct peer *peer, /* peer structure pointer */ 1711132451Sroberto u_int opcode, /* operation code */ 1712280849Scy associd_t associd, /* association ID */ 1713132451Sroberto char *str /* argument string */ 1714132451Sroberto ) 1715132451Sroberto{ 1716132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 1717132451Sroberto struct exten *ep; /* extension field pointer */ 1718132451Sroberto u_int len; /* extension field length */ 1719282408Scy size_t slen = 0; 1720132451Sroberto 1721132451Sroberto tstamp = crypto_time(); 1722132451Sroberto len = sizeof(struct exten); 1723280849Scy if (str != NULL) { 1724280849Scy slen = strlen(str); 1725280849Scy INSIST(slen < MAX_VALLEN); 1726280849Scy len += slen; 1727280849Scy } 1728280849Scy ep = emalloc_zero(len); 1729182007Sroberto if (opcode == 0) 1730182007Sroberto return (ep); 1731182007Sroberto 1732280849Scy REQUIRE(0 == (len & ~0x0000ffff)); 1733280849Scy REQUIRE(0 == (opcode & ~0xffff0000)); 1734280849Scy 1735132451Sroberto ep->opcode = htonl(opcode + len); 1736280849Scy ep->associd = htonl(associd); 1737132451Sroberto ep->tstamp = htonl(tstamp); 1738132451Sroberto ep->fstamp = hostval.tstamp; 1739132451Sroberto ep->vallen = 0; 1740132451Sroberto if (str != NULL) { 1741280849Scy ep->vallen = htonl(slen); 1742280849Scy memcpy((char *)ep->pkt, str, slen); 1743132451Sroberto } 1744132451Sroberto return (ep); 174582498Sroberto} 174682498Sroberto 174782498Sroberto 174882498Sroberto/* 1749132451Sroberto * crypto_send - construct extension field from value components 1750132451Sroberto * 1751280849Scy * The value and signature fields are zero-padded to a word boundary. 1752280849Scy * Note: it is not polite to send a nonempty signature with zero 1753280849Scy * timestamp or a nonzero timestamp with an empty signature, but those 1754280849Scy * rules are not enforced here. 1755280849Scy * 1756280849Scy * XXX This code won't work on a box with 16-bit ints. 175782498Sroberto */ 1758280849Scyint 1759132451Srobertocrypto_send( 1760132451Sroberto struct exten *ep, /* extension field pointer */ 1761280849Scy struct value *vp, /* value pointer */ 1762280849Scy int start /* buffer offset */ 1763132451Sroberto ) 176482498Sroberto{ 1765280849Scy u_int len, vallen, siglen, opcode; 1766280849Scy u_int i, j; 176782498Sroberto 176882498Sroberto /* 1769280849Scy * Calculate extension field length and check for buffer 1770280849Scy * overflow. Leave room for the MAC. 177182498Sroberto */ 1772280849Scy len = 16; /* XXX Document! */ 1773280849Scy vallen = ntohl(vp->vallen); 1774280849Scy INSIST(vallen <= MAX_VALLEN); 1775280849Scy len += ((vallen + 3) / 4 + 1) * 4; 1776280849Scy siglen = ntohl(vp->siglen); 1777280849Scy len += ((siglen + 3) / 4 + 1) * 4; 1778280849Scy if (start + len > sizeof(struct pkt) - MAX_MAC_LEN) 1779280849Scy return (0); 1780280849Scy 1781280849Scy /* 1782280849Scy * Copy timestamps. 1783280849Scy */ 1784132451Sroberto ep->tstamp = vp->tstamp; 1785132451Sroberto ep->fstamp = vp->fstamp; 1786132451Sroberto ep->vallen = vp->vallen; 1787132451Sroberto 1788132451Sroberto /* 1789280849Scy * Copy value. If the data field is empty or zero length, 1790280849Scy * encode an empty value with length zero. 1791280849Scy */ 1792280849Scy i = 0; 1793280849Scy if (vallen > 0 && vp->ptr != NULL) { 1794280849Scy j = vallen / 4; 1795280849Scy if (j * 4 < vallen) 1796280849Scy ep->pkt[i + j++] = 0; 1797280849Scy memcpy(&ep->pkt[i], vp->ptr, vallen); 1798280849Scy i += j; 1799280849Scy } 1800280849Scy 1801280849Scy /* 1802132451Sroberto * Copy signature. If the signature field is empty or zero 1803132451Sroberto * length, encode an empty signature with length zero. 1804132451Sroberto */ 1805132451Sroberto ep->pkt[i++] = vp->siglen; 1806280849Scy if (siglen > 0 && vp->sig != NULL) { 1807280849Scy j = siglen / 4; 1808280849Scy if (j * 4 < siglen) 1809280849Scy ep->pkt[i + j++] = 0; 1810280849Scy memcpy(&ep->pkt[i], vp->sig, siglen); 1811289764Sglebius /* i += j; */ /* We don't use i after this */ 1812280849Scy } 1813280849Scy opcode = ntohl(ep->opcode); 1814280849Scy ep->opcode = htonl((opcode & 0xffff0000) | len); 1815280849Scy ENSURE(len <= MAX_VALLEN); 1816132451Sroberto return (len); 1817132451Sroberto} 1818132451Sroberto 1819132451Sroberto 1820132451Sroberto/* 1821132451Sroberto * crypto_update - compute new public value and sign extension fields 1822132451Sroberto * 1823132451Sroberto * This routine runs periodically, like once a day, and when something 1824132451Sroberto * changes. It updates the timestamps on three value structures and one 1825132451Sroberto * value structure list, then signs all the structures: 1826132451Sroberto * 1827132451Sroberto * hostval host name (not signed) 1828132451Sroberto * pubkey public key 1829132451Sroberto * cinfo certificate info/value list 1830280849Scy * tai_leap leap values 1831132451Sroberto * 1832280849Scy * Filestamps are proventic data, so this routine runs only when the 1833280849Scy * host is synchronized to a proventicated source. Thus, the timestamp 1834280849Scy * is proventic and can be used to deflect clogging attacks. 1835132451Sroberto * 1836132451Sroberto * Returns void (no errors) 1837132451Sroberto */ 1838132451Srobertovoid 1839132451Srobertocrypto_update(void) 1840132451Sroberto{ 1841309007Sdelphij EVP_MD_CTX *ctx; /* message digest context */ 1842280849Scy struct cert_info *cp; /* certificate info/value */ 1843132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 1844280849Scy u_int32 *ptr; 1845132451Sroberto u_int len; 1846285169Scy leap_result_t leap_data; 1847132451Sroberto 1848280849Scy hostval.tstamp = htonl(crypto_time()); 1849280849Scy if (hostval.tstamp == 0) 185082498Sroberto return; 1851182007Sroberto 1852309007Sdelphij ctx = EVP_MD_CTX_new(); 1853309007Sdelphij 185482498Sroberto /* 1855132451Sroberto * Sign public key and timestamps. The filestamp is derived from 1856132451Sroberto * the host key file extension from wherever the file was 1857132451Sroberto * generated. 185882498Sroberto */ 1859132451Sroberto if (pubkey.vallen != 0) { 1860132451Sroberto pubkey.tstamp = hostval.tstamp; 1861132451Sroberto pubkey.siglen = 0; 1862132451Sroberto if (pubkey.sig == NULL) 1863132451Sroberto pubkey.sig = emalloc(sign_siglen); 1864309007Sdelphij EVP_SignInit(ctx, sign_digest); 1865309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&pubkey, 12); 1866309007Sdelphij EVP_SignUpdate(ctx, pubkey.ptr, ntohl(pubkey.vallen)); 1867309007Sdelphij if (EVP_SignFinal(ctx, pubkey.sig, &len, sign_pkey)) { 1868289764Sglebius INSIST(len <= sign_siglen); 1869285169Scy pubkey.siglen = htonl(len); 1870285169Scy } 187182498Sroberto } 187282498Sroberto 187382498Sroberto /* 1874132451Sroberto * Sign certificates and timestamps. The filestamp is derived 1875132451Sroberto * from the certificate file extension from wherever the file 1876182007Sroberto * was generated. Note we do not throw expired certificates 1877182007Sroberto * away; they may have signed younger ones. 187882498Sroberto */ 1879280849Scy for (cp = cinfo; cp != NULL; cp = cp->link) { 1880182007Sroberto cp->cert.tstamp = hostval.tstamp; 1881182007Sroberto cp->cert.siglen = 0; 1882182007Sroberto if (cp->cert.sig == NULL) 1883182007Sroberto cp->cert.sig = emalloc(sign_siglen); 1884309007Sdelphij EVP_SignInit(ctx, sign_digest); 1885309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&cp->cert, 12); 1886309007Sdelphij EVP_SignUpdate(ctx, cp->cert.ptr, 1887182007Sroberto ntohl(cp->cert.vallen)); 1888309007Sdelphij if (EVP_SignFinal(ctx, cp->cert.sig, &len, sign_pkey)) { 1889289764Sglebius INSIST(len <= sign_siglen); 1890285169Scy cp->cert.siglen = htonl(len); 1891285169Scy } 189282498Sroberto } 189382498Sroberto 189482498Sroberto /* 1895280849Scy * Sign leapseconds values and timestamps. Note it is not an 1896280849Scy * error to return null values. 189782498Sroberto */ 1898280849Scy tai_leap.tstamp = hostval.tstamp; 1899280849Scy tai_leap.fstamp = hostval.fstamp; 1900285169Scy 1901285169Scy /* Get the leap second era. We might need a full lookup early 1902285169Scy * after start, when the cache is not yet loaded. 1903285169Scy */ 1904285169Scy leapsec_frame(&leap_data); 1905285169Scy if ( ! memcmp(&leap_data.ebase, &leap_data.ttime, sizeof(vint64))) { 1906285169Scy time_t now = time(NULL); 1907285169Scy uint32_t nowntp = (uint32_t)now + JAN_1970; 1908285169Scy leapsec_query(&leap_data, nowntp, &now); 1909285169Scy } 1910285169Scy 1911285169Scy /* Create the data block. The protocol does not work without. */ 1912280849Scy len = 3 * sizeof(u_int32); 1913285169Scy if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) { 1914285169Scy free(tai_leap.ptr); 1915280849Scy tai_leap.ptr = emalloc(len); 1916285169Scy tai_leap.vallen = htonl(len); 1917285169Scy } 1918280849Scy ptr = (u_int32 *)tai_leap.ptr; 1919285169Scy if (leap_data.tai_offs > 10) { 1920285169Scy /* create a TAI / leap era block. The end time is a 1921285169Scy * fake -- maybe we can do better. 1922285169Scy */ 1923285169Scy ptr[0] = htonl(leap_data.tai_offs); 1924285169Scy ptr[1] = htonl(leap_data.ebase.d_s.lo); 1925285169Scy if (leap_data.ttime.d_s.hi >= 0) 1926285169Scy ptr[2] = htonl(leap_data.ttime.D_s.lo + 7*86400); 1927285169Scy else 1928285169Scy ptr[2] = htonl(leap_data.ebase.D_s.lo + 25*86400); 1929285169Scy } else { 1930285169Scy /* no leap era available */ 1931285169Scy memset(ptr, 0, len); 1932285169Scy } 1933280849Scy if (tai_leap.sig == NULL) 1934280849Scy tai_leap.sig = emalloc(sign_siglen); 1935309007Sdelphij EVP_SignInit(ctx, sign_digest); 1936309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&tai_leap, 12); 1937309007Sdelphij EVP_SignUpdate(ctx, tai_leap.ptr, len); 1938309007Sdelphij if (EVP_SignFinal(ctx, tai_leap.sig, &len, sign_pkey)) { 1939289764Sglebius INSIST(len <= sign_siglen); 1940285169Scy tai_leap.siglen = htonl(len); 1941285169Scy } 1942285169Scy crypto_flags |= CRYPTO_FLAG_TAI; 1943285169Scy 1944280849Scy snprintf(statstr, sizeof(statstr), "signature update ts %u", 1945280849Scy ntohl(hostval.tstamp)); 1946132451Sroberto record_crypto_stats(NULL, statstr); 1947285169Scy DPRINTF(1, ("crypto_update: %s\n", statstr)); 1948309007Sdelphij EVP_MD_CTX_free(ctx); 194982498Sroberto} 195082498Sroberto 1951285169Scy/* 1952285169Scy * crypto_update_taichange - eventually trigger crypto_update 1953285169Scy * 1954285169Scy * This is called when a change in 'sys_tai' is detected. This will 1955285169Scy * happen shortly after a leap second is detected, but unhappily also 1956285169Scy * early after system start; also, the crypto stuff might be unused and 1957285169Scy * an unguarded call to crypto_update() causes a crash. 1958285169Scy * 1959285169Scy * This function makes sure that there already *is* a valid crypto block 1960285169Scy * for the use with autokey, and only calls 'crypto_update()' if it can 1961285169Scy * succeed. 1962285169Scy * 1963285169Scy * Returns void (no errors) 1964285169Scy */ 1965285169Scyvoid 1966285169Scycrypto_update_taichange(void) 1967285169Scy{ 1968285169Scy static const u_int len = 3 * sizeof(u_int32); 196982498Sroberto 1970285169Scy /* check if the signing digest algo is available */ 1971285169Scy if (sign_digest == NULL || sign_pkey == NULL) 1972285169Scy return; 1973285169Scy 1974285169Scy /* check size of TAI extension block */ 1975285169Scy if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) 1976285169Scy return; 1977285169Scy 1978285169Scy /* crypto_update should at least not crash here! */ 1979285169Scy crypto_update(); 1980285169Scy} 1981285169Scy 198282498Sroberto/* 1983132451Sroberto * value_free - free value structure components. 1984132451Sroberto * 1985132451Sroberto * Returns void (no errors) 198682498Sroberto */ 1987132451Srobertovoid 1988132451Srobertovalue_free( 1989132451Sroberto struct value *vp /* value structure */ 199082498Sroberto ) 199182498Sroberto{ 1992132451Sroberto if (vp->ptr != NULL) 1993132451Sroberto free(vp->ptr); 1994132451Sroberto if (vp->sig != NULL) 1995132451Sroberto free(vp->sig); 1996132451Sroberto memset(vp, 0, sizeof(struct value)); 1997132451Sroberto} 199882498Sroberto 1999132451Sroberto 2000132451Sroberto/* 2001280849Scy * crypto_time - returns current NTP time. 2002280849Scy * 2003280849Scy * Returns NTP seconds if in synch, 0 otherwise 2004132451Sroberto */ 2005132451Srobertotstamp_t 2006132451Srobertocrypto_time() 2007132451Sroberto{ 2008280849Scy l_fp tstamp; /* NTP time */ 2009132451Sroberto 2010132451Sroberto L_CLR(&tstamp); 2011132451Sroberto if (sys_leap != LEAP_NOTINSYNC) 2012132451Sroberto get_systime(&tstamp); 2013132451Sroberto return (tstamp.l_ui); 2014132451Sroberto} 2015132451Sroberto 2016132451Sroberto 2017132451Sroberto/* 2018280849Scy * asn_to_calendar - convert ASN1_TIME time structure to struct calendar. 2019280849Scy * 2020132451Sroberto */ 2021280849Scystatic 2022280849Scyvoid 2023280849Scyasn_to_calendar ( 2024316068Sdelphij const ASN1_TIME *asn1time, /* pointer to ASN1_TIME structure */ 2025280849Scy struct calendar *pjd /* pointer to result */ 2026132451Sroberto ) 2027132451Sroberto{ 2028280849Scy size_t len; /* length of ASN1_TIME string */ 2029280849Scy char v[24]; /* writable copy of ASN1_TIME string */ 2030280849Scy unsigned long temp; /* result from strtoul */ 2031132451Sroberto 203282498Sroberto /* 2033132451Sroberto * Extract time string YYMMDDHHMMSSZ from ASN1 time structure. 2034280849Scy * Or YYYYMMDDHHMMSSZ. 2035132451Sroberto * Note that the YY, MM, DD fields start with one, the HH, MM, 2036280849Scy * SS fields start with zero and the Z character is ignored. 2037280849Scy * Also note that two-digit years less than 50 map to years greater than 2038280849Scy * 100. Dontcha love ASN.1? Better than MIL-188. 203982498Sroberto */ 2040280849Scy len = asn1time->length; 2041289764Sglebius REQUIRE(len < sizeof(v)); 2042280849Scy (void)strncpy(v, (char *)(asn1time->data), len); 2043289764Sglebius REQUIRE(len >= 13); 2044280849Scy temp = strtoul(v+len-3, NULL, 10); 2045280849Scy pjd->second = temp; 2046280849Scy v[len-3] = '\0'; 2047182007Sroberto 2048280849Scy temp = strtoul(v+len-5, NULL, 10); 2049280849Scy pjd->minute = temp; 2050280849Scy v[len-5] = '\0'; 2051280849Scy 2052280849Scy temp = strtoul(v+len-7, NULL, 10); 2053280849Scy pjd->hour = temp; 2054280849Scy v[len-7] = '\0'; 2055280849Scy 2056280849Scy temp = strtoul(v+len-9, NULL, 10); 2057280849Scy pjd->monthday = temp; 2058280849Scy v[len-9] = '\0'; 2059280849Scy 2060280849Scy temp = strtoul(v+len-11, NULL, 10); 2061280849Scy pjd->month = temp; 2062280849Scy v[len-11] = '\0'; 2063280849Scy 2064280849Scy temp = strtoul(v, NULL, 10); 2065280849Scy /* handle two-digit years */ 2066280849Scy if (temp < 50UL) 2067280849Scy temp += 100UL; 2068280849Scy if (temp < 150UL) 2069280849Scy temp += 1900UL; 2070280849Scy pjd->year = temp; 2071280849Scy 2072280849Scy pjd->yearday = pjd->weekday = 0; 2073280849Scy return; 2074132451Sroberto} 2075132451Sroberto 2076132451Sroberto 2077132451Sroberto/* 2078132451Sroberto * bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number. 2079280849Scy * 2080280849Scy * Returns void (no errors) 2081132451Sroberto */ 2082280849Scystatic void 2083132451Srobertobighash( 2084132451Sroberto BIGNUM *bn, /* BIGNUM * from */ 2085132451Sroberto BIGNUM *bk /* BIGNUM * to */ 2086132451Sroberto ) 2087132451Sroberto{ 2088309007Sdelphij EVP_MD_CTX *ctx; /* message digest context */ 2089132451Sroberto u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */ 2090132451Sroberto u_char *ptr; /* a BIGNUM as binary string */ 2091132451Sroberto u_int len; 2092132451Sroberto 2093132451Sroberto len = BN_num_bytes(bn); 2094132451Sroberto ptr = emalloc(len); 2095132451Sroberto BN_bn2bin(bn, ptr); 2096309007Sdelphij ctx = EVP_MD_CTX_new(); 2097330106Sdelphij# if defined(OPENSSL) && defined(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) 2098330106Sdelphij /* [Bug 3457] set flags and don't kill them again */ 2099330106Sdelphij EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); 2100330106Sdelphij EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 2101330106Sdelphij# else 2102309007Sdelphij EVP_DigestInit(ctx, EVP_md5()); 2103330106Sdelphij# endif 2104309007Sdelphij EVP_DigestUpdate(ctx, ptr, len); 2105309007Sdelphij EVP_DigestFinal(ctx, dgst, &len); 2106309007Sdelphij EVP_MD_CTX_free(ctx); 2107132451Sroberto BN_bin2bn(dgst, len, bk); 2108280849Scy free(ptr); 2109132451Sroberto} 2110132451Sroberto 2111132451Sroberto 2112132451Sroberto/* 2113132451Sroberto *********************************************************************** 2114132451Sroberto * * 2115132451Sroberto * The following routines implement the Schnorr (IFF) identity scheme * 2116132451Sroberto * * 2117132451Sroberto *********************************************************************** 2118132451Sroberto * 2119132451Sroberto * The Schnorr (IFF) identity scheme is intended for use when 2120280849Scy * certificates are generated by some other trusted certificate 2121280849Scy * authority and the certificate cannot be used to convey public 2122280849Scy * parameters. There are two kinds of files: encrypted server files that 2123280849Scy * contain private and public values and nonencrypted client files that 2124280849Scy * contain only public values. New generations of server files must be 2125280849Scy * securely transmitted to all servers of the group; client files can be 2126280849Scy * distributed by any means. The scheme is self contained and 2127280849Scy * independent of new generations of host keys, sign keys and 2128280849Scy * certificates. 2129132451Sroberto * 2130280849Scy * The IFF values hide in a DSA cuckoo structure which uses the same 2131280849Scy * parameters. The values are used by an identity scheme based on DSA 2132280849Scy * cryptography and described in Stimson p. 285. The p is a 512-bit 2133280849Scy * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1 2134280849Scy * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a 2135280849Scy * private random group key b (0 < b < q) and public key v = g^b, then 2136280849Scy * sends (p, q, g, b) to the servers and (p, q, g, v) to the clients. 2137280849Scy * Alice challenges Bob to confirm identity using the protocol described 2138280849Scy * below. 2139132451Sroberto * 2140132451Sroberto * How it works 2141132451Sroberto * 2142132451Sroberto * The scheme goes like this. Both Alice and Bob have the public primes 2143132451Sroberto * p, q and generator g. The TA gives private key b to Bob and public 2144280849Scy * key v to Alice. 2145132451Sroberto * 2146280849Scy * Alice rolls new random challenge r (o < r < q) and sends to Bob in 2147280849Scy * the IFF request message. Bob rolls new random k (0 < k < q), then 2148280849Scy * computes y = k + b r mod q and x = g^k mod p and sends (y, hash(x)) 2149280849Scy * to Alice in the response message. Besides making the response 2150280849Scy * shorter, the hash makes it effectivey impossible for an intruder to 2151280849Scy * solve for b by observing a number of these messages. 2152132451Sroberto * 2153132451Sroberto * Alice receives the response and computes g^y v^r mod p. After a bit 2154132451Sroberto * of algebra, this simplifies to g^k. If the hash of this result 2155132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed 2156132451Sroberto * response binds this knowledge to Bob's private key and the public key 2157132451Sroberto * previously received in his certificate. 2158132451Sroberto * 2159132451Sroberto * crypto_alice - construct Alice's challenge in IFF scheme 2160132451Sroberto * 2161132451Sroberto * Returns 2162132451Sroberto * XEVNT_OK success 2163280849Scy * XEVNT_ID bad or missing group key 2164132451Sroberto * XEVNT_PUB bad or missing public key 2165132451Sroberto */ 2166132451Srobertostatic int 2167132451Srobertocrypto_alice( 2168132451Sroberto struct peer *peer, /* peer pointer */ 2169132451Sroberto struct value *vp /* value pointer */ 2170132451Sroberto ) 2171132451Sroberto{ 2172132451Sroberto DSA *dsa; /* IFF parameters */ 2173132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2174309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2175132451Sroberto tstamp_t tstamp; 2176132451Sroberto u_int len; 2177309007Sdelphij const BIGNUM *q; 2178132451Sroberto 2179132451Sroberto /* 2180132451Sroberto * The identity parameters must have correct format and content. 2181132451Sroberto */ 2182280849Scy if (peer->ident_pkey == NULL) { 2183280849Scy msyslog(LOG_NOTICE, "crypto_alice: scheme unavailable"); 2184132451Sroberto return (XEVNT_ID); 2185280849Scy } 2186182007Sroberto 2187309007Sdelphij if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) { 2188280849Scy msyslog(LOG_NOTICE, "crypto_alice: defective key"); 2189132451Sroberto return (XEVNT_PUB); 2190132451Sroberto } 2191132451Sroberto 2192132451Sroberto /* 2193280849Scy * Roll new random r (0 < r < q). 2194132451Sroberto */ 2195132451Sroberto if (peer->iffval != NULL) 2196132451Sroberto BN_free(peer->iffval); 2197132451Sroberto peer->iffval = BN_new(); 2198309007Sdelphij DSA_get0_pqg(dsa, NULL, &q, NULL); 2199309007Sdelphij len = BN_num_bytes(q); 2200280849Scy BN_rand(peer->iffval, len * 8, -1, 1); /* r mod q*/ 2201280849Scy bctx = BN_CTX_new(); 2202309007Sdelphij BN_mod(peer->iffval, peer->iffval, q, bctx); 2203132451Sroberto BN_CTX_free(bctx); 2204132451Sroberto 2205132451Sroberto /* 2206132451Sroberto * Sign and send to Bob. The filestamp is from the local file. 2207132451Sroberto */ 2208280849Scy memset(vp, 0, sizeof(struct value)); 2209132451Sroberto tstamp = crypto_time(); 2210132451Sroberto vp->tstamp = htonl(tstamp); 2211280849Scy vp->fstamp = htonl(peer->ident_pkey->fstamp); 2212132451Sroberto vp->vallen = htonl(len); 2213132451Sroberto vp->ptr = emalloc(len); 2214132451Sroberto BN_bn2bin(peer->iffval, vp->ptr); 2215132451Sroberto if (tstamp == 0) 2216132451Sroberto return (XEVNT_OK); 2217182007Sroberto 2218132451Sroberto vp->sig = emalloc(sign_siglen); 2219309007Sdelphij ctx = EVP_MD_CTX_new(); 2220309007Sdelphij EVP_SignInit(ctx, sign_digest); 2221309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 2222309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 2223309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 2224289764Sglebius INSIST(len <= sign_siglen); 2225285169Scy vp->siglen = htonl(len); 2226285169Scy } 2227309007Sdelphij EVP_MD_CTX_free(ctx); 2228132451Sroberto return (XEVNT_OK); 2229132451Sroberto} 2230132451Sroberto 2231132451Sroberto 2232132451Sroberto/* 2233132451Sroberto * crypto_bob - construct Bob's response to Alice's challenge 2234132451Sroberto * 2235132451Sroberto * Returns 2236132451Sroberto * XEVNT_OK success 2237280849Scy * XEVNT_ERR protocol error 2238182007Sroberto * XEVNT_ID bad or missing group key 2239132451Sroberto */ 2240132451Srobertostatic int 2241132451Srobertocrypto_bob( 2242132451Sroberto struct exten *ep, /* extension pointer */ 2243132451Sroberto struct value *vp /* value pointer */ 2244132451Sroberto ) 2245132451Sroberto{ 2246132451Sroberto DSA *dsa; /* IFF parameters */ 2247132451Sroberto DSA_SIG *sdsa; /* DSA signature context fake */ 2248132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2249309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2250132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 2251132451Sroberto BIGNUM *bn, *bk, *r; 2252132451Sroberto u_char *ptr; 2253289764Sglebius u_int len; /* extension field value length */ 2254309007Sdelphij const BIGNUM *p, *q, *g; 2255309007Sdelphij const BIGNUM *priv_key; 2256132451Sroberto 2257132451Sroberto /* 2258132451Sroberto * If the IFF parameters are not valid, something awful 2259132451Sroberto * happened or we are being tormented. 2260132451Sroberto */ 2261280849Scy if (iffkey_info == NULL) { 2262280849Scy msyslog(LOG_NOTICE, "crypto_bob: scheme unavailable"); 2263182007Sroberto return (XEVNT_ID); 2264132451Sroberto } 2265309007Sdelphij dsa = EVP_PKEY_get0_DSA(iffkey_info->pkey); 2266309007Sdelphij DSA_get0_pqg(dsa, &p, &q, &g); 2267309007Sdelphij DSA_get0_key(dsa, NULL, &priv_key); 2268132451Sroberto 2269132451Sroberto /* 2270132451Sroberto * Extract r from the challenge. 2271132451Sroberto */ 2272289764Sglebius len = exten_payload_size(ep); 2273289764Sglebius if (len == 0 || len > MAX_VALLEN) 2274289764Sglebius return (XEVNT_LEN); 2275289764Sglebius if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) { 2276280849Scy msyslog(LOG_ERR, "crypto_bob: %s", 2277132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2278182007Sroberto return (XEVNT_ERR); 2279132451Sroberto } 2280132451Sroberto 2281132451Sroberto /* 2282132451Sroberto * Bob rolls random k (0 < k < q), computes y = k + b r mod q 2283132451Sroberto * and x = g^k mod p, then sends (y, hash(x)) to Alice. 2284132451Sroberto */ 2285132451Sroberto bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new(); 2286132451Sroberto sdsa = DSA_SIG_new(); 2287289764Sglebius BN_rand(bk, len * 8, -1, 1); /* k */ 2288309007Sdelphij BN_mod_mul(bn, priv_key, r, q, bctx); /* b r mod q */ 2289132451Sroberto BN_add(bn, bn, bk); 2290309007Sdelphij BN_mod(bn, bn, q, bctx); /* k + b r mod q */ 2291309007Sdelphij BN_mod_exp(bk, g, bk, p, bctx); /* g^k mod p */ 2292132451Sroberto bighash(bk, bk); 2293309007Sdelphij DSA_SIG_set0(sdsa, bn, bk); 2294132451Sroberto BN_CTX_free(bctx); 2295309007Sdelphij BN_free(r); 2296280849Scy#ifdef DEBUG 2297280849Scy if (debug > 1) 2298280849Scy DSA_print_fp(stdout, dsa, 0); 2299280849Scy#endif 2300132451Sroberto 2301132451Sroberto /* 2302280849Scy * Encode the values in ASN.1 and sign. The filestamp is from 2303280849Scy * the local file. 2304132451Sroberto */ 2305289764Sglebius len = i2d_DSA_SIG(sdsa, NULL); 2306289764Sglebius if (len == 0) { 2307280849Scy msyslog(LOG_ERR, "crypto_bob: %s", 2308132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2309132451Sroberto DSA_SIG_free(sdsa); 2310182007Sroberto return (XEVNT_ERR); 2311132451Sroberto } 2312289764Sglebius if (len > MAX_VALLEN) { 2313289764Sglebius msyslog(LOG_ERR, "crypto_bob: signature is too big: %u", 2314289764Sglebius len); 2315280849Scy DSA_SIG_free(sdsa); 2316280849Scy return (XEVNT_LEN); 2317280849Scy } 2318280849Scy memset(vp, 0, sizeof(struct value)); 2319280849Scy tstamp = crypto_time(); 2320280849Scy vp->tstamp = htonl(tstamp); 2321280849Scy vp->fstamp = htonl(iffkey_info->fstamp); 2322289764Sglebius vp->vallen = htonl(len); 2323289764Sglebius ptr = emalloc(len); 2324132451Sroberto vp->ptr = ptr; 2325132451Sroberto i2d_DSA_SIG(sdsa, &ptr); 2326132451Sroberto DSA_SIG_free(sdsa); 2327132451Sroberto if (tstamp == 0) 2328132451Sroberto return (XEVNT_OK); 2329182007Sroberto 2330280849Scy /* XXX: more validation to make sure the sign fits... */ 2331132451Sroberto vp->sig = emalloc(sign_siglen); 2332309007Sdelphij ctx = EVP_MD_CTX_new(); 2333309007Sdelphij EVP_SignInit(ctx, sign_digest); 2334309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 2335309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 2336309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 2337289764Sglebius INSIST(len <= sign_siglen); 2338289764Sglebius vp->siglen = htonl(len); 2339285169Scy } 2340309007Sdelphij EVP_MD_CTX_free(ctx); 2341132451Sroberto return (XEVNT_OK); 2342132451Sroberto} 2343132451Sroberto 2344132451Sroberto 2345132451Sroberto/* 2346132451Sroberto * crypto_iff - verify Bob's response to Alice's challenge 2347132451Sroberto * 2348132451Sroberto * Returns 2349132451Sroberto * XEVNT_OK success 2350280849Scy * XEVNT_FSP bad filestamp 2351280849Scy * XEVNT_ID bad or missing group key 2352132451Sroberto * XEVNT_PUB bad or missing public key 2353132451Sroberto */ 2354132451Srobertoint 2355132451Srobertocrypto_iff( 2356132451Sroberto struct exten *ep, /* extension pointer */ 2357132451Sroberto struct peer *peer /* peer structure pointer */ 2358132451Sroberto ) 2359132451Sroberto{ 2360132451Sroberto DSA *dsa; /* IFF parameters */ 2361132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2362132451Sroberto DSA_SIG *sdsa; /* DSA parameters */ 2363132451Sroberto BIGNUM *bn, *bk; 2364132451Sroberto u_int len; 2365280849Scy const u_char *ptr; 2366132451Sroberto int temp; 2367309007Sdelphij const BIGNUM *p, *g; 2368309007Sdelphij const BIGNUM *r, *s; 2369309007Sdelphij const BIGNUM *pub_key; 2370132451Sroberto 2371132451Sroberto /* 2372132451Sroberto * If the IFF parameters are not valid or no challenge was sent, 2373132451Sroberto * something awful happened or we are being tormented. 2374132451Sroberto */ 2375132451Sroberto if (peer->ident_pkey == NULL) { 2376280849Scy msyslog(LOG_NOTICE, "crypto_iff: scheme unavailable"); 2377182007Sroberto return (XEVNT_ID); 2378132451Sroberto } 2379280849Scy if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) { 2380280849Scy msyslog(LOG_NOTICE, "crypto_iff: invalid filestamp %u", 2381132451Sroberto ntohl(ep->fstamp)); 2382132451Sroberto return (XEVNT_FSP); 2383132451Sroberto } 2384309007Sdelphij if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) { 2385280849Scy msyslog(LOG_NOTICE, "crypto_iff: defective key"); 2386132451Sroberto return (XEVNT_PUB); 2387132451Sroberto } 2388132451Sroberto if (peer->iffval == NULL) { 2389280849Scy msyslog(LOG_NOTICE, "crypto_iff: missing challenge"); 2390182007Sroberto return (XEVNT_ID); 2391132451Sroberto } 2392132451Sroberto 2393132451Sroberto /* 2394132451Sroberto * Extract the k + b r and g^k values from the response. 2395132451Sroberto */ 2396132451Sroberto bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new(); 2397132451Sroberto len = ntohl(ep->vallen); 2398280849Scy ptr = (u_char *)ep->pkt; 2399132451Sroberto if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) { 2400280849Scy BN_free(bn); BN_free(bk); BN_CTX_free(bctx); 2401280849Scy msyslog(LOG_ERR, "crypto_iff: %s", 2402132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2403182007Sroberto return (XEVNT_ERR); 2404132451Sroberto } 2405132451Sroberto 2406132451Sroberto /* 2407132451Sroberto * Compute g^(k + b r) g^(q - b)r mod p. 2408132451Sroberto */ 2409309007Sdelphij DSA_get0_key(dsa, &pub_key, NULL); 2410309007Sdelphij DSA_get0_pqg(dsa, &p, NULL, &g); 2411309007Sdelphij DSA_SIG_get0(sdsa, &r, &s); 2412309007Sdelphij BN_mod_exp(bn, pub_key, peer->iffval, p, bctx); 2413309007Sdelphij BN_mod_exp(bk, g, r, p, bctx); 2414309007Sdelphij BN_mod_mul(bn, bn, bk, p, bctx); 2415132451Sroberto 2416132451Sroberto /* 2417132451Sroberto * Verify the hash of the result matches hash(x). 2418132451Sroberto */ 2419132451Sroberto bighash(bn, bn); 2420309007Sdelphij temp = BN_cmp(bn, s); 2421132451Sroberto BN_free(bn); BN_free(bk); BN_CTX_free(bctx); 2422132451Sroberto BN_free(peer->iffval); 2423132451Sroberto peer->iffval = NULL; 2424132451Sroberto DSA_SIG_free(sdsa); 2425132451Sroberto if (temp == 0) 2426132451Sroberto return (XEVNT_OK); 2427182007Sroberto 2428280849Scy msyslog(LOG_NOTICE, "crypto_iff: identity not verified"); 2429280849Scy return (XEVNT_ID); 2430132451Sroberto} 2431132451Sroberto 2432132451Sroberto 2433132451Sroberto/* 2434132451Sroberto *********************************************************************** 2435132451Sroberto * * 2436132451Sroberto * The following routines implement the Guillou-Quisquater (GQ) * 2437132451Sroberto * identity scheme * 2438132451Sroberto * * 2439132451Sroberto *********************************************************************** 2440132451Sroberto * 2441132451Sroberto * The Guillou-Quisquater (GQ) identity scheme is intended for use when 2442280849Scy * the certificate can be used to convey public parameters. The scheme 2443280849Scy * uses a X509v3 certificate extension field do convey the public key of 2444280849Scy * a private key known only to servers. There are two kinds of files: 2445280849Scy * encrypted server files that contain private and public values and 2446280849Scy * nonencrypted client files that contain only public values. New 2447280849Scy * generations of server files must be securely transmitted to all 2448280849Scy * servers of the group; client files can be distributed by any means. 2449280849Scy * The scheme is self contained and independent of new generations of 2450280849Scy * host keys and sign keys. The scheme is self contained and independent 2451280849Scy * of new generations of host keys and sign keys. 2452132451Sroberto * 2453280849Scy * The GQ parameters hide in a RSA cuckoo structure which uses the same 2454280849Scy * parameters. The values are used by an identity scheme based on RSA 2455280849Scy * cryptography and described in Stimson p. 300 (with errors). The 512- 2456280849Scy * bit public modulus is n = p q, where p and q are secret large primes. 2457280849Scy * The TA rolls private random group key b as RSA exponent. These values 2458280849Scy * are known to all group members. 2459132451Sroberto * 2460280849Scy * When rolling new certificates, a server recomputes the private and 2461132451Sroberto * public keys. The private key u is a random roll, while the public key 2462132451Sroberto * is the inverse obscured by the group key v = (u^-1)^b. These values 2463132451Sroberto * replace the private and public keys normally generated by the RSA 2464132451Sroberto * scheme. Alice challenges Bob to confirm identity using the protocol 2465132451Sroberto * described below. 2466132451Sroberto * 2467132451Sroberto * How it works 2468132451Sroberto * 2469132451Sroberto * The scheme goes like this. Both Alice and Bob have the same modulus n 2470132451Sroberto * and some random b as the group key. These values are computed and 2471132451Sroberto * distributed in advance via secret means, although only the group key 2472132451Sroberto * b is truly secret. Each has a private random private key u and public 2473132451Sroberto * key (u^-1)^b, although not necessarily the same ones. Bob and Alice 2474132451Sroberto * can regenerate the key pair from time to time without affecting 2475132451Sroberto * operations. The public key is conveyed on the certificate in an 2476132451Sroberto * extension field; the private key is never revealed. 2477132451Sroberto * 2478132451Sroberto * Alice rolls new random challenge r and sends to Bob in the GQ 2479132451Sroberto * request message. Bob rolls new random k, then computes y = k u^r mod 2480132451Sroberto * n and x = k^b mod n and sends (y, hash(x)) to Alice in the response 2481132451Sroberto * message. Besides making the response shorter, the hash makes it 2482132451Sroberto * effectivey impossible for an intruder to solve for b by observing 2483132451Sroberto * a number of these messages. 2484132451Sroberto * 2485132451Sroberto * Alice receives the response and computes y^b v^r mod n. After a bit 2486132451Sroberto * of algebra, this simplifies to k^b. If the hash of this result 2487132451Sroberto * matches hash(x), Alice knows that Bob has the group key b. The signed 2488132451Sroberto * response binds this knowledge to Bob's private key and the public key 2489132451Sroberto * previously received in his certificate. 2490132451Sroberto * 2491132451Sroberto * crypto_alice2 - construct Alice's challenge in GQ scheme 2492132451Sroberto * 2493132451Sroberto * Returns 2494132451Sroberto * XEVNT_OK success 2495280849Scy * XEVNT_ID bad or missing group key 2496132451Sroberto * XEVNT_PUB bad or missing public key 2497132451Sroberto */ 2498132451Srobertostatic int 2499132451Srobertocrypto_alice2( 2500132451Sroberto struct peer *peer, /* peer pointer */ 2501132451Sroberto struct value *vp /* value pointer */ 2502132451Sroberto ) 2503132451Sroberto{ 2504132451Sroberto RSA *rsa; /* GQ parameters */ 2505132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2506309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2507132451Sroberto tstamp_t tstamp; 2508132451Sroberto u_int len; 2509309007Sdelphij const BIGNUM *n; 2510132451Sroberto 2511132451Sroberto /* 2512132451Sroberto * The identity parameters must have correct format and content. 2513132451Sroberto */ 2514132451Sroberto if (peer->ident_pkey == NULL) 2515132451Sroberto return (XEVNT_ID); 2516182007Sroberto 2517309007Sdelphij if ((rsa = EVP_PKEY_get0_RSA(peer->ident_pkey->pkey)) == NULL) { 2518280849Scy msyslog(LOG_NOTICE, "crypto_alice2: defective key"); 2519132451Sroberto return (XEVNT_PUB); 252082498Sroberto } 252182498Sroberto 252282498Sroberto /* 2523280849Scy * Roll new random r (0 < r < n). 252482498Sroberto */ 2525132451Sroberto if (peer->iffval != NULL) 2526132451Sroberto BN_free(peer->iffval); 2527132451Sroberto peer->iffval = BN_new(); 2528309007Sdelphij RSA_get0_key(rsa, &n, NULL, NULL); 2529309007Sdelphij len = BN_num_bytes(n); 2530132451Sroberto BN_rand(peer->iffval, len * 8, -1, 1); /* r mod n */ 2531280849Scy bctx = BN_CTX_new(); 2532309007Sdelphij BN_mod(peer->iffval, peer->iffval, n, bctx); 2533132451Sroberto BN_CTX_free(bctx); 2534132451Sroberto 2535132451Sroberto /* 2536132451Sroberto * Sign and send to Bob. The filestamp is from the local file. 2537132451Sroberto */ 2538280849Scy memset(vp, 0, sizeof(struct value)); 2539132451Sroberto tstamp = crypto_time(); 2540132451Sroberto vp->tstamp = htonl(tstamp); 2541280849Scy vp->fstamp = htonl(peer->ident_pkey->fstamp); 2542132451Sroberto vp->vallen = htonl(len); 2543132451Sroberto vp->ptr = emalloc(len); 2544132451Sroberto BN_bn2bin(peer->iffval, vp->ptr); 2545132451Sroberto if (tstamp == 0) 2546132451Sroberto return (XEVNT_OK); 2547182007Sroberto 2548132451Sroberto vp->sig = emalloc(sign_siglen); 2549309007Sdelphij ctx = EVP_MD_CTX_new(); 2550309007Sdelphij EVP_SignInit(ctx, sign_digest); 2551309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 2552309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 2553309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 2554289764Sglebius INSIST(len <= sign_siglen); 2555285169Scy vp->siglen = htonl(len); 2556285169Scy } 2557309007Sdelphij EVP_MD_CTX_free(ctx); 2558132451Sroberto return (XEVNT_OK); 2559132451Sroberto} 2560132451Sroberto 2561132451Sroberto 2562132451Sroberto/* 2563132451Sroberto * crypto_bob2 - construct Bob's response to Alice's challenge 2564132451Sroberto * 2565132451Sroberto * Returns 2566132451Sroberto * XEVNT_OK success 2567280849Scy * XEVNT_ERR protocol error 2568182007Sroberto * XEVNT_ID bad or missing group key 2569132451Sroberto */ 2570132451Srobertostatic int 2571132451Srobertocrypto_bob2( 2572132451Sroberto struct exten *ep, /* extension pointer */ 2573132451Sroberto struct value *vp /* value pointer */ 2574132451Sroberto ) 2575132451Sroberto{ 2576132451Sroberto RSA *rsa; /* GQ parameters */ 2577132451Sroberto DSA_SIG *sdsa; /* DSA parameters */ 2578132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2579309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2580132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 2581132451Sroberto BIGNUM *r, *k, *g, *y; 2582132451Sroberto u_char *ptr; 2583132451Sroberto u_int len; 2584280849Scy int s_len; 2585309007Sdelphij const BIGNUM *n, *p, *e; 2586132451Sroberto 2587132451Sroberto /* 2588132451Sroberto * If the GQ parameters are not valid, something awful 2589132451Sroberto * happened or we are being tormented. 2590132451Sroberto */ 2591280849Scy if (gqkey_info == NULL) { 2592280849Scy msyslog(LOG_NOTICE, "crypto_bob2: scheme unavailable"); 2593182007Sroberto return (XEVNT_ID); 259482498Sroberto } 2595309007Sdelphij rsa = EVP_PKEY_get0_RSA(gqkey_info->pkey); 2596309007Sdelphij RSA_get0_key(rsa, &n, &p, &e); 259782498Sroberto 259882498Sroberto /* 2599132451Sroberto * Extract r from the challenge. 260082498Sroberto */ 2601289764Sglebius len = exten_payload_size(ep); 2602289764Sglebius if (len == 0 || len > MAX_VALLEN) 2603289764Sglebius return (XEVNT_LEN); 2604132451Sroberto if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) { 2605280849Scy msyslog(LOG_ERR, "crypto_bob2: %s", 2606132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2607182007Sroberto return (XEVNT_ERR); 2608132451Sroberto } 2609132451Sroberto 2610132451Sroberto /* 2611132451Sroberto * Bob rolls random k (0 < k < n), computes y = k u^r mod n and 2612132451Sroberto * x = k^b mod n, then sends (y, hash(x)) to Alice. 2613132451Sroberto */ 2614132451Sroberto bctx = BN_CTX_new(); k = BN_new(); g = BN_new(); y = BN_new(); 2615132451Sroberto sdsa = DSA_SIG_new(); 2616132451Sroberto BN_rand(k, len * 8, -1, 1); /* k */ 2617309007Sdelphij BN_mod(k, k, n, bctx); 2618309007Sdelphij BN_mod_exp(y, p, r, n, bctx); /* u^r mod n */ 2619309007Sdelphij BN_mod_mul(y, k, y, n, bctx); /* k u^r mod n */ 2620309007Sdelphij BN_mod_exp(g, k, e, n, bctx); /* k^b mod n */ 2621132451Sroberto bighash(g, g); 2622309007Sdelphij DSA_SIG_set0(sdsa, y, g); 2623132451Sroberto BN_CTX_free(bctx); 2624309007Sdelphij BN_free(r); BN_free(k); 2625280849Scy#ifdef DEBUG 2626280849Scy if (debug > 1) 2627280849Scy RSA_print_fp(stdout, rsa, 0); 2628280849Scy#endif 2629132451Sroberto 2630132451Sroberto /* 2631280849Scy * Encode the values in ASN.1 and sign. The filestamp is from 2632280849Scy * the local file. 2633132451Sroberto */ 2634280849Scy len = s_len = i2d_DSA_SIG(sdsa, NULL); 2635280849Scy if (s_len <= 0) { 2636280849Scy msyslog(LOG_ERR, "crypto_bob2: %s", 2637132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2638132451Sroberto DSA_SIG_free(sdsa); 2639182007Sroberto return (XEVNT_ERR); 2640132451Sroberto } 2641280849Scy memset(vp, 0, sizeof(struct value)); 2642280849Scy tstamp = crypto_time(); 2643280849Scy vp->tstamp = htonl(tstamp); 2644280849Scy vp->fstamp = htonl(gqkey_info->fstamp); 2645132451Sroberto vp->vallen = htonl(len); 2646132451Sroberto ptr = emalloc(len); 2647132451Sroberto vp->ptr = ptr; 2648132451Sroberto i2d_DSA_SIG(sdsa, &ptr); 2649132451Sroberto DSA_SIG_free(sdsa); 2650132451Sroberto if (tstamp == 0) 2651132451Sroberto return (XEVNT_OK); 2652182007Sroberto 2653132451Sroberto vp->sig = emalloc(sign_siglen); 2654309007Sdelphij ctx = EVP_MD_CTX_new(); 2655309007Sdelphij EVP_SignInit(ctx, sign_digest); 2656309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 2657309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 2658309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 2659289764Sglebius INSIST(len <= sign_siglen); 2660285169Scy vp->siglen = htonl(len); 2661285169Scy } 2662309007Sdelphij EVP_MD_CTX_free(ctx); 2663132451Sroberto return (XEVNT_OK); 2664132451Sroberto} 2665132451Sroberto 2666132451Sroberto 2667132451Sroberto/* 2668132451Sroberto * crypto_gq - verify Bob's response to Alice's challenge 2669132451Sroberto * 2670132451Sroberto * Returns 2671132451Sroberto * XEVNT_OK success 2672182007Sroberto * XEVNT_ERR protocol error 2673132451Sroberto * XEVNT_FSP bad filestamp 2674280849Scy * XEVNT_ID bad or missing group keys 2675280849Scy * XEVNT_PUB bad or missing public key 2676132451Sroberto */ 2677132451Srobertoint 2678132451Srobertocrypto_gq( 2679132451Sroberto struct exten *ep, /* extension pointer */ 2680132451Sroberto struct peer *peer /* peer structure pointer */ 2681132451Sroberto ) 2682132451Sroberto{ 2683132451Sroberto RSA *rsa; /* GQ parameters */ 2684132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2685132451Sroberto DSA_SIG *sdsa; /* RSA signature context fake */ 2686132451Sroberto BIGNUM *y, *v; 2687280849Scy const u_char *ptr; 2688280849Scy long len; 2689280849Scy u_int temp; 2690309007Sdelphij const BIGNUM *n, *e; 2691309007Sdelphij const BIGNUM *r, *s; 2692132451Sroberto 2693132451Sroberto /* 2694132451Sroberto * If the GQ parameters are not valid or no challenge was sent, 2695280849Scy * something awful happened or we are being tormented. Note that 2696280849Scy * the filestamp on the local key file can be greater than on 2697280849Scy * the remote parameter file if the keys have been refreshed. 2698132451Sroberto */ 2699132451Sroberto if (peer->ident_pkey == NULL) { 2700280849Scy msyslog(LOG_NOTICE, "crypto_gq: scheme unavailable"); 2701182007Sroberto return (XEVNT_ID); 2702132451Sroberto } 2703280849Scy if (ntohl(ep->fstamp) < peer->ident_pkey->fstamp) { 2704280849Scy msyslog(LOG_NOTICE, "crypto_gq: invalid filestamp %u", 2705132451Sroberto ntohl(ep->fstamp)); 2706132451Sroberto return (XEVNT_FSP); 2707132451Sroberto } 2708309007Sdelphij if ((rsa = EVP_PKEY_get0_RSA(peer->ident_pkey->pkey)) == NULL) { 2709280849Scy msyslog(LOG_NOTICE, "crypto_gq: defective key"); 2710132451Sroberto return (XEVNT_PUB); 2711132451Sroberto } 2712309007Sdelphij RSA_get0_key(rsa, &n, NULL, &e); 2713132451Sroberto if (peer->iffval == NULL) { 2714280849Scy msyslog(LOG_NOTICE, "crypto_gq: missing challenge"); 2715182007Sroberto return (XEVNT_ID); 2716132451Sroberto } 2717132451Sroberto 2718132451Sroberto /* 2719132451Sroberto * Extract the y = k u^r and hash(x = k^b) values from the 2720132451Sroberto * response. 2721132451Sroberto */ 2722132451Sroberto bctx = BN_CTX_new(); y = BN_new(); v = BN_new(); 2723132451Sroberto len = ntohl(ep->vallen); 2724280849Scy ptr = (u_char *)ep->pkt; 2725132451Sroberto if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) { 2726280849Scy BN_CTX_free(bctx); BN_free(y); BN_free(v); 2727280849Scy msyslog(LOG_ERR, "crypto_gq: %s", 2728132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2729182007Sroberto return (XEVNT_ERR); 2730132451Sroberto } 2731309007Sdelphij DSA_SIG_get0(sdsa, &r, &s); 2732132451Sroberto 2733132451Sroberto /* 2734132451Sroberto * Compute v^r y^b mod n. 2735132451Sroberto */ 2736280849Scy if (peer->grpkey == NULL) { 2737280849Scy msyslog(LOG_NOTICE, "crypto_gq: missing group key"); 2738280849Scy return (XEVNT_ID); 2739280849Scy } 2740309007Sdelphij BN_mod_exp(v, peer->grpkey, peer->iffval, n, bctx); 2741132451Sroberto /* v^r mod n */ 2742309007Sdelphij BN_mod_exp(y, r, e, n, bctx); /* y^b mod n */ 2743309007Sdelphij BN_mod_mul(y, v, y, n, bctx); /* v^r y^b mod n */ 2744132451Sroberto 2745132451Sroberto /* 2746132451Sroberto * Verify the hash of the result matches hash(x). 2747132451Sroberto */ 2748132451Sroberto bighash(y, y); 2749309007Sdelphij temp = BN_cmp(y, s); 2750132451Sroberto BN_CTX_free(bctx); BN_free(y); BN_free(v); 2751132451Sroberto BN_free(peer->iffval); 2752132451Sroberto peer->iffval = NULL; 2753132451Sroberto DSA_SIG_free(sdsa); 2754132451Sroberto if (temp == 0) 2755132451Sroberto return (XEVNT_OK); 2756182007Sroberto 2757280849Scy msyslog(LOG_NOTICE, "crypto_gq: identity not verified"); 2758280849Scy return (XEVNT_ID); 2759132451Sroberto} 2760132451Sroberto 2761132451Sroberto 2762132451Sroberto/* 2763132451Sroberto *********************************************************************** 2764132451Sroberto * * 2765132451Sroberto * The following routines implement the Mu-Varadharajan (MV) identity * 2766132451Sroberto * scheme * 2767132451Sroberto * * 2768132451Sroberto *********************************************************************** 2769280849Scy * 2770132451Sroberto * The Mu-Varadharajan (MV) cryptosystem was originally intended when 2771132451Sroberto * servers broadcast messages to clients, but clients never send 2772132451Sroberto * messages to servers. There is one encryption key for the server and a 2773132451Sroberto * separate decryption key for each client. It operated something like a 2774132451Sroberto * pay-per-view satellite broadcasting system where the session key is 2775132451Sroberto * encrypted by the broadcaster and the decryption keys are held in a 2776132451Sroberto * tamperproof set-top box. 2777132451Sroberto * 2778132451Sroberto * The MV parameters and private encryption key hide in a DSA cuckoo 2779132451Sroberto * structure which uses the same parameters, but generated in a 2780132451Sroberto * different way. The values are used in an encryption scheme similar to 2781132451Sroberto * El Gamal cryptography and a polynomial formed from the expansion of 2782132451Sroberto * product terms (x - x[j]), as described in Mu, Y., and V. 2783132451Sroberto * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001, 2784132451Sroberto * 223-231. The paper has significant errors and serious omissions. 2785132451Sroberto * 2786280849Scy * Let q be the product of n distinct primes s1[j] (j = 1...n), where 2787280849Scy * each s1[j] has m significant bits. Let p be a prime p = 2 * q + 1, so 2788280849Scy * that q and each s1[j] divide p - 1 and p has M = n * m + 1 2789280849Scy * significant bits. Let g be a generator of Zp; that is, gcd(g, p - 1) 2790280849Scy * = 1 and g^q = 1 mod p. We do modular arithmetic over Zq and then 2791280849Scy * project into Zp* as exponents of g. Sometimes we have to compute an 2792280849Scy * inverse b^-1 of random b in Zq, but for that purpose we require 2793280849Scy * gcd(b, q) = 1. We expect M to be in the 500-bit range and n 2794280849Scy * relatively small, like 30. These are the parameters of the scheme and 2795280849Scy * they are expensive to compute. 2796132451Sroberto * 2797132451Sroberto * We set up an instance of the scheme as follows. A set of random 2798132451Sroberto * values x[j] mod q (j = 1...n), are generated as the zeros of a 2799132451Sroberto * polynomial of order n. The product terms (x - x[j]) are expanded to 2800132451Sroberto * form coefficients a[i] mod q (i = 0...n) in powers of x. These are 2801132451Sroberto * used as exponents of the generator g mod p to generate the private 2802132451Sroberto * encryption key A. The pair (gbar, ghat) of public server keys and the 2803132451Sroberto * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used 2804132451Sroberto * to construct the decryption keys. The devil is in the details. 2805132451Sroberto * 2806280849Scy * This routine generates a private server encryption file including the 2807280849Scy * private encryption key E and partial decryption keys gbar and ghat. 2808280849Scy * It then generates public client decryption files including the public 2809280849Scy * keys xbar[j] and xhat[j] for each client j. The partial decryption 2810280849Scy * files are used to compute the inverse of E. These values are suitably 2811280849Scy * blinded so secrets are not revealed. 2812280849Scy * 2813132451Sroberto * The distinguishing characteristic of this scheme is the capability to 2814132451Sroberto * revoke keys. Included in the calculation of E, gbar and ghat is the 2815280849Scy * product s = prod(s1[j]) (j = 1...n) above. If the factor s1[j] is 2816132451Sroberto * subsequently removed from the product and E, gbar and ghat 2817132451Sroberto * recomputed, the jth client will no longer be able to compute E^-1 and 2818280849Scy * thus unable to decrypt the messageblock. 2819132451Sroberto * 2820132451Sroberto * How it works 2821132451Sroberto * 2822280849Scy * The scheme goes like this. Bob has the server values (p, E, q, gbar, 2823280849Scy * ghat) and Alice has the client values (p, xbar, xhat). 2824132451Sroberto * 2825280849Scy * Alice rolls new random nonce r mod p and sends to Bob in the MV 2826280849Scy * request message. Bob rolls random nonce k mod q, encrypts y = r E^k 2827280849Scy * mod p and sends (y, gbar^k, ghat^k) to Alice. 2828132451Sroberto * 2829280849Scy * Alice receives the response and computes the inverse (E^k)^-1 from 2830280849Scy * the partial decryption keys gbar^k, ghat^k, xbar and xhat. She then 2831280849Scy * decrypts y and verifies it matches the original r. The signed 2832280849Scy * response binds this knowledge to Bob's private key and the public key 2833280849Scy * previously received in his certificate. 2834132451Sroberto * 2835132451Sroberto * crypto_alice3 - construct Alice's challenge in MV scheme 2836132451Sroberto * 2837132451Sroberto * Returns 2838132451Sroberto * XEVNT_OK success 2839280849Scy * XEVNT_ID bad or missing group key 2840132451Sroberto * XEVNT_PUB bad or missing public key 2841132451Sroberto */ 2842132451Srobertostatic int 2843132451Srobertocrypto_alice3( 2844132451Sroberto struct peer *peer, /* peer pointer */ 2845132451Sroberto struct value *vp /* value pointer */ 2846132451Sroberto ) 2847132451Sroberto{ 2848132451Sroberto DSA *dsa; /* MV parameters */ 2849132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2850309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2851132451Sroberto tstamp_t tstamp; 2852132451Sroberto u_int len; 2853309007Sdelphij const BIGNUM *p; 2854132451Sroberto 2855132451Sroberto /* 2856132451Sroberto * The identity parameters must have correct format and content. 2857132451Sroberto */ 2858132451Sroberto if (peer->ident_pkey == NULL) 2859132451Sroberto return (XEVNT_ID); 2860182007Sroberto 2861309007Sdelphij if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) { 2862280849Scy msyslog(LOG_NOTICE, "crypto_alice3: defective key"); 2863132451Sroberto return (XEVNT_PUB); 286482498Sroberto } 2865309007Sdelphij DSA_get0_pqg(dsa, &p, NULL, NULL); 286682498Sroberto 286782498Sroberto /* 2868280849Scy * Roll new random r (0 < r < q). 286982498Sroberto */ 2870132451Sroberto if (peer->iffval != NULL) 2871132451Sroberto BN_free(peer->iffval); 2872132451Sroberto peer->iffval = BN_new(); 2873309007Sdelphij len = BN_num_bytes(p); 2874280849Scy BN_rand(peer->iffval, len * 8, -1, 1); /* r mod p */ 2875280849Scy bctx = BN_CTX_new(); 2876309007Sdelphij BN_mod(peer->iffval, peer->iffval, p, bctx); 2877132451Sroberto BN_CTX_free(bctx); 2878132451Sroberto 2879132451Sroberto /* 2880132451Sroberto * Sign and send to Bob. The filestamp is from the local file. 2881132451Sroberto */ 2882280849Scy memset(vp, 0, sizeof(struct value)); 2883132451Sroberto tstamp = crypto_time(); 2884132451Sroberto vp->tstamp = htonl(tstamp); 2885280849Scy vp->fstamp = htonl(peer->ident_pkey->fstamp); 2886132451Sroberto vp->vallen = htonl(len); 2887132451Sroberto vp->ptr = emalloc(len); 2888132451Sroberto BN_bn2bin(peer->iffval, vp->ptr); 2889132451Sroberto if (tstamp == 0) 2890132451Sroberto return (XEVNT_OK); 2891182007Sroberto 2892132451Sroberto vp->sig = emalloc(sign_siglen); 2893309007Sdelphij ctx = EVP_MD_CTX_new(); 2894309007Sdelphij EVP_SignInit(ctx, sign_digest); 2895309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 2896309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 2897309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 2898289764Sglebius INSIST(len <= sign_siglen); 2899285169Scy vp->siglen = htonl(len); 2900285169Scy } 2901309007Sdelphij EVP_MD_CTX_free(ctx); 2902132451Sroberto return (XEVNT_OK); 2903132451Sroberto} 2904132451Sroberto 2905132451Sroberto 2906132451Sroberto/* 2907132451Sroberto * crypto_bob3 - construct Bob's response to Alice's challenge 2908132451Sroberto * 2909132451Sroberto * Returns 2910132451Sroberto * XEVNT_OK success 2911182007Sroberto * XEVNT_ERR protocol error 2912132451Sroberto */ 2913132451Srobertostatic int 2914132451Srobertocrypto_bob3( 2915132451Sroberto struct exten *ep, /* extension pointer */ 2916132451Sroberto struct value *vp /* value pointer */ 2917132451Sroberto ) 2918132451Sroberto{ 2919132451Sroberto DSA *dsa; /* MV parameters */ 2920132451Sroberto DSA *sdsa; /* DSA signature context fake */ 2921132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 2922309007Sdelphij EVP_MD_CTX *ctx; /* signature context */ 2923132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 2924132451Sroberto BIGNUM *r, *k, *u; 2925132451Sroberto u_char *ptr; 2926132451Sroberto u_int len; 2927309007Sdelphij const BIGNUM *p, *q, *g; 2928309007Sdelphij const BIGNUM *pub_key, *priv_key; 2929309007Sdelphij BIGNUM *sp, *sq, *sg; 2930132451Sroberto 2931132451Sroberto /* 2932132451Sroberto * If the MV parameters are not valid, something awful 2933132451Sroberto * happened or we are being tormented. 2934132451Sroberto */ 2935280849Scy if (mvkey_info == NULL) { 2936280849Scy msyslog(LOG_NOTICE, "crypto_bob3: scheme unavailable"); 2937182007Sroberto return (XEVNT_ID); 293882498Sroberto } 2939309007Sdelphij dsa = EVP_PKEY_get0_DSA(mvkey_info->pkey); 2940309007Sdelphij DSA_get0_pqg(dsa, &p, &q, &g); 2941309007Sdelphij DSA_get0_key(dsa, &pub_key, &priv_key); 2942132451Sroberto 2943132451Sroberto /* 2944132451Sroberto * Extract r from the challenge. 2945132451Sroberto */ 2946289764Sglebius len = exten_payload_size(ep); 2947289764Sglebius if (len == 0 || len > MAX_VALLEN) 2948289764Sglebius return (XEVNT_LEN); 2949132451Sroberto if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) { 2950280849Scy msyslog(LOG_ERR, "crypto_bob3: %s", 2951132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2952182007Sroberto return (XEVNT_ERR); 2953132451Sroberto } 2954132451Sroberto 2955132451Sroberto /* 2956132451Sroberto * Bob rolls random k (0 < k < q), making sure it is not a 2957280849Scy * factor of q. He then computes y = r A^k and sends (y, gbar^k, 2958280849Scy * and ghat^k) to Alice. 2959132451Sroberto */ 2960132451Sroberto bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); 2961132451Sroberto sdsa = DSA_new(); 2962309007Sdelphij sp = BN_new(); sq = BN_new(); sg = BN_new(); 2963132451Sroberto while (1) { 2964309007Sdelphij BN_rand(k, BN_num_bits(q), 0, 0); 2965309007Sdelphij BN_mod(k, k, q, bctx); 2966309007Sdelphij BN_gcd(u, k, q, bctx); 2967132451Sroberto if (BN_is_one(u)) 2968132451Sroberto break; 2969132451Sroberto } 2970309007Sdelphij BN_mod_exp(u, g, k, p, bctx); /* A^k r */ 2971309007Sdelphij BN_mod_mul(sp, u, r, p, bctx); 2972309007Sdelphij BN_mod_exp(sq, priv_key, k, p, bctx); /* gbar */ 2973309007Sdelphij BN_mod_exp(sg, pub_key, k, p, bctx); /* ghat */ 2974309007Sdelphij DSA_set0_key(sdsa, BN_dup(pub_key), NULL); 2975309007Sdelphij DSA_set0_pqg(sdsa, sp, sq, sg); 2976132451Sroberto BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u); 2977280849Scy#ifdef DEBUG 2978280849Scy if (debug > 1) 2979280849Scy DSA_print_fp(stdout, sdsa, 0); 2980280849Scy#endif 2981132451Sroberto 2982132451Sroberto /* 2983280849Scy * Encode the values in ASN.1 and sign. The filestamp is from 2984280849Scy * the local file. 2985132451Sroberto */ 2986280849Scy memset(vp, 0, sizeof(struct value)); 2987132451Sroberto tstamp = crypto_time(); 2988132451Sroberto vp->tstamp = htonl(tstamp); 2989280849Scy vp->fstamp = htonl(mvkey_info->fstamp); 2990132451Sroberto len = i2d_DSAparams(sdsa, NULL); 2991280849Scy if (len == 0) { 2992280849Scy msyslog(LOG_ERR, "crypto_bob3: %s", 2993132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 2994132451Sroberto DSA_free(sdsa); 2995182007Sroberto return (XEVNT_ERR); 2996132451Sroberto } 2997132451Sroberto vp->vallen = htonl(len); 2998132451Sroberto ptr = emalloc(len); 2999132451Sroberto vp->ptr = ptr; 3000132451Sroberto i2d_DSAparams(sdsa, &ptr); 3001132451Sroberto DSA_free(sdsa); 3002132451Sroberto if (tstamp == 0) 3003132451Sroberto return (XEVNT_OK); 3004182007Sroberto 3005132451Sroberto vp->sig = emalloc(sign_siglen); 3006309007Sdelphij ctx = EVP_MD_CTX_new(); 3007309007Sdelphij EVP_SignInit(ctx, sign_digest); 3008309007Sdelphij EVP_SignUpdate(ctx, (u_char *)&vp->tstamp, 12); 3009309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 3010309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 3011289764Sglebius INSIST(len <= sign_siglen); 3012285169Scy vp->siglen = htonl(len); 3013285169Scy } 3014309007Sdelphij EVP_MD_CTX_free(ctx); 3015132451Sroberto return (XEVNT_OK); 3016132451Sroberto} 3017132451Sroberto 3018132451Sroberto 3019132451Sroberto/* 3020132451Sroberto * crypto_mv - verify Bob's response to Alice's challenge 3021132451Sroberto * 3022132451Sroberto * Returns 3023132451Sroberto * XEVNT_OK success 3024182007Sroberto * XEVNT_ERR protocol error 3025132451Sroberto * XEVNT_FSP bad filestamp 3026280849Scy * XEVNT_ID bad or missing group key 3027280849Scy * XEVNT_PUB bad or missing public key 3028132451Sroberto */ 3029132451Srobertoint 3030132451Srobertocrypto_mv( 3031132451Sroberto struct exten *ep, /* extension pointer */ 3032132451Sroberto struct peer *peer /* peer structure pointer */ 3033132451Sroberto ) 3034132451Sroberto{ 3035132451Sroberto DSA *dsa; /* MV parameters */ 3036132451Sroberto DSA *sdsa; /* DSA parameters */ 3037132451Sroberto BN_CTX *bctx; /* BIGNUM context */ 3038132451Sroberto BIGNUM *k, *u, *v; 3039132451Sroberto u_int len; 3040280849Scy const u_char *ptr; 3041132451Sroberto int temp; 3042309007Sdelphij const BIGNUM *p; 3043309007Sdelphij const BIGNUM *pub_key, *priv_key; 3044309007Sdelphij const BIGNUM *sp, *sq, *sg; 3045132451Sroberto 3046132451Sroberto /* 3047132451Sroberto * If the MV parameters are not valid or no challenge was sent, 3048132451Sroberto * something awful happened or we are being tormented. 3049132451Sroberto */ 3050132451Sroberto if (peer->ident_pkey == NULL) { 3051280849Scy msyslog(LOG_NOTICE, "crypto_mv: scheme unavailable"); 3052182007Sroberto return (XEVNT_ID); 3053132451Sroberto } 3054280849Scy if (ntohl(ep->fstamp) != peer->ident_pkey->fstamp) { 3055280849Scy msyslog(LOG_NOTICE, "crypto_mv: invalid filestamp %u", 3056132451Sroberto ntohl(ep->fstamp)); 3057132451Sroberto return (XEVNT_FSP); 3058132451Sroberto } 3059309007Sdelphij if ((dsa = EVP_PKEY_get0_DSA(peer->ident_pkey->pkey)) == NULL) { 3060280849Scy msyslog(LOG_NOTICE, "crypto_mv: defective key"); 3061132451Sroberto return (XEVNT_PUB); 3062132451Sroberto } 3063309007Sdelphij DSA_get0_pqg(dsa, &p, NULL, NULL); 3064309007Sdelphij DSA_get0_key(dsa, &pub_key, &priv_key); 3065132451Sroberto if (peer->iffval == NULL) { 3066280849Scy msyslog(LOG_NOTICE, "crypto_mv: missing challenge"); 3067182007Sroberto return (XEVNT_ID); 3068132451Sroberto } 3069132451Sroberto 3070132451Sroberto /* 3071280849Scy * Extract the y, gbar and ghat values from the response. 3072132451Sroberto */ 3073132451Sroberto bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); v = BN_new(); 3074132451Sroberto len = ntohl(ep->vallen); 3075280849Scy ptr = (u_char *)ep->pkt; 3076132451Sroberto if ((sdsa = d2i_DSAparams(NULL, &ptr, len)) == NULL) { 3077280849Scy msyslog(LOG_ERR, "crypto_mv: %s", 3078132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3079182007Sroberto return (XEVNT_ERR); 3080132451Sroberto } 3081309007Sdelphij DSA_get0_pqg(sdsa, &sp, &sq, &sg); 3082132451Sroberto 3083132451Sroberto /* 3084280849Scy * Compute (gbar^xhat ghat^xbar) mod p. 3085132451Sroberto */ 3086309007Sdelphij BN_mod_exp(u, sq, pub_key, p, bctx); 3087309007Sdelphij BN_mod_exp(v, sg, priv_key, p, bctx); 3088309007Sdelphij BN_mod_mul(u, u, v, p, bctx); 3089309007Sdelphij BN_mod_mul(u, u, sp, p, bctx); 3090132451Sroberto 3091132451Sroberto /* 3092280849Scy * The result should match r. 3093132451Sroberto */ 3094280849Scy temp = BN_cmp(u, peer->iffval); 3095132451Sroberto BN_CTX_free(bctx); BN_free(k); BN_free(u); BN_free(v); 3096132451Sroberto BN_free(peer->iffval); 3097132451Sroberto peer->iffval = NULL; 3098132451Sroberto DSA_free(sdsa); 3099132451Sroberto if (temp == 0) 3100132451Sroberto return (XEVNT_OK); 3101182007Sroberto 3102280849Scy msyslog(LOG_NOTICE, "crypto_mv: identity not verified"); 3103280849Scy return (XEVNT_ID); 3104132451Sroberto} 3105132451Sroberto 3106132451Sroberto 3107132451Sroberto/* 3108132451Sroberto *********************************************************************** 3109132451Sroberto * * 3110132451Sroberto * The following routines are used to manipulate certificates * 3111132451Sroberto * * 3112132451Sroberto *********************************************************************** 3113132451Sroberto */ 3114132451Sroberto/* 3115182007Sroberto * cert_sign - sign x509 certificate equest and update value structure. 3116132451Sroberto * 3117182007Sroberto * The certificate request includes a copy of the host certificate, 3118182007Sroberto * which includes the version number, subject name and public key of the 3119182007Sroberto * host. The resulting certificate includes these values plus the 3120182007Sroberto * serial number, issuer name and valid interval of the server. The 3121182007Sroberto * valid interval extends from the current time to the same time one 3122182007Sroberto * year hence. This may extend the life of the signed certificate beyond 3123182007Sroberto * that of the signer certificate. 3124132451Sroberto * 3125182007Sroberto * It is convenient to use the NTP seconds of the current time as the 3126182007Sroberto * serial number. In the value structure the timestamp is the current 3127182007Sroberto * time and the filestamp is taken from the extension field. Note this 3128182007Sroberto * routine is called only when the client clock is synchronized to a 3129182007Sroberto * proventic source, so timestamp comparisons are valid. 3130182007Sroberto * 3131182007Sroberto * The host certificate is valid from the time it was generated for a 3132182007Sroberto * period of one year. A signed certificate is valid from the time of 3133182007Sroberto * signature for a period of one year, but only the host certificate (or 3134182007Sroberto * sign certificate if used) is actually used to encrypt and decrypt 3135182007Sroberto * signatures. The signature trail is built from the client via the 3136182007Sroberto * intermediate servers to the trusted server. Each signature on the 3137182007Sroberto * trail must be valid at the time of signature, but it could happen 3138182007Sroberto * that a signer certificate expire before the signed certificate, which 3139182007Sroberto * remains valid until its expiration. 3140182007Sroberto * 3141132451Sroberto * Returns 3142132451Sroberto * XEVNT_OK success 3143280849Scy * XEVNT_CRT bad or missing certificate 3144280849Scy * XEVNT_PER host certificate expired 3145132451Sroberto * XEVNT_PUB bad or missing public key 3146132451Sroberto * XEVNT_VFY certificate not verified 314782498Sroberto */ 3148132451Srobertostatic int 3149132451Srobertocert_sign( 3150132451Sroberto struct exten *ep, /* extension field pointer */ 3151132451Sroberto struct value *vp /* value pointer */ 315282498Sroberto ) 315382498Sroberto{ 3154132451Sroberto X509 *req; /* X509 certificate request */ 3155132451Sroberto X509 *cert; /* X509 certificate */ 3156132451Sroberto X509_EXTENSION *ext; /* certificate extension */ 3157132451Sroberto ASN1_INTEGER *serial; /* serial number */ 3158132451Sroberto X509_NAME *subj; /* distinguished (common) name */ 3159132451Sroberto EVP_PKEY *pkey; /* public key */ 3160309007Sdelphij EVP_MD_CTX *ctx; /* message digest context */ 3161132451Sroberto tstamp_t tstamp; /* NTP timestamp */ 3162280849Scy struct calendar tscal; 3163132451Sroberto u_int len; 3164280849Scy const u_char *cptr; 3165280849Scy u_char *ptr; 3166132451Sroberto int i, temp; 316782498Sroberto 316882498Sroberto /* 3169132451Sroberto * Decode ASN.1 objects and construct certificate structure. 3170182007Sroberto * Make sure the system clock is synchronized to a proventic 3171182007Sroberto * source. 317282498Sroberto */ 3173132451Sroberto tstamp = crypto_time(); 3174132451Sroberto if (tstamp == 0) 3175132451Sroberto return (XEVNT_TSP); 3176132451Sroberto 3177289764Sglebius len = exten_payload_size(ep); 3178289764Sglebius if (len == 0 || len > MAX_VALLEN) 3179289764Sglebius return (XEVNT_LEN); 3180280849Scy cptr = (void *)ep->pkt; 3181289764Sglebius if ((req = d2i_X509(NULL, &cptr, len)) == NULL) { 3182280849Scy msyslog(LOG_ERR, "cert_sign: %s", 3183132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3184132451Sroberto return (XEVNT_CRT); 318582498Sroberto } 3186132451Sroberto /* 3187132451Sroberto * Extract public key and check for errors. 3188132451Sroberto */ 3189132451Sroberto if ((pkey = X509_get_pubkey(req)) == NULL) { 3190280849Scy msyslog(LOG_ERR, "cert_sign: %s", 3191132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3192132451Sroberto X509_free(req); 3193132451Sroberto return (XEVNT_PUB); 3194132451Sroberto } 319582498Sroberto 319682498Sroberto /* 3197280849Scy * Generate X509 certificate signed by this server. If this is a 3198280849Scy * trusted host, the issuer name is the group name; otherwise, 3199280849Scy * it is the host name. Also copy any extensions that might be 3200280849Scy * present. 320182498Sroberto */ 3202132451Sroberto cert = X509_new(); 3203132451Sroberto X509_set_version(cert, X509_get_version(req)); 3204132451Sroberto serial = ASN1_INTEGER_new(); 3205132451Sroberto ASN1_INTEGER_set(serial, tstamp); 3206132451Sroberto X509_set_serialNumber(cert, serial); 3207316068Sdelphij X509_gmtime_adj(X509_getm_notBefore(cert), 0L); 3208316068Sdelphij X509_gmtime_adj(X509_getm_notAfter(cert), YEAR); 3209132451Sroberto subj = X509_get_issuer_name(cert); 3210132451Sroberto X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC, 3211280849Scy hostval.ptr, strlen((const char *)hostval.ptr), -1, 0); 3212132451Sroberto subj = X509_get_subject_name(req); 3213132451Sroberto X509_set_subject_name(cert, subj); 3214132451Sroberto X509_set_pubkey(cert, pkey); 3215132451Sroberto temp = X509_get_ext_count(req); 3216132451Sroberto for (i = 0; i < temp; i++) { 3217132451Sroberto ext = X509_get_ext(req, i); 3218280849Scy INSIST(X509_add_ext(cert, ext, -1)); 321982498Sroberto } 3220132451Sroberto X509_free(req); 322182498Sroberto 322282498Sroberto /* 3223280849Scy * Sign and verify the client certificate, but only if the host 3224280849Scy * certificate has not expired. 322582498Sroberto */ 3226280849Scy (void)ntpcal_ntp_to_date(&tscal, tstamp, NULL); 3227280849Scy if ((calcomp(&tscal, &(cert_host->first)) < 0) 3228280849Scy || (calcomp(&tscal, &(cert_host->last)) > 0)) { 3229280849Scy X509_free(cert); 3230280849Scy return (XEVNT_PER); 3231280849Scy } 3232132451Sroberto X509_sign(cert, sign_pkey, sign_digest); 3233280849Scy if (X509_verify(cert, sign_pkey) <= 0) { 3234280849Scy msyslog(LOG_ERR, "cert_sign: %s", 3235132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3236132451Sroberto X509_free(cert); 3237132451Sroberto return (XEVNT_VFY); 3238132451Sroberto } 3239132451Sroberto len = i2d_X509(cert, NULL); 324082498Sroberto 324182498Sroberto /* 3242132451Sroberto * Build and sign the value structure. We have to sign it here, 3243132451Sroberto * since the response has to be returned right away. This is a 3244132451Sroberto * clogging hazard. 324582498Sroberto */ 3246132451Sroberto memset(vp, 0, sizeof(struct value)); 3247132451Sroberto vp->tstamp = htonl(tstamp); 3248132451Sroberto vp->fstamp = ep->fstamp; 3249132451Sroberto vp->vallen = htonl(len); 3250132451Sroberto vp->ptr = emalloc(len); 3251132451Sroberto ptr = vp->ptr; 3252280849Scy i2d_X509(cert, (unsigned char **)(intptr_t)&ptr); 3253132451Sroberto vp->siglen = 0; 3254280849Scy if (tstamp != 0) { 3255280849Scy vp->sig = emalloc(sign_siglen); 3256309007Sdelphij ctx = EVP_MD_CTX_new(); 3257309007Sdelphij EVP_SignInit(ctx, sign_digest); 3258309007Sdelphij EVP_SignUpdate(ctx, (u_char *)vp, 12); 3259309007Sdelphij EVP_SignUpdate(ctx, vp->ptr, len); 3260309007Sdelphij if (EVP_SignFinal(ctx, vp->sig, &len, sign_pkey)) { 3261289764Sglebius INSIST(len <= sign_siglen); 3262285169Scy vp->siglen = htonl(len); 3263285169Scy } 3264309007Sdelphij EVP_MD_CTX_free(ctx); 3265280849Scy } 326682498Sroberto#ifdef DEBUG 3267132451Sroberto if (debug > 1) 3268132451Sroberto X509_print_fp(stdout, cert); 326982498Sroberto#endif 3270132451Sroberto X509_free(cert); 3271132451Sroberto return (XEVNT_OK); 327282498Sroberto} 327382498Sroberto 327482498Sroberto 327582498Sroberto/* 3276280849Scy * cert_install - install certificate in certificate cache 3277132451Sroberto * 3278132451Sroberto * This routine encodes an extension field into a certificate info/value 3279132451Sroberto * structure. It searches the certificate list for duplicates and 3280280849Scy * expunges whichever is older. Finally, it inserts this certificate 3281280849Scy * first on the list. 3282132451Sroberto * 3283280849Scy * Returns certificate info pointer if valid, NULL if not. 3284132451Sroberto */ 3285280849Scystruct cert_info * 3286132451Srobertocert_install( 3287132451Sroberto struct exten *ep, /* cert info/value */ 3288132451Sroberto struct peer *peer /* peer structure */ 3289132451Sroberto ) 3290132451Sroberto{ 3291280849Scy struct cert_info *cp, *xp, **zp; 3292132451Sroberto 329382498Sroberto /* 3294132451Sroberto * Parse and validate the signed certificate. If valid, 3295280849Scy * construct the info/value structure; otherwise, scamper home 3296280849Scy * empty handed. 329782498Sroberto */ 3298280849Scy if ((cp = cert_parse((u_char *)ep->pkt, (long)ntohl(ep->vallen), 3299280849Scy (tstamp_t)ntohl(ep->fstamp))) == NULL) 3300280849Scy return (NULL); 3301132451Sroberto 3302132451Sroberto /* 3303132451Sroberto * Scan certificate list looking for another certificate with 3304132451Sroberto * the same subject and issuer. If another is found with the 3305132451Sroberto * same or older filestamp, unlink it and return the goodies to 3306182007Sroberto * the heap. If another is found with a later filestamp, discard 3307280849Scy * the new one and leave the building with the old one. 3308182007Sroberto * 3309182007Sroberto * Make a note to study this issue again. An earlier certificate 3310182007Sroberto * with a long lifetime might be overtaken by a later 3311182007Sroberto * certificate with a short lifetime, thus invalidating the 3312182007Sroberto * earlier signature. However, we gotta find a way to leak old 3313182007Sroberto * stuff from the cache, so we do it anyway. 3314132451Sroberto */ 3315132451Sroberto zp = &cinfo; 3316132451Sroberto for (xp = cinfo; xp != NULL; xp = xp->link) { 3317132451Sroberto if (strcmp(cp->subject, xp->subject) == 0 && 3318132451Sroberto strcmp(cp->issuer, xp->issuer) == 0) { 3319132451Sroberto if (ntohl(cp->cert.fstamp) <= 3320132451Sroberto ntohl(xp->cert.fstamp)) { 3321280849Scy cert_free(cp); 3322280849Scy cp = xp; 3323280849Scy } else { 3324280849Scy *zp = xp->link; 3325132451Sroberto cert_free(xp); 3326280849Scy xp = NULL; 3327132451Sroberto } 3328132451Sroberto break; 3329132451Sroberto } 3330132451Sroberto zp = &xp->link; 3331132451Sroberto } 3332280849Scy if (xp == NULL) { 3333280849Scy cp->link = cinfo; 3334280849Scy cinfo = cp; 3335280849Scy } 3336280849Scy cp->flags |= CERT_VALID; 3337280849Scy crypto_update(); 3338280849Scy return (cp); 3339280849Scy} 3340132451Sroberto 3341280849Scy 3342280849Scy/* 3343280849Scy * cert_hike - verify the signature using the issuer public key 3344280849Scy * 3345280849Scy * Returns 3346280849Scy * XEVNT_OK success 3347280849Scy * XEVNT_CRT bad or missing certificate 3348280849Scy * XEVNT_PER host certificate expired 3349280849Scy * XEVNT_VFY certificate not verified 3350280849Scy */ 3351280849Scyint 3352280849Scycert_hike( 3353280849Scy struct peer *peer, /* peer structure pointer */ 3354280849Scy struct cert_info *yp /* issuer certificate */ 3355280849Scy ) 3356280849Scy{ 3357280849Scy struct cert_info *xp; /* subject certificate */ 3358280849Scy X509 *cert; /* X509 certificate */ 3359280849Scy const u_char *ptr; 3360280849Scy 3361132451Sroberto /* 3362280849Scy * Save the issuer on the new certificate, but remember the old 3363280849Scy * one. 3364132451Sroberto */ 3365280849Scy if (peer->issuer != NULL) 3366280849Scy free(peer->issuer); 3367280849Scy peer->issuer = estrdup(yp->issuer); 3368280849Scy xp = peer->xinfo; 3369280849Scy peer->xinfo = yp; 3370132451Sroberto 3371280849Scy /* 3372280849Scy * If subject Y matches issuer Y, then the certificate trail is 3373280849Scy * complete. If Y is not trusted, the server certificate has yet 3374280849Scy * been signed, so keep trying. Otherwise, save the group key 3375280849Scy * and light the valid bit. If the host certificate is trusted, 3376280849Scy * do not execute a sign exchange. If no identity scheme is in 3377280849Scy * use, light the identity and proventic bits. 3378280849Scy */ 3379280849Scy if (strcmp(yp->subject, yp->issuer) == 0) { 3380280849Scy if (!(yp->flags & CERT_TRUST)) 3381280849Scy return (XEVNT_OK); 3382132451Sroberto 3383280849Scy /* 3384280849Scy * If the server has an an identity scheme, fetch the 3385280849Scy * identity credentials. If not, the identity is 3386280849Scy * verified only by the trusted certificate. The next 3387280849Scy * signature will set the server proventic. 3388280849Scy */ 3389280849Scy peer->crypto |= CRYPTO_FLAG_CERT; 3390280849Scy peer->grpkey = yp->grpkey; 3391280849Scy if (peer->ident == NULL || !(peer->crypto & 3392280849Scy CRYPTO_FLAG_MASK)) 3393280849Scy peer->crypto |= CRYPTO_FLAG_VRFY; 3394280849Scy } 3395132451Sroberto 3396280849Scy /* 3397280849Scy * If X exists, verify signature X using public key Y. 3398280849Scy */ 3399280849Scy if (xp == NULL) 3400280849Scy return (XEVNT_OK); 3401182007Sroberto 3402280849Scy ptr = (u_char *)xp->cert.ptr; 3403280849Scy cert = d2i_X509(NULL, &ptr, ntohl(xp->cert.vallen)); 3404280849Scy if (cert == NULL) { 3405280849Scy xp->flags |= CERT_ERROR; 3406280849Scy return (XEVNT_CRT); 3407280849Scy } 3408280849Scy if (X509_verify(cert, yp->pkey) <= 0) { 3409280849Scy X509_free(cert); 3410280849Scy xp->flags |= CERT_ERROR; 3411280849Scy return (XEVNT_VFY); 3412280849Scy } 3413280849Scy X509_free(cert); 3414182007Sroberto 3415280849Scy /* 3416280849Scy * Signature X is valid only if it begins during the 3417280849Scy * lifetime of Y. 3418280849Scy */ 3419280849Scy if ((calcomp(&(xp->first), &(yp->first)) < 0) 3420280849Scy || (calcomp(&(xp->first), &(yp->last)) > 0)) { 3421280849Scy xp->flags |= CERT_ERROR; 3422280849Scy return (XEVNT_PER); 3423280849Scy } 3424280849Scy xp->flags |= CERT_SIGN; 3425280849Scy return (XEVNT_OK); 3426280849Scy} 3427132451Sroberto 3428132451Sroberto 3429280849Scy/* 3430280849Scy * cert_parse - parse x509 certificate and create info/value structures. 3431280849Scy * 3432280849Scy * The server certificate includes the version number, issuer name, 3433280849Scy * subject name, public key and valid date interval. If the issuer name 3434280849Scy * is the same as the subject name, the certificate is self signed and 3435280849Scy * valid only if the server is configured as trustable. If the names are 3436280849Scy * different, another issuer has signed the server certificate and 3437280849Scy * vouched for it. In this case the server certificate is valid if 3438280849Scy * verified by the issuer public key. 3439280849Scy * 3440280849Scy * Returns certificate info/value pointer if valid, NULL if not. 3441280849Scy */ 3442280849Scystruct cert_info * /* certificate information structure */ 3443280849Scycert_parse( 3444280849Scy const u_char *asn1cert, /* X509 certificate */ 3445280849Scy long len, /* certificate length */ 3446280849Scy tstamp_t fstamp /* filestamp */ 3447280849Scy ) 3448280849Scy{ 3449280849Scy X509 *cert; /* X509 certificate */ 3450280849Scy struct cert_info *ret; /* certificate info/value */ 3451280849Scy BIO *bp; 3452280849Scy char pathbuf[MAXFILENAME]; 3453280849Scy const u_char *ptr; 3454280849Scy char *pch; 3455309007Sdelphij int cnt, i; 3456280849Scy struct calendar fscal; 3457132451Sroberto 3458280849Scy /* 3459280849Scy * Decode ASN.1 objects and construct certificate structure. 3460280849Scy */ 3461280849Scy ptr = asn1cert; 3462280849Scy if ((cert = d2i_X509(NULL, &ptr, len)) == NULL) { 3463280849Scy msyslog(LOG_ERR, "cert_parse: %s", 3464280849Scy ERR_error_string(ERR_get_error(), NULL)); 3465280849Scy return (NULL); 3466280849Scy } 3467280849Scy#ifdef DEBUG 3468280849Scy if (debug > 1) 3469280849Scy X509_print_fp(stdout, cert); 3470280849Scy#endif 3471132451Sroberto 3472280849Scy /* 3473280849Scy * Extract version, subject name and public key. 3474280849Scy */ 3475280849Scy ret = emalloc_zero(sizeof(*ret)); 3476280849Scy if ((ret->pkey = X509_get_pubkey(cert)) == NULL) { 3477280849Scy msyslog(LOG_ERR, "cert_parse: %s", 3478280849Scy ERR_error_string(ERR_get_error(), NULL)); 3479280849Scy cert_free(ret); 3480280849Scy X509_free(cert); 3481280849Scy return (NULL); 3482280849Scy } 3483280849Scy ret->version = X509_get_version(cert); 3484280849Scy X509_NAME_oneline(X509_get_subject_name(cert), pathbuf, 3485280849Scy sizeof(pathbuf)); 3486280849Scy pch = strstr(pathbuf, "CN="); 3487280849Scy if (NULL == pch) { 3488280849Scy msyslog(LOG_NOTICE, "cert_parse: invalid subject %s", 3489280849Scy pathbuf); 3490280849Scy cert_free(ret); 3491280849Scy X509_free(cert); 3492280849Scy return (NULL); 3493280849Scy } 3494280849Scy ret->subject = estrdup(pch + 3); 3495132451Sroberto 3496280849Scy /* 3497280849Scy * Extract remaining objects. Note that the NTP serial number is 3498280849Scy * the NTP seconds at the time of signing, but this might not be 3499280849Scy * the case for other authority. We don't bother to check the 3500280849Scy * objects at this time, since the real crunch can happen only 3501280849Scy * when the time is valid but not yet certificated. 3502280849Scy */ 3503309007Sdelphij ret->nid = X509_get_signature_nid(cert); 3504280849Scy ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid); 3505280849Scy ret->serial = 3506280849Scy (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert)); 3507280849Scy X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf, 3508280849Scy sizeof(pathbuf)); 3509280849Scy if ((pch = strstr(pathbuf, "CN=")) == NULL) { 3510280849Scy msyslog(LOG_NOTICE, "cert_parse: invalid issuer %s", 3511280849Scy pathbuf); 3512280849Scy cert_free(ret); 3513280849Scy X509_free(cert); 3514280849Scy return (NULL); 3515280849Scy } 3516280849Scy ret->issuer = estrdup(pch + 3); 3517316068Sdelphij asn_to_calendar(X509_get0_notBefore(cert), &(ret->first)); 3518316068Sdelphij asn_to_calendar(X509_get0_notAfter(cert), &(ret->last)); 3519280849Scy 3520280849Scy /* 3521280849Scy * Extract extension fields. These are ad hoc ripoffs of 3522280849Scy * currently assigned functions and will certainly be changed 3523280849Scy * before prime time. 3524280849Scy */ 3525280849Scy cnt = X509_get_ext_count(cert); 3526280849Scy for (i = 0; i < cnt; i++) { 3527309007Sdelphij X509_EXTENSION *ext; 3528309007Sdelphij ASN1_OBJECT *obj; 3529309007Sdelphij int nid; 3530309007Sdelphij ASN1_OCTET_STRING *data; 3531309007Sdelphij 3532280849Scy ext = X509_get_ext(cert, i); 3533309007Sdelphij obj = X509_EXTENSION_get_object(ext); 3534309007Sdelphij nid = OBJ_obj2nid(obj); 3535280849Scy 3536309007Sdelphij switch (nid) { 3537309007Sdelphij 3538280849Scy /* 3539280849Scy * If a key_usage field is present, we decode whether 3540280849Scy * this is a trusted or private certificate. This is 3541280849Scy * dorky; all we want is to compare NIDs, but OpenSSL 3542280849Scy * insists on BIO text strings. 3543280849Scy */ 3544280849Scy case NID_ext_key_usage: 3545280849Scy bp = BIO_new(BIO_s_mem()); 3546280849Scy X509V3_EXT_print(bp, ext, 0, 0); 3547280849Scy BIO_gets(bp, pathbuf, sizeof(pathbuf)); 3548280849Scy BIO_free(bp); 3549280849Scy if (strcmp(pathbuf, "Trust Root") == 0) 3550280849Scy ret->flags |= CERT_TRUST; 3551280849Scy else if (strcmp(pathbuf, "Private") == 0) 3552280849Scy ret->flags |= CERT_PRIV; 3553285169Scy DPRINTF(1, ("cert_parse: %s: %s\n", 3554309007Sdelphij OBJ_nid2ln(nid), pathbuf)); 3555280849Scy break; 3556280849Scy 3557280849Scy /* 3558280849Scy * If a NID_subject_key_identifier field is present, it 3559280849Scy * contains the GQ public key. 3560280849Scy */ 3561280849Scy case NID_subject_key_identifier: 3562309007Sdelphij data = X509_EXTENSION_get_data(ext); 3563309007Sdelphij ret->grpkey = BN_bin2bn(&data->data[2], 3564309007Sdelphij data->length - 2, NULL); 3565280849Scy /* fall through */ 3566280849Scy default: 3567285169Scy DPRINTF(1, ("cert_parse: %s\n", 3568309007Sdelphij OBJ_nid2ln(nid))); 3569285169Scy break; 3570132451Sroberto } 3571132451Sroberto } 3572280849Scy if (strcmp(ret->subject, ret->issuer) == 0) { 3573132451Sroberto 3574280849Scy /* 3575280849Scy * If certificate is self signed, verify signature. 3576280849Scy */ 3577280849Scy if (X509_verify(cert, ret->pkey) <= 0) { 3578280849Scy msyslog(LOG_NOTICE, 3579280849Scy "cert_parse: signature not verified %s", 3580280849Scy ret->subject); 3581280849Scy cert_free(ret); 3582280849Scy X509_free(cert); 3583280849Scy return (NULL); 3584280849Scy } 3585280849Scy } else { 3586280849Scy 3587280849Scy /* 3588280849Scy * Check for a certificate loop. 3589280849Scy */ 3590280849Scy if (strcmp((const char *)hostval.ptr, ret->issuer) == 0) { 3591280849Scy msyslog(LOG_NOTICE, 3592280849Scy "cert_parse: certificate trail loop %s", 3593280849Scy ret->subject); 3594280849Scy cert_free(ret); 3595280849Scy X509_free(cert); 3596280849Scy return (NULL); 3597280849Scy } 3598280849Scy } 3599280849Scy 3600132451Sroberto /* 3601280849Scy * Verify certificate valid times. Note that certificates cannot 3602280849Scy * be retroactive. 3603132451Sroberto */ 3604280849Scy (void)ntpcal_ntp_to_date(&fscal, fstamp, NULL); 3605280849Scy if ((calcomp(&(ret->first), &(ret->last)) > 0) 3606280849Scy || (calcomp(&(ret->first), &fscal) < 0)) { 3607280849Scy msyslog(LOG_NOTICE, 3608280849Scy "cert_parse: invalid times %s first %u-%02u-%02uT%02u:%02u:%02u last %u-%02u-%02uT%02u:%02u:%02u fstamp %u-%02u-%02uT%02u:%02u:%02u", 3609280849Scy ret->subject, 3610280849Scy ret->first.year, ret->first.month, ret->first.monthday, 3611280849Scy ret->first.hour, ret->first.minute, ret->first.second, 3612280849Scy ret->last.year, ret->last.month, ret->last.monthday, 3613280849Scy ret->last.hour, ret->last.minute, ret->last.second, 3614280849Scy fscal.year, fscal.month, fscal.monthday, 3615280849Scy fscal.hour, fscal.minute, fscal.second); 3616280849Scy cert_free(ret); 3617280849Scy X509_free(cert); 3618280849Scy return (NULL); 3619280849Scy } 3620280849Scy 3621280849Scy /* 3622280849Scy * Build the value structure to sign and send later. 3623280849Scy */ 3624280849Scy ret->cert.fstamp = htonl(fstamp); 3625280849Scy ret->cert.vallen = htonl(len); 3626280849Scy ret->cert.ptr = emalloc(len); 3627280849Scy memcpy(ret->cert.ptr, asn1cert, len); 3628280849Scy X509_free(cert); 3629280849Scy return (ret); 3630132451Sroberto} 3631132451Sroberto 3632132451Sroberto 3633132451Sroberto/* 3634132451Sroberto * cert_free - free certificate information structure 3635132451Sroberto */ 3636132451Srobertovoid 3637132451Srobertocert_free( 3638132451Sroberto struct cert_info *cinf /* certificate info/value structure */ 3639132451Sroberto ) 3640132451Sroberto{ 3641132451Sroberto if (cinf->pkey != NULL) 3642132451Sroberto EVP_PKEY_free(cinf->pkey); 3643132451Sroberto if (cinf->subject != NULL) 3644132451Sroberto free(cinf->subject); 3645132451Sroberto if (cinf->issuer != NULL) 3646132451Sroberto free(cinf->issuer); 3647132451Sroberto if (cinf->grpkey != NULL) 3648280849Scy BN_free(cinf->grpkey); 3649132451Sroberto value_free(&cinf->cert); 3650132451Sroberto free(cinf); 3651132451Sroberto} 3652132451Sroberto 3653132451Sroberto 3654132451Sroberto/* 3655280849Scy * crypto_key - load cryptographic parameters and keys 3656132451Sroberto * 3657280849Scy * This routine searches the key cache for matching name in the form 3658280849Scy * ntpkey_<key>_<name>, where <key> is one of host, sign, iff, gq, mv, 3659280849Scy * and <name> is the host/group name. If not found, it tries to load a 3660280849Scy * PEM-encoded file of the same name and extracts the filestamp from 3661280849Scy * the first line of the file name. It returns the key pointer if valid, 3662280849Scy * NULL if not. 3663132451Sroberto */ 3664280849Scystatic struct pkey_info * 3665132451Srobertocrypto_key( 3666132451Sroberto char *cp, /* file name */ 3667280849Scy char *passwd1, /* password */ 3668280849Scy sockaddr_u *addr /* IP address */ 3669132451Sroberto ) 3670132451Sroberto{ 3671132451Sroberto FILE *str; /* file handle */ 3672280849Scy struct pkey_info *pkp; /* generic key */ 3673132451Sroberto EVP_PKEY *pkey = NULL; /* public/private key */ 3674280849Scy tstamp_t fstamp; 3675132451Sroberto char filename[MAXFILENAME]; /* name of key file */ 3676132451Sroberto char linkname[MAXFILENAME]; /* filestamp buffer) */ 3677132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 3678132451Sroberto char *ptr; 3679132451Sroberto 3680132451Sroberto /* 3681280849Scy * Search the key cache for matching key and name. 3682280849Scy */ 3683280849Scy for (pkp = pkinfo; pkp != NULL; pkp = pkp->link) { 3684280849Scy if (strcmp(cp, pkp->name) == 0) 3685280849Scy return (pkp); 3686280849Scy } 3687280849Scy 3688280849Scy /* 3689132451Sroberto * Open the key file. If the first character of the file name is 3690132451Sroberto * not '/', prepend the keys directory string. If something goes 3691132451Sroberto * wrong, abandon ship. 3692132451Sroberto */ 369382498Sroberto if (*cp == '/') 3694280849Scy strlcpy(filename, cp, sizeof(filename)); 369582498Sroberto else 3696280849Scy snprintf(filename, sizeof(filename), "%s/%s", keysdir, 3697280849Scy cp); 369882498Sroberto str = fopen(filename, "r"); 3699132451Sroberto if (str == NULL) 3700132451Sroberto return (NULL); 3701132451Sroberto 3702132451Sroberto /* 3703132451Sroberto * Read the filestamp, which is contained in the first line. 3704132451Sroberto */ 3705280849Scy if ((ptr = fgets(linkname, sizeof(linkname), str)) == NULL) { 3706280849Scy msyslog(LOG_ERR, "crypto_key: empty file %s", 3707132451Sroberto filename); 3708280849Scy fclose(str); 3709132451Sroberto return (NULL); 371082498Sroberto } 3711132451Sroberto if ((ptr = strrchr(ptr, '.')) == NULL) { 3712280849Scy msyslog(LOG_ERR, "crypto_key: no filestamp %s", 3713132451Sroberto filename); 3714280849Scy fclose(str); 3715132451Sroberto return (NULL); 3716132451Sroberto } 3717280849Scy if (sscanf(++ptr, "%u", &fstamp) != 1) { 3718280849Scy msyslog(LOG_ERR, "crypto_key: invalid filestamp %s", 3719132451Sroberto filename); 3720280849Scy fclose(str); 3721132451Sroberto return (NULL); 3722132451Sroberto } 372382498Sroberto 372482498Sroberto /* 3725280849Scy * Read and decrypt PEM-encoded private key. If it fails to 3726280849Scy * decrypt, game over. 372782498Sroberto */ 3728280849Scy pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd1); 3729132451Sroberto fclose(str); 3730132451Sroberto if (pkey == NULL) { 3731280849Scy msyslog(LOG_ERR, "crypto_key: %s", 3732132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3733280849Scy exit (-1); 373482498Sroberto } 373582498Sroberto 373682498Sroberto /* 3737280849Scy * Make a new entry in the key cache. 3738280849Scy */ 3739280849Scy pkp = emalloc(sizeof(struct pkey_info)); 3740280849Scy pkp->link = pkinfo; 3741280849Scy pkinfo = pkp; 3742280849Scy pkp->pkey = pkey; 3743280849Scy pkp->name = estrdup(cp); 3744280849Scy pkp->fstamp = fstamp; 3745280849Scy 3746280849Scy /* 3747132451Sroberto * Leave tracks in the cryptostats. 374882498Sroberto */ 3749132451Sroberto if ((ptr = strrchr(linkname, '\n')) != NULL) 3750132451Sroberto *ptr = '\0'; 3751280849Scy snprintf(statstr, sizeof(statstr), "%s mod %d", &linkname[2], 3752132451Sroberto EVP_PKEY_size(pkey) * 8); 3753280849Scy record_crypto_stats(addr, statstr); 3754285169Scy 3755285169Scy DPRINTF(1, ("crypto_key: %s\n", statstr)); 3756132451Sroberto#ifdef DEBUG 3757132451Sroberto if (debug > 1) { 3758309007Sdelphij if (EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) 3759309007Sdelphij DSA_print_fp(stdout, EVP_PKEY_get0_DSA(pkey), 0); 3760309007Sdelphij else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) 3761309007Sdelphij RSA_print_fp(stdout, EVP_PKEY_get0_RSA(pkey), 0); 376282498Sroberto } 3763132451Sroberto#endif 3764280849Scy return (pkp); 3765132451Sroberto} 376682498Sroberto 3767132451Sroberto 3768132451Sroberto/* 3769280849Scy *********************************************************************** 3770280849Scy * * 3771280849Scy * The following routines are used only at initialization time * 3772280849Scy * * 3773280849Scy *********************************************************************** 3774280849Scy */ 3775280849Scy/* 3776132451Sroberto * crypto_cert - load certificate from file 3777132451Sroberto * 3778280849Scy * This routine loads an X.509 RSA or DSA certificate from a file and 3779132451Sroberto * constructs a info/cert value structure for this machine. The 3780132451Sroberto * structure includes a filestamp extracted from the file name. Later 3781280849Scy * the certificate can be sent to another machine on request. 3782132451Sroberto * 3783132451Sroberto * Returns certificate info/value pointer if valid, NULL if not. 3784132451Sroberto */ 3785132451Srobertostatic struct cert_info * /* certificate information */ 3786132451Srobertocrypto_cert( 3787132451Sroberto char *cp /* file name */ 3788132451Sroberto ) 3789132451Sroberto{ 3790132451Sroberto struct cert_info *ret; /* certificate information */ 3791132451Sroberto FILE *str; /* file handle */ 3792132451Sroberto char filename[MAXFILENAME]; /* name of certificate file */ 3793132451Sroberto char linkname[MAXFILENAME]; /* filestamp buffer */ 3794132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 3795132451Sroberto tstamp_t fstamp; /* filestamp */ 3796132451Sroberto long len; 3797132451Sroberto char *ptr; 3798132451Sroberto char *name, *header; 3799132451Sroberto u_char *data; 3800132451Sroberto 380182498Sroberto /* 3802132451Sroberto * Open the certificate file. If the first character of the file 3803132451Sroberto * name is not '/', prepend the keys directory string. If 3804132451Sroberto * something goes wrong, abandon ship. 380582498Sroberto */ 3806132451Sroberto if (*cp == '/') 3807280849Scy strlcpy(filename, cp, sizeof(filename)); 3808132451Sroberto else 3809280849Scy snprintf(filename, sizeof(filename), "%s/%s", keysdir, 3810280849Scy cp); 3811132451Sroberto str = fopen(filename, "r"); 3812132451Sroberto if (str == NULL) 3813132451Sroberto return (NULL); 381482498Sroberto 3815132451Sroberto /* 3816132451Sroberto * Read the filestamp, which is contained in the first line. 3817132451Sroberto */ 3818280849Scy if ((ptr = fgets(linkname, sizeof(linkname), str)) == NULL) { 3819280849Scy msyslog(LOG_ERR, "crypto_cert: empty file %s", 3820132451Sroberto filename); 3821280849Scy fclose(str); 3822132451Sroberto return (NULL); 3823132451Sroberto } 3824132451Sroberto if ((ptr = strrchr(ptr, '.')) == NULL) { 3825280849Scy msyslog(LOG_ERR, "crypto_cert: no filestamp %s", 3826132451Sroberto filename); 3827280849Scy fclose(str); 3828132451Sroberto return (NULL); 3829132451Sroberto } 3830132451Sroberto if (sscanf(++ptr, "%u", &fstamp) != 1) { 3831280849Scy msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s", 3832132451Sroberto filename); 3833280849Scy fclose(str); 3834132451Sroberto return (NULL); 3835132451Sroberto } 383682498Sroberto 383782498Sroberto /* 3838132451Sroberto * Read PEM-encoded certificate and install. 383982498Sroberto */ 3840132451Sroberto if (!PEM_read(str, &name, &header, &data, &len)) { 3841280849Scy msyslog(LOG_ERR, "crypto_cert: %s", 3842132451Sroberto ERR_error_string(ERR_get_error(), NULL)); 3843280849Scy fclose(str); 3844132451Sroberto return (NULL); 3845132451Sroberto } 3846280849Scy fclose(str); 3847132451Sroberto free(header); 3848280849Scy if (strcmp(name, "CERTIFICATE") != 0) { 3849280849Scy msyslog(LOG_NOTICE, "crypto_cert: wrong PEM type %s", 3850132451Sroberto name); 3851132451Sroberto free(name); 3852132451Sroberto free(data); 3853132451Sroberto return (NULL); 3854132451Sroberto } 3855132451Sroberto free(name); 385682498Sroberto 385782498Sroberto /* 3858280849Scy * Parse certificate and generate info/value structure. The 3859280849Scy * pointer and copy nonsense is due something broken in Solaris. 386082498Sroberto */ 3861132451Sroberto ret = cert_parse(data, len, fstamp); 3862132451Sroberto free(data); 3863132451Sroberto if (ret == NULL) 3864132451Sroberto return (NULL); 3865182007Sroberto 3866132451Sroberto if ((ptr = strrchr(linkname, '\n')) != NULL) 3867132451Sroberto *ptr = '\0'; 3868280849Scy snprintf(statstr, sizeof(statstr), "%s 0x%x len %lu", 3869280849Scy &linkname[2], ret->flags, len); 3870132451Sroberto record_crypto_stats(NULL, statstr); 3871285169Scy DPRINTF(1, ("crypto_cert: %s\n", statstr)); 3872132451Sroberto return (ret); 387382498Sroberto} 387482498Sroberto 387582498Sroberto 387682498Sroberto/* 3877280849Scy * crypto_setup - load keys, certificate and identity parameters 3878132451Sroberto * 3879280849Scy * This routine loads the public/private host key and certificate. If 3880280849Scy * available, it loads the public/private sign key, which defaults to 3881280849Scy * the host key. The host key must be RSA, but the sign key can be 3882280849Scy * either RSA or DSA. If a trusted certificate, it loads the identity 3883280849Scy * parameters. In either case, the public key on the certificate must 3884280849Scy * agree with the sign key. 3885280849Scy * 3886280849Scy * Required but missing files and inconsistent data and errors are 3887280849Scy * fatal. Allowing configuration to continue would be hazardous and 3888280849Scy * require really messy error checks. 388982498Sroberto */ 3890280849Scyvoid 3891280849Scycrypto_setup(void) 389282498Sroberto{ 3893280849Scy struct pkey_info *pinfo; /* private/public key */ 3894280849Scy char filename[MAXFILENAME]; /* file name buffer */ 3895280849Scy char hostname[MAXFILENAME]; /* host name buffer */ 3896280849Scy char *randfile; 3897132451Sroberto char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ 3898280849Scy l_fp seed; /* crypto PRNG seed as NTP timestamp */ 3899132451Sroberto u_int len; 3900280849Scy int bytes; 3901280849Scy u_char *ptr; 390282498Sroberto 390382498Sroberto /* 3904280849Scy * Check for correct OpenSSL version and avoid initialization in 3905280849Scy * the case of multiple crypto commands. 390682498Sroberto */ 3907280849Scy if (crypto_flags & CRYPTO_FLAG_ENAB) { 3908280849Scy msyslog(LOG_NOTICE, 3909280849Scy "crypto_setup: spurious crypto command"); 391082498Sroberto return; 391182498Sroberto } 3912280849Scy ssl_check_version(); 391382498Sroberto 391482498Sroberto /* 3915280849Scy * Load required random seed file and seed the random number 3916280849Scy * generator. Be default, it is found as .rnd in the user home 3917280849Scy * directory. The root home directory may be / or /root, 3918280849Scy * depending on the system. Wiggle the contents a bit and write 3919280849Scy * it back so the sequence does not repeat when we next restart. 392082498Sroberto */ 3921280849Scy if (!RAND_status()) { 3922280849Scy if (rand_file == NULL) { 3923280849Scy RAND_file_name(filename, sizeof(filename)); 3924280849Scy randfile = filename; 3925280849Scy } else if (*rand_file != '/') { 3926280849Scy snprintf(filename, sizeof(filename), "%s/%s", 3927280849Scy keysdir, rand_file); 3928280849Scy randfile = filename; 3929280849Scy } else 3930280849Scy randfile = rand_file; 3931182007Sroberto 3932280849Scy if ((bytes = RAND_load_file(randfile, -1)) == 0) { 3933280849Scy msyslog(LOG_ERR, 3934280849Scy "crypto_setup: random seed file %s missing", 3935280849Scy randfile); 3936280849Scy exit (-1); 3937280849Scy } 3938281016Scy arc4random_buf(&seed, sizeof(l_fp)); 3939280849Scy RAND_seed(&seed, sizeof(l_fp)); 3940280849Scy RAND_write_file(randfile); 3941285169Scy DPRINTF(1, ("crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n", 3942316068Sdelphij OpenSSL_version_num(), randfile, bytes)); 3943316068Sdelphij 3944280849Scy } 394582498Sroberto 394682498Sroberto /* 3947132451Sroberto * Initialize structures. 394882498Sroberto */ 3949280849Scy gethostname(hostname, sizeof(hostname)); 3950280849Scy if (host_filename != NULL) 3951280849Scy strlcpy(hostname, host_filename, sizeof(hostname)); 3952132451Sroberto if (passwd == NULL) 3953280849Scy passwd = estrdup(hostname); 3954132451Sroberto memset(&hostval, 0, sizeof(hostval)); 3955132451Sroberto memset(&pubkey, 0, sizeof(pubkey)); 3956132451Sroberto memset(&tai_leap, 0, sizeof(tai_leap)); 3957132451Sroberto 3958132451Sroberto /* 3959280849Scy * Load required host key from file "ntpkey_host_<hostname>". If 3960280849Scy * no host key file is not found or has invalid password, life 3961280849Scy * as we know it ends. The host key also becomes the default 3962280849Scy * sign key. 3963132451Sroberto */ 3964280849Scy snprintf(filename, sizeof(filename), "ntpkey_host_%s", hostname); 3965280849Scy pinfo = crypto_key(filename, passwd, NULL); 3966280849Scy if (pinfo == NULL) { 3967132451Sroberto msyslog(LOG_ERR, 3968132451Sroberto "crypto_setup: host key file %s not found or corrupt", 3969280849Scy filename); 3970132451Sroberto exit (-1); 3971132451Sroberto } 3972309007Sdelphij if (EVP_PKEY_base_id(pinfo->pkey) != EVP_PKEY_RSA) { 3973132451Sroberto msyslog(LOG_ERR, 3974132451Sroberto "crypto_setup: host key is not RSA key type"); 3975132451Sroberto exit (-1); 3976132451Sroberto } 3977280849Scy host_pkey = pinfo->pkey; 3978280849Scy sign_pkey = host_pkey; 3979280849Scy hostval.fstamp = htonl(pinfo->fstamp); 3980132451Sroberto 3981132451Sroberto /* 3982132451Sroberto * Construct public key extension field for agreement scheme. 3983132451Sroberto */ 3984132451Sroberto len = i2d_PublicKey(host_pkey, NULL); 3985132451Sroberto ptr = emalloc(len); 3986132451Sroberto pubkey.ptr = ptr; 3987132451Sroberto i2d_PublicKey(host_pkey, &ptr); 3988280849Scy pubkey.fstamp = hostval.fstamp; 3989132451Sroberto pubkey.vallen = htonl(len); 3990132451Sroberto 3991132451Sroberto /* 3992132451Sroberto * Load optional sign key from file "ntpkey_sign_<hostname>". If 3993280849Scy * available, it becomes the sign key. 3994132451Sroberto */ 3995280849Scy snprintf(filename, sizeof(filename), "ntpkey_sign_%s", hostname); 3996280849Scy pinfo = crypto_key(filename, passwd, NULL); 3997280849Scy if (pinfo != NULL) 3998280849Scy sign_pkey = pinfo->pkey; 3999132451Sroberto 4000132451Sroberto /* 4001280849Scy * Load required certificate from file "ntpkey_cert_<hostname>". 4002132451Sroberto */ 4003280849Scy snprintf(filename, sizeof(filename), "ntpkey_cert_%s", hostname); 4004280849Scy cinfo = crypto_cert(filename); 4005280849Scy if (cinfo == NULL) { 4006280849Scy msyslog(LOG_ERR, 4007280849Scy "crypto_setup: certificate file %s not found or corrupt", 4008280849Scy filename); 4009280849Scy exit (-1); 4010132451Sroberto } 4011280849Scy cert_host = cinfo; 4012280849Scy sign_digest = cinfo->digest; 4013280849Scy sign_siglen = EVP_PKEY_size(sign_pkey); 4014280849Scy if (cinfo->flags & CERT_PRIV) 4015280849Scy crypto_flags |= CRYPTO_FLAG_PRIV; 4016132451Sroberto 4017132451Sroberto /* 4018280849Scy * The certificate must be self-signed. 4019132451Sroberto */ 4020280849Scy if (strcmp(cinfo->subject, cinfo->issuer) != 0) { 4021280849Scy msyslog(LOG_ERR, 4022280849Scy "crypto_setup: certificate %s is not self-signed", 4023280849Scy filename); 4024280849Scy exit (-1); 4025132451Sroberto } 4026280849Scy hostval.ptr = estrdup(cinfo->subject); 4027280849Scy hostval.vallen = htonl(strlen(cinfo->subject)); 4028280849Scy sys_hostname = hostval.ptr; 4029280849Scy ptr = (u_char *)strchr(sys_hostname, '@'); 4030280849Scy if (ptr != NULL) 4031280849Scy sys_groupname = estrdup((char *)++ptr); 4032280849Scy if (ident_filename != NULL) 4033280849Scy strlcpy(hostname, ident_filename, sizeof(hostname)); 4034132451Sroberto 4035132451Sroberto /* 4036280849Scy * Load optional IFF parameters from file 4037280849Scy * "ntpkey_iffkey_<hostname>". 4038132451Sroberto */ 4039280849Scy snprintf(filename, sizeof(filename), "ntpkey_iffkey_%s", 4040280849Scy hostname); 4041280849Scy iffkey_info = crypto_key(filename, passwd, NULL); 4042280849Scy if (iffkey_info != NULL) 4043280849Scy crypto_flags |= CRYPTO_FLAG_IFF; 4044132451Sroberto 4045132451Sroberto /* 4046280849Scy * Load optional GQ parameters from file 4047280849Scy * "ntpkey_gqkey_<hostname>". 4048132451Sroberto */ 4049280849Scy snprintf(filename, sizeof(filename), "ntpkey_gqkey_%s", 4050280849Scy hostname); 4051280849Scy gqkey_info = crypto_key(filename, passwd, NULL); 4052280849Scy if (gqkey_info != NULL) 4053280849Scy crypto_flags |= CRYPTO_FLAG_GQ; 4054132451Sroberto 4055132451Sroberto /* 4056280849Scy * Load optional MV parameters from file 4057280849Scy * "ntpkey_mvkey_<hostname>". 4058132451Sroberto */ 4059280849Scy snprintf(filename, sizeof(filename), "ntpkey_mvkey_%s", 4060280849Scy hostname); 4061280849Scy mvkey_info = crypto_key(filename, passwd, NULL); 4062280849Scy if (mvkey_info != NULL) 4063280849Scy crypto_flags |= CRYPTO_FLAG_MV; 4064132451Sroberto 4065132451Sroberto /* 4066280849Scy * We met the enemy and he is us. Now strike up the dance. 4067132451Sroberto */ 4068280849Scy crypto_flags |= CRYPTO_FLAG_ENAB | (cinfo->nid << 16); 4069280849Scy snprintf(statstr, sizeof(statstr), "setup 0x%x host %s %s", 4070280849Scy crypto_flags, hostname, OBJ_nid2ln(cinfo->nid)); 4071280849Scy record_crypto_stats(NULL, statstr); 4072285169Scy DPRINTF(1, ("crypto_setup: %s\n", statstr)); 407382498Sroberto} 407482498Sroberto 407582498Sroberto 407682498Sroberto/* 4077280849Scy * crypto_config - configure data from the crypto command. 407882498Sroberto */ 407982498Srobertovoid 408082498Srobertocrypto_config( 4081132451Sroberto int item, /* configuration item */ 4082280849Scy char *cp /* item name */ 408382498Sroberto ) 408482498Sroberto{ 4085280849Scy int nid; 4086280849Scy 4087285169Scy DPRINTF(1, ("crypto_config: item %d %s\n", item, cp)); 4088285169Scy 408982498Sroberto switch (item) { 409082498Sroberto 409182498Sroberto /* 4092280849Scy * Set host name (host). 409382498Sroberto */ 409482498Sroberto case CRYPTO_CONF_PRIV: 4095280849Scy if (NULL != host_filename) 4096280849Scy free(host_filename); 4097280849Scy host_filename = estrdup(cp); 409882498Sroberto break; 409982498Sroberto 410082498Sroberto /* 4101280849Scy * Set group name (ident). 410282498Sroberto */ 4103280849Scy case CRYPTO_CONF_IDENT: 4104280849Scy if (NULL != ident_filename) 4105280849Scy free(ident_filename); 4106280849Scy ident_filename = estrdup(cp); 410782498Sroberto break; 410882498Sroberto 410982498Sroberto /* 4110280849Scy * Set private key password (pw). 411182498Sroberto */ 4112280849Scy case CRYPTO_CONF_PW: 4113280849Scy if (NULL != passwd) 4114280849Scy free(passwd); 4115280849Scy passwd = estrdup(cp); 411682498Sroberto break; 411782498Sroberto 411882498Sroberto /* 4119280849Scy * Set random seed file name (randfile). 412082498Sroberto */ 4121280849Scy case CRYPTO_CONF_RAND: 4122280849Scy if (NULL != rand_file) 4123280849Scy free(rand_file); 4124280849Scy rand_file = estrdup(cp); 412582498Sroberto break; 412682498Sroberto 412782498Sroberto /* 4128280849Scy * Set message digest NID. 412982498Sroberto */ 4130280849Scy case CRYPTO_CONF_NID: 4131280849Scy nid = OBJ_sn2nid(cp); 4132280849Scy if (nid == 0) 4133280849Scy msyslog(LOG_ERR, 4134280849Scy "crypto_config: invalid digest name %s", cp); 4135280849Scy else 4136280849Scy crypto_nid = nid; 413782498Sroberto break; 413882498Sroberto } 413982498Sroberto} 4140289764Sglebius 4141289764Sglebius/* 4142289764Sglebius * Get the payload size (internal value length) of an extension packet. 4143289764Sglebius * If the inner value size does not match the outer packet size (that 4144289764Sglebius * is, the value would end behind the frame given by the opcode/size 4145289764Sglebius * field) the function will effectively return UINT_MAX. If the frame is 4146289764Sglebius * too short to hold a variable-sized value, the return value is zero. 4147289764Sglebius */ 4148289764Sglebiusstatic u_int 4149289764Sglebiusexten_payload_size( 4150289764Sglebius const struct exten * ep) 4151289764Sglebius{ 4152289764Sglebius typedef const u_char *BPTR; 4153289764Sglebius 4154289764Sglebius size_t extn_size; 4155289764Sglebius size_t data_size; 4156289764Sglebius size_t head_size; 4157289764Sglebius 4158289764Sglebius data_size = 0; 4159289764Sglebius if (NULL != ep) { 4160289764Sglebius head_size = (BPTR)(&ep->vallen + 1) - (BPTR)ep; 4161289764Sglebius extn_size = (uint16_t)(ntohl(ep->opcode) & 0x0000ffff); 4162289764Sglebius if (extn_size >= head_size) { 4163289764Sglebius data_size = (uint32_t)ntohl(ep->vallen); 4164289764Sglebius if (data_size > extn_size - head_size) 4165289764Sglebius data_size = ~(size_t)0u; 4166289764Sglebius } 4167289764Sglebius } 4168289764Sglebius return (u_int)data_size; 4169289764Sglebius} 4170280849Scy# else /* !AUTOKEY follows */ 417182498Srobertoint ntp_crypto_bs_pubkey; 4172280849Scy# endif /* !AUTOKEY */ 4173