+4168. [security] A buffer accounting error could trigger an
+ assertion failure when parsing certain malformed
+ DNSSEC keys. (CVE-2015-5722) [RT #40212]
+
--- 9.9.8b1 released ---
4165. [security] A failure to reset a value to NULL in tkey.c could
BIND 9.9.8 is a maintenance release and addresses bugs
found in BIND 9.9.7 and earlier, as well as the security
- flaws described in CVE-2015-4620 and CVE-2015-5477. It also
- makes the following new features available via a compile
- time option:
+ flaws described in CVE-2015-4620, CVE-2015-5477, and
+ CVE-2015-5722.
+
+ It also makes the following new features available via a
+ compile-time option:
- New "fetchlimit" quotas are now available for the use of
recursive resolvers that are are under high query load for
+ "fetches-per-zone" limits the number of simultaneous queries
that can be sent for names within a single domain. (Note:
Unlike "fetches-per-server", this value is not self-tuning.)
- + New stats counters have been added to count
+ + New stats counters have been added to count
queries spilled due to these quotas.
- NOTE: These options are NOT built in by default; use
- "configure --enable-fetchlimit" to enable them.
+ NOTE: These options are NOT built in by default; use
+ "configure --enable-fetchlimit" to enable them.
BIND 9.9.7
<sect2 id="relnotes_security">
<title>Security Fixes</title>
<itemizedlist>
+ <listitem>
+ <para>
+ A buffer accounting error could trigger an assertion failure
+ when parsing certain malformed DNSSEC keys.
+ </para>
+ <para>
+ This flaw was discovered by Hanno Böck of the Fuzzing
+ Project, and is disclosed in CVE-2015-5722. [RT #40212]
+ </para>
+ </listitem>
<listitem>
<para>
A specially crafted query could trigger an assertion failure
- in message.c
+ in message.c.
</para>
<para>
This flaw was discovered by Jonathan Foote, and is disclosed
hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
if (hmacmd5ctx == NULL)
return (ISC_R_NOMEMORY);
- isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
+ isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH);
dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
return (ISC_R_SUCCESS);
}
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH))
return (ISC_TRUE);
else
return (ISC_FALSE);
isc_buffer_t b;
isc_result_t ret;
unsigned int bytes;
- unsigned char data[ISC_SHA1_BLOCK_LENGTH];
+ unsigned char data[ISC_MD5_BLOCK_LENGTH];
UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > ISC_SHA1_BLOCK_LENGTH) {
- bytes = ISC_SHA1_BLOCK_LENGTH;
- key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
+ if (bytes > ISC_MD5_BLOCK_LENGTH) {
+ bytes = ISC_MD5_BLOCK_LENGTH;
+ key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
}
- memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
+ memset(data, 0, ISC_MD5_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacmd5_fromdns(key, &b);
- memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
+ memset(data, 0, ISC_MD5_BLOCK_LENGTH);
return (ret);
}
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA1_BLOCK_LENGTH) {
+ if (r.length > ISC_MD5_BLOCK_LENGTH) {
isc_md5_init(&md5ctx);
isc_md5_update(&md5ctx, r.base, r.length);
isc_md5_final(&md5ctx, hkey->key);
key->key_size = keylen * 8;
key->keydata.hmacmd5 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
key->key_size = keylen * 8;
key->keydata.hmacsha1 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
key->key_size = keylen * 8;
key->keydata.hmacsha224 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
key->key_size = keylen * 8;
key->keydata.hmacsha256 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
key->key_size = keylen * 8;
key->keydata.hmacsha384 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
key->key_size = keylen * 8;
key->keydata.hmacsha512 = hkey;
+ isc_buffer_forward(data, r.length);
+
return (ISC_R_SUCCESS);
}
#define DST_ALG_HMACSHA256 163 /* XXXMPA */
#define DST_ALG_HMACSHA384 164 /* XXXMPA */
#define DST_ALG_HMACSHA512 165 /* XXXMPA */
+#define DST_ALG_INDIRECT 252
#define DST_ALG_PRIVATE 254
#define DST_ALG_EXPAND 255
#define DST_MAX_ALGS 255
dns_name_fromregion(&tname, &remaining);
INSIST(remaining.length >= tname.length);
isc_buffer_forward(&source, tname.length);
- remaining.length -= tname.length;
- remaining.base += tname.length;
+ isc_region_consume(&remaining, tname.length);
INSIST(remaining.length >= 2);
type = isc_buffer_getuint16(&source);
- remaining.length -= 2;
- remaining.base += 2;
+ isc_region_consume(&remaining, 2);
if (type != dns_rdatatype_rrsig ||
!dns_name_equal(&tname, name)) {
INSIST(remaining.length >= 1);
trust = isc_buffer_getuint8(&source);
INSIST(trust <= dns_trust_ultimate);
- remaining.length -= 1;
- remaining.base += 1;
+ isc_region_consume(&remaining, 1);
raw = remaining.base;
count = raw[0] * 256 + raw[1];
static void
uint16_toregion(isc_uint16_t val, isc_region_t *region) {
- *region->base++ = (val & 0xff00) >> 8;
- *region->base++ = (val & 0x00ff);
+ *region->base = (val & 0xff00) >> 8;
+ isc_region_consume(region, 1);
+ *region->base = (val & 0x00ff);
+ isc_region_consume(region, 1);
}
static isc_uint16_t
val = ((unsigned int)(cp[0])) << 8;
val |= ((unsigned int)(cp[1]));
- region->base += 2;
+ isc_region_consume(region, 2);
+
return (val);
}
}
else
BN_bn2bin(dh->p, r.base);
- r.base += plen;
+ isc_region_consume(&r, plen);
uint16_toregion(glen, &r);
if (glen > 0)
BN_bn2bin(dh->g, r.base);
- r.base += glen;
+ isc_region_consume(&r, glen);
uint16_toregion(publen, &r);
BN_bn2bin(dh->pub_key, r.base);
- r.base += publen;
+ isc_region_consume(&r, publen);
isc_buffer_add(data, dnslen);
return (DST_R_INVALIDPUBLICKEY);
}
if (plen == 1 || plen == 2) {
- if (plen == 1)
- special = *r.base++;
- else
+ if (plen == 1) {
+ special = *r.base;
+ isc_region_consume(&r, 1);
+ } else {
special = uint16_fromregion(&r);
+ }
switch (special) {
case 1:
dh->p = bn768;
DH_free(dh);
return (DST_R_INVALIDPUBLICKEY);
}
- }
- else {
+ } else {
dh->p = BN_bin2bn(r.base, plen, NULL);
- r.base += plen;
+ isc_region_consume(&r, plen);
}
/*
return (DST_R_INVALIDPUBLICKEY);
}
}
- }
- else {
+ } else {
if (glen == 0) {
DH_free(dh);
return (DST_R_INVALIDPUBLICKEY);
}
dh->g = BN_bin2bn(r.base, glen, NULL);
}
- r.base += glen;
+ isc_region_consume(&r, glen);
if (r.length < 2) {
DH_free(dh);
return (DST_R_INVALIDPUBLICKEY);
}
dh->pub_key = BN_bin2bn(r.base, publen, NULL);
- r.base += publen;
+ isc_region_consume(&r, publen);
key->key_size = BN_num_bits(dh->p);
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
#ifdef OPENSSL
#ifndef USE_EVP
#define USE_EVP 1
DSA *dsa = key->keydata.dsa;
isc_region_t r;
DSA_SIG *dsasig;
+ unsigned int klen;
#if USE_EVP
EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
EVP_PKEY *pkey;
ISC_R_FAILURE));
}
free(sigbuf);
+
#elif 0
/* Only use EVP for the Digest */
if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
"DSA_do_sign",
DST_R_SIGNFAILURE));
#endif
- *r.base++ = (key->key_size - 512)/64;
+
+ klen = (key->key_size - 512)/64;
+ if (klen > 255)
+ return (ISC_R_FAILURE);
+ *r.base = klen;
+ isc_region_consume(&r, 1);
+
BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
- r.base += ISC_SHA1_DIGESTLENGTH;
+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
- r.base += ISC_SHA1_DIGESTLENGTH;
+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
DSA_SIG_free(dsasig);
isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
if (r.length < (unsigned int) dnslen)
return (ISC_R_NOSPACE);
- *r.base++ = t;
+ *r.base = t;
+ isc_region_consume(&r, 1);
BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
- r.base += ISC_SHA1_DIGESTLENGTH;
+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
isc_buffer_add(data, dnslen);
return (ISC_R_NOMEMORY);
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
- t = (unsigned int) *r.base++;
+ t = (unsigned int) *r.base;
+ isc_region_consume(&r, 1);
if (t > 8) {
DSA_free(dsa);
return (DST_R_INVALIDPUBLICKEY);
}
p_bytes = 64 + 8 * t;
- if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
+ if (r.length < ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
DSA_free(dsa);
return (DST_R_INVALIDPUBLICKEY);
}
dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
- r.base += ISC_SHA1_DIGESTLENGTH;
+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
- r.base += p_bytes;
+ isc_region_consume(&r, p_bytes);
key->key_size = p_bytes * 8;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
#include <config.h>
#ifdef HAVE_OPENSSL_ECDSA
"ECDSA_do_sign",
DST_R_SIGNFAILURE));
BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2);
- r.base += siglen / 2;
+ isc_region_consume(&r, siglen / 2);
BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2);
- r.base += siglen / 2;
+ isc_region_consume(&r, siglen / 2);
ECDSA_SIG_free(ecdsasig);
isc_buffer_add(sig, siglen);
ret = ISC_R_SUCCESS;
RSA *rsa;
isc_region_t r;
unsigned int e_bytes;
+ unsigned int length;
#if USE_EVP
EVP_PKEY *pkey;
#endif
isc_buffer_remainingregion(data, &r);
if (r.length == 0)
return (ISC_R_SUCCESS);
+ length = r.length;
rsa = RSA_new();
if (rsa == NULL)
RSA_free(rsa);
return (DST_R_INVALIDPUBLICKEY);
}
- e_bytes = *r.base++;
- r.length--;
+ e_bytes = *r.base;
+ isc_region_consume(&r, 1);
if (e_bytes == 0) {
if (r.length < 2) {
RSA_free(rsa);
return (DST_R_INVALIDPUBLICKEY);
}
- e_bytes = ((*r.base++) << 8);
- e_bytes += *r.base++;
- r.length -= 2;
+ e_bytes = (*r.base) << 8;
+ isc_region_consume(&r, 1);
+ e_bytes += *r.base;
+ isc_region_consume(&r, 1);
}
if (r.length < e_bytes) {
return (DST_R_INVALIDPUBLICKEY);
}
rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
- r.base += e_bytes;
- r.length -= e_bytes;
+ isc_region_consume(&r, e_bytes);
rsa->n = BN_bin2bn(r.base, r.length, NULL);
key->key_size = BN_num_bits(rsa->n);
- isc_buffer_forward(data, r.length);
+ isc_buffer_forward(data, length);
#if USE_EVP
pkey = EVP_PKEY_new();
REQUIRE(VALID_RESOLVER(resolver));
+ /*
+ * DH is unsupported for DNSKEYs, see RFC 4034 sec. A.1.
+ */
+ if ((alg == DST_ALG_DH) || (alg == DST_ALG_INDIRECT))
+ return (ISC_FALSE);
+
#if USE_ALGLOCK
RWLOCK(&resolver->alglock, isc_rwlocktype_read);
#endif
#endif
if (found)
return (ISC_FALSE);
+
return (dst_algorithm_supported(alg));
}