http://bk.ntp.org/ntp-stable/?PAGE=patch&REV=54abb266In81wLNAqIaovtP8f2UmUw http://bk.ntp.org/ntp-stable/?PAGE=patch&REV=54a7c595jlwS3KmAxBML75HFGLR_pQ http://bk.ntp.org/ntp-stable/?PAGE=patch&REV=5492d353ncauuWt_PONxaDhC5Qv_SA diff -up ntp-4.2.6p5/ntpd/ntp_crypto.c.cve-2014-9297 ntp-4.2.6p5/ntpd/ntp_crypto.c --- ntp-4.2.6p5/ntpd/ntp_crypto.c.cve-2014-9297 2015-02-04 11:37:44.488673076 +0100 +++ ntp-4.2.6p5/ntpd/ntp_crypto.c 2015-02-04 11:37:44.491673082 +0100 @@ -109,6 +109,7 @@ #define TAI_1972 10 /* initial TAI offset (s) */ #define MAX_LEAP 100 /* max UTC leapseconds (s) */ #define VALUE_LEN (6 * 4) /* min response field length */ +#define MAX_VALLEN (65535 - VALUE_LEN) #define YEAR (60 * 60 * 24 * 365) /* seconds in year */ /* @@ -147,8 +148,8 @@ static char *rand_file = NULL; /* random */ static int crypto_verify (struct exten *, struct value *, struct peer *); -static int crypto_encrypt (struct exten *, struct value *, - keyid_t *); +static int crypto_encrypt (const u_char *, u_int, keyid_t *, + struct value *); static int crypto_alice (struct peer *, struct value *); static int crypto_alice2 (struct peer *, struct value *); static int crypto_alice3 (struct peer *, struct value *); @@ -444,6 +445,12 @@ crypto_recv( tstamp = ntohl(ep->tstamp); fstamp = ntohl(ep->fstamp); vallen = ntohl(ep->vallen); + /* + * Bug 2761: I hope this isn't too early... + */ + if ( vallen == 0 + || len - VALUE_LEN < vallen) + return XEVNT_LEN; } switch (code) { @@ -494,8 +501,9 @@ crypto_recv( rval = XEVNT_ERR; break; } + INSIST(len >= VALUE_LEN); if (vallen == 0 || vallen > MAXHOSTNAME || - len < VALUE_LEN + vallen) { + len - VALUE_LEN < vallen) { rval = XEVNT_LEN; break; } @@ -1162,11 +1170,11 @@ crypto_xmit( * choice. */ case CRYPTO_CERT | CRYPTO_RESP: - vallen = ntohl(ep->vallen); - if (vallen == 0 || vallen > MAXHOSTNAME) { + vallen = ntohl(ep->vallen); /* Must be <64k */ + if (vallen == 0 || vallen > MAXHOSTNAME || + len - VALUE_LEN < vallen) { rval = XEVNT_LEN; break; - } else { memcpy(certname, ep->pkt, vallen); certname[vallen] = '\0'; @@ -1315,7 +1323,10 @@ crypto_xmit( * anything goes wrong. */ case CRYPTO_COOK | CRYPTO_RESP: - if ((opcode & 0xffff) < VALUE_LEN) { + vallen = ntohl(ep->vallen); /* Must be <64k */ + if ( vallen == 0 + || (vallen >= MAX_VALLEN) + || (opcode & 0x0000ffff) < VALUE_LEN + vallen) { rval = XEVNT_LEN; break; } @@ -1323,8 +1334,8 @@ crypto_xmit( tcookie = cookie; else tcookie = peer->hcookie; - if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) == - XEVNT_OK) { + if ((rval = crypto_encrypt((const u_char *)ep->pkt, vallen, &tcookie, &vtemp)) + == XEVNT_OK) { len = crypto_send(fp, &vtemp, start); value_free(&vtemp); } @@ -1464,13 +1475,16 @@ crypto_verify( * up to the next word (4 octets). */ vallen = ntohl(ep->vallen); - if (vallen == 0) + if ( vallen == 0 + || vallen > MAX_VALLEN) return (XEVNT_LEN); i = (vallen + 3) / 4; siglen = ntohl(ep->pkt[i++]); - if (len < VALUE_LEN + ((vallen + 3) / 4) * 4 + ((siglen + 3) / - 4) * 4) + if ( siglen > MAX_VALLEN + || len - VALUE_LEN < ((vallen + 3) / 4) * 4 + || len - VALUE_LEN - ((vallen + 3) / 4) * 4 + < ((siglen + 3) / 4) * 4) return (XEVNT_LEN); /* @@ -1528,6 +1542,7 @@ crypto_verify( * proventic bit. What a relief. */ EVP_VerifyInit(&ctx, peer->digest); + /* XXX: the "+ 12" needs to be at least documented... */ EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen + 12); if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen, pkey) <= 0) @@ -1540,34 +1555,32 @@ crypto_verify( /* - * crypto_encrypt - construct encrypted cookie and signature from - * extension field and cookie + * crypto_encrypt - construct vp (encrypted cookie and signature) from + * the public key and cookie. * - * Returns + * Returns: * XEVNT_OK success * XEVNT_CKY bad or missing cookie * XEVNT_PUB bad or missing public key */ static int crypto_encrypt( - struct exten *ep, /* extension pointer */ - struct value *vp, /* value pointer */ - keyid_t *cookie /* server cookie */ + const u_char *ptr, /* Public Key */ + u_int vallen, /* Length of Public Key */ + keyid_t *cookie, /* server cookie */ + struct value *vp /* value pointer */ ) { EVP_PKEY *pkey; /* public key */ EVP_MD_CTX ctx; /* signature context */ tstamp_t tstamp; /* NTP timestamp */ u_int32 temp32; - u_int len; - u_char *ptr; + u_char *puch; /* * Extract the public key from the request. */ - len = ntohl(ep->vallen); - ptr = (u_char *)ep->pkt; - pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len); + pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, vallen); if (pkey == NULL) { msyslog(LOG_ERR, "crypto_encrypt: %s", ERR_error_string(ERR_get_error(), NULL)); @@ -1581,12 +1594,12 @@ crypto_encrypt( tstamp = crypto_time(); vp->tstamp = htonl(tstamp); vp->fstamp = hostval.tstamp; - len = EVP_PKEY_size(pkey); - vp->vallen = htonl(len); - vp->ptr = emalloc(len); - ptr = vp->ptr; + vallen = EVP_PKEY_size(pkey); + vp->vallen = htonl(vallen); + vp->ptr = emalloc(vallen); + puch = vp->ptr; temp32 = htonl(*cookie); - if (RSA_public_encrypt(4, (u_char *)&temp32, ptr, + if (RSA_public_encrypt(4, (u_char *)&temp32, puch, pkey->pkey.rsa, RSA_PKCS1_OAEP_PADDING) <= 0) { msyslog(LOG_ERR, "crypto_encrypt: %s", ERR_error_string(ERR_get_error(), NULL)); @@ -1601,8 +1614,8 @@ crypto_encrypt( vp->sig = emalloc(sign_siglen); EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); - EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) + EVP_SignUpdate(&ctx, vp->ptr, vallen); + if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) vp->siglen = htonl(sign_siglen); return (XEVNT_OK); } @@ -1673,6 +1686,9 @@ crypto_ident( * call in the protocol module. * * Returns extension field pointer (no errors) + * + * XXX: opcode and len should really be 32-bit quantities and + * we should make sure that str is not too big. */ struct exten * crypto_args( @@ -1685,24 +1701,31 @@ crypto_args( tstamp_t tstamp; /* NTP timestamp */ struct exten *ep; /* extension field pointer */ u_int len; /* extension field length */ + size_t slen; tstamp = crypto_time(); len = sizeof(struct exten); - if (str != NULL) - len += strlen(str); + if (str != NULL) { + slen = strlen(str); + INSIST(slen < MAX_VALLEN); + len += slen; + } ep = emalloc(len); memset(ep, 0, len); if (opcode == 0) return (ep); + REQUIRE(0 == (len & ~0x0000ffff)); + REQUIRE(0 == (opcode & ~0xffff0000)); + ep->opcode = htonl(opcode + len); ep->associd = htonl(associd); ep->tstamp = htonl(tstamp); ep->fstamp = hostval.tstamp; ep->vallen = 0; if (str != NULL) { - ep->vallen = htonl(strlen(str)); - memcpy((char *)ep->pkt, str, strlen(str)); + ep->vallen = htonl(slen); + memcpy((char *)ep->pkt, str, slen); } return (ep); } @@ -1715,6 +1738,8 @@ crypto_args( * Note: it is not polite to send a nonempty signature with zero * timestamp or a nonzero timestamp with an empty signature, but those * rules are not enforced here. + * + * XXX This code won't work on a box with 16-bit ints. */ int crypto_send( @@ -1730,8 +1755,9 @@ crypto_send( * Calculate extension field length and check for buffer * overflow. Leave room for the MAC. */ - len = 16; + len = 16; /* XXX Document! */ vallen = ntohl(vp->vallen); + INSIST(vallen <= MAX_VALLEN); len += ((vallen + 3) / 4 + 1) * 4; siglen = ntohl(vp->siglen); len += ((siglen + 3) / 4 + 1) * 4; @@ -1772,6 +1798,7 @@ crypto_send( } opcode = ntohl(ep->opcode); ep->opcode = htonl((opcode & 0xffff0000) | len); + ENSURE(len <= MAX_VALLEN); return (len); } @@ -1807,7 +1834,6 @@ crypto_update(void) if (hostval.tstamp == 0) return; - /* * Sign public key and timestamps. The filestamp is derived from * the host key file extension from wherever the file was @@ -2108,7 +2134,8 @@ crypto_bob( tstamp_t tstamp; /* NTP timestamp */ BIGNUM *bn, *bk, *r; u_char *ptr; - u_int len; + u_int len; /* extension field length */ + u_int vallen = 0; /* value length */ /* * If the IFF parameters are not valid, something awful @@ -2123,8 +2150,11 @@ crypto_bob( /* * Extract r from the challenge. */ - len = ntohl(ep->vallen); - if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) { + vallen = ntohl(ep->vallen); + len = ntohl(ep->opcode) & 0x0000ffff; + if (vallen == 0 || len < VALUE_LEN || len - VALUE_LEN < vallen) + return XEVNT_LEN; + if ((r = BN_bin2bn((u_char *)ep->pkt, vallen, NULL)) == NULL) { msyslog(LOG_ERR, "crypto_bob: %s", ERR_error_string(ERR_get_error(), NULL)); return (XEVNT_ERR); @@ -2136,7 +2166,7 @@ crypto_bob( */ bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new(); sdsa = DSA_SIG_new(); - BN_rand(bk, len * 8, -1, 1); /* k */ + BN_rand(bk, vallen * 8, -1, 1); /* k */ BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */ BN_add(bn, bn, bk); BN_mod(bn, bn, dsa->q, bctx); /* k + b r mod q */ @@ -2155,30 +2185,37 @@ crypto_bob( * Encode the values in ASN.1 and sign. The filestamp is from * the local file. */ - len = i2d_DSA_SIG(sdsa, NULL); - if (len == 0) { + vallen = i2d_DSA_SIG(sdsa, NULL); + if (vallen == 0) { msyslog(LOG_ERR, "crypto_bob: %s", ERR_error_string(ERR_get_error(), NULL)); DSA_SIG_free(sdsa); return (XEVNT_ERR); } + if (vallen > MAX_VALLEN) { + msyslog(LOG_ERR, "crypto_bob: signature is too big: %d", + vallen); + DSA_SIG_free(sdsa); + return (XEVNT_LEN); + } memset(vp, 0, sizeof(struct value)); tstamp = crypto_time(); vp->tstamp = htonl(tstamp); vp->fstamp = htonl(iffkey_info->fstamp); - vp->vallen = htonl(len); - ptr = emalloc(len); + vp->vallen = htonl(vallen); + ptr = emalloc(vallen); vp->ptr = ptr; i2d_DSA_SIG(sdsa, &ptr); DSA_SIG_free(sdsa); if (tstamp == 0) return (XEVNT_OK); + /* XXX: more validation to make sure the sign fits... */ vp->sig = emalloc(sign_siglen); EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); - EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) + EVP_SignUpdate(&ctx, vp->ptr, vallen); + if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) vp->siglen = htonl(sign_siglen); return (XEVNT_OK); } diff -up ntp-4.2.6p5/ntpd/ntp_proto.c.cve-2014-9297 ntp-4.2.6p5/ntpd/ntp_proto.c --- ntp-4.2.6p5/ntpd/ntp_proto.c.cve-2014-9297 2015-02-04 11:37:44.490673080 +0100 +++ ntp-4.2.6p5/ntpd/ntp_proto.c 2015-02-04 11:47:42.653868627 +0100 @@ -431,7 +431,7 @@ receive( */ authlen = LEN_PKT_NOMAC; has_mac = rbufp->recv_length - authlen; - while (has_mac != 0) { + while (has_mac > 0) { u_int32 len; if (has_mac % 4 != 0 || has_mac < MIN_MAC_LEN) { @@ -456,6 +456,14 @@ receive( } /* + * If has_mac is < 0 we had a malformed packet. + */ + if (has_mac < 0) { + sys_badlength++; + return; /* bad length */ + } + + /* * If authentication required, a MAC must be present. */ if (restrict_mask & RES_DONTTRUST && has_mac == 0) {