diff --git a/CHANGES b/CHANGES index 75f15c625e..2f20d3acb8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4168. [security] A buffer accounting error could trigger an + assertion failure when parsing certain malformed + DNSSEC keys. (CVE-2015-5722) [RT #40212] + 4167. [func] Update rndc's usage output to include recently added commands. Thanks to Tony Finch for submitting a patch. [RT #40010] diff --git a/README b/README index 67982136e2..a40dc5d15b 100644 --- a/README +++ b/README @@ -119,7 +119,7 @@ BIND 9.11.0 This release addresses the security flaws described in CVE-2014-3214, CVE-2014-3859, CVE-2014-8500, CVE-2014-8680, - CVE-2015-1349 and CVE-2015-5477. + CVE-2015-1349, CVE-2015-5477 and CVE-2015-5722. BIND 9.10.0 diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index 8b3237e94f..1f6ca5b857 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -38,10 +38,20 @@ Security Fixes + + + A buffer accounting error could trigger an assertion failure + when parsing certain malformed DNSSEC keys. + + + This flaw was discovered by Hanno Böck of the Fuzzing + Project, and is disclosed in CVE-2015-5722. [RT #40212] + + A specially crafted query could trigger an assertion failure - in message.c + in message.c. This flaw was discovered by Jonathan Foote, and is disclosed diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c index 01876d336a..b1ef314e4e 100644 --- a/lib/dns/hmac_link.c +++ b/lib/dns/hmac_link.c @@ -76,7 +76,7 @@ hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) { 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); } @@ -139,7 +139,7 @@ hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) { 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); @@ -150,17 +150,17 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { 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) @@ -169,7 +169,7 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { 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); } @@ -223,7 +223,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) { 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); @@ -236,6 +236,8 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacmd5 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } @@ -519,6 +521,8 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacsha1 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } @@ -804,6 +808,8 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacsha224 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } @@ -1089,6 +1095,8 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacsha256 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } @@ -1374,6 +1382,8 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacsha384 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } @@ -1659,6 +1669,8 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) { key->key_size = keylen * 8; key->keydata.hmacsha512 = hkey; + isc_buffer_forward(data, r.length); + return (ISC_R_SUCCESS); } diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 080b405480..df81b398c7 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -69,6 +69,7 @@ typedef struct dst_context dst_context_t; #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 diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index de9f5f4c2d..9252762a01 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -615,13 +615,11 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, 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)) { @@ -633,8 +631,7 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *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]; diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c index d41fee38b2..9f42219806 100644 --- a/lib/dns/openssldh_link.c +++ b/lib/dns/openssldh_link.c @@ -277,8 +277,10 @@ openssldh_destroy(dst_key_t *key) { 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 @@ -289,7 +291,8 @@ uint16_fromregion(isc_region_t *region) { val = ((unsigned int)(cp[0])) << 8; val |= ((unsigned int)(cp[1])); - region->base += 2; + isc_region_consume(region, 2); + return (val); } @@ -330,16 +333,16 @@ openssldh_todns(const dst_key_t *key, isc_buffer_t *data) { } 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); @@ -380,10 +383,12 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { 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; @@ -398,10 +403,9 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { 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); } /* @@ -432,15 +436,14 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { 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); @@ -452,7 +455,7 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { 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); diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c index 510e78e5ae..963e2f508e 100644 --- a/lib/dns/openssldsa_link.c +++ b/lib/dns/openssldsa_link.c @@ -29,8 +29,6 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #ifdef OPENSSL #ifndef USE_EVP #define USE_EVP 1 @@ -137,6 +135,7 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { 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; @@ -188,6 +187,7 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { ISC_R_FAILURE)); } free(sigbuf); + #elif 0 /* Only use EVP for the Digest */ if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) { @@ -209,11 +209,17 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { "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); @@ -457,15 +463,16 @@ openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) { 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); @@ -490,29 +497,30 @@ openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 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; diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c index b881880c7d..b6b34611ce 100644 --- a/lib/dns/opensslecdsa_link.c +++ b/lib/dns/opensslecdsa_link.c @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #include #if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA) @@ -159,9 +157,9 @@ opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { "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; diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index 301e469710..e34cdd823d 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -971,6 +971,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { RSA *rsa; isc_region_t r; unsigned int e_bytes; + unsigned int length; #if USE_EVP EVP_PKEY *pkey; #endif @@ -978,6 +979,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { isc_buffer_remainingregion(data, &r); if (r.length == 0) return (ISC_R_SUCCESS); + length = r.length; rsa = RSA_new(); if (rsa == NULL) @@ -988,17 +990,18 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 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) { @@ -1006,14 +1009,13 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 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(); diff --git a/lib/dns/pkcs11dh_link.c b/lib/dns/pkcs11dh_link.c index c4d16d47ac..7679f4b2de 100644 --- a/lib/dns/pkcs11dh_link.c +++ b/lib/dns/pkcs11dh_link.c @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #ifdef PKCS11CRYPTO #include @@ -632,8 +630,10 @@ pkcs11dh_destroy(dst_key_t *key) { 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 @@ -644,7 +644,8 @@ uint16_fromregion(isc_region_t *region) { val = ((unsigned int)(cp[0])) << 8; val |= ((unsigned int)(cp[1])); - region->base += 2; + isc_region_consume(region, 2); + return (val); } @@ -708,16 +709,16 @@ pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) { } else memmove(r.base, prime, plen); - r.base += plen; + isc_region_consume(&r, plen); uint16_toregion(glen, &r); if (glen > 0) memmove(r.base, base, glen); - r.base += glen; + isc_region_consume(&r, glen); uint16_toregion(publen, &r); memmove(r.base, pub, publen); - r.base += publen; + isc_region_consume(&r, publen); isc_buffer_add(data, dnslen); @@ -764,10 +765,12 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { } plen_ = plen; 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: prime = pk11_dh_bn768; @@ -789,7 +792,7 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { } else { prime = r.base; - r.base += plen; + isc_region_consume(&r, plen); } /* @@ -835,7 +838,7 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { } base = r.base; } - r.base += glen; + isc_region_consume(&r, glen); if (r.length < 2) { memset(dh, 0, sizeof(*dh)); @@ -849,7 +852,7 @@ pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { return (DST_R_INVALIDPUBLICKEY); } pub = r.base; - r.base += publen; + isc_region_consume(&r, publen); key->key_size = pk11_numbits(prime, plen_); diff --git a/lib/dns/pkcs11dsa_link.c b/lib/dns/pkcs11dsa_link.c index be31f72c55..809f7f4b14 100644 --- a/lib/dns/pkcs11dsa_link.c +++ b/lib/dns/pkcs11dsa_link.c @@ -388,6 +388,7 @@ pkcs11dsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { isc_region_t r; pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; isc_result_t ret = ISC_R_SUCCESS; + unsigned int klen; isc_buffer_availableregion(sig, &r); if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1) @@ -399,7 +400,10 @@ pkcs11dsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { if (siglen != ISC_SHA1_DIGESTLENGTH * 2) return (DST_R_SIGNFAILURE); - *r.base = (dctx->key->key_size - 512)/64; + klen = (dctx->key->key_size - 512)/64; + if (klen > 255) + return (ISC_R_FAILURE); + *r.base = klen; isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1); err: @@ -744,23 +748,25 @@ pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data) { return (ISC_R_NOSPACE); memset(r.base, 0, dnslen); - *r.base++ = t; + *r.base = t; + isc_region_consume(&r, 1); + cp = (CK_BYTE *) subprime->pValue; memmove(r.base + ISC_SHA1_DIGESTLENGTH - subprime->ulValueLen, cp, subprime->ulValueLen); - r.base += ISC_SHA1_DIGESTLENGTH; + isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); cp = (CK_BYTE *) prime->pValue; memmove(r.base + key->key_size/8 - prime->ulValueLen, cp, prime->ulValueLen); - r.base += p_bytes; + isc_region_consume(&r, p_bytes); cp = (CK_BYTE *) base->pValue; memmove(r.base + key->key_size/8 - base->ulValueLen, cp, base->ulValueLen); - r.base += p_bytes; + isc_region_consume(&r, p_bytes); cp = (CK_BYTE *) pub_key->pValue; memmove(r.base + key->key_size/8 - pub_key->ulValueLen, cp, pub_key->ulValueLen); - r.base += p_bytes; + isc_region_consume(&r, p_bytes); isc_buffer_add(data, dnslen); @@ -784,7 +790,8 @@ pkcs11dsa_fromdns(dst_key_t *key, isc_buffer_t *data) { return (ISC_R_NOMEMORY); memset(dsa, 0, sizeof(*dsa)); - t = (unsigned int) *r.base++; + t = (unsigned int) *r.base; + isc_region_consume(&r, 1); if (t > 8) { memset(dsa, 0, sizeof(*dsa)); isc_mem_put(key->mctx, dsa, sizeof(*dsa)); @@ -792,23 +799,23 @@ pkcs11dsa_fromdns(dst_key_t *key, isc_buffer_t *data) { } p_bytes = 64 + 8 * t; - if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) { + if (r.length < ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) { memset(dsa, 0, sizeof(*dsa)); isc_mem_put(key->mctx, dsa, sizeof(*dsa)); return (DST_R_INVALIDPUBLICKEY); } subprime = r.base; - r.base += ISC_SHA1_DIGESTLENGTH; + isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); prime = r.base; - r.base += p_bytes; + isc_region_consume(&r, p_bytes); base = r.base; - r.base += p_bytes; + isc_region_consume(&r, p_bytes); pub_key = r.base; - r.base += p_bytes; + isc_region_consume(&r, p_bytes); key->key_size = p_bytes * 8; diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c index a028925b6c..bca1392ab8 100644 --- a/lib/dns/pkcs11rsa_link.c +++ b/lib/dns/pkcs11rsa_link.c @@ -791,23 +791,21 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { unsigned int e_bytes, mod_bytes; CK_BYTE *exponent = NULL, *modulus = NULL; CK_ATTRIBUTE *attr; + unsigned int length; isc_buffer_remainingregion(data, &r); if (r.length == 0) return (ISC_R_SUCCESS); + length = r.length; rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); if (rsa == NULL) return (ISC_R_NOMEMORY); + memset(rsa, 0, sizeof(*rsa)); - if (r.length < 1) { - memset(rsa, 0, sizeof(*rsa)); - isc_mem_put(key->mctx, rsa, sizeof(*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) { @@ -815,9 +813,10 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { isc_mem_put(key->mctx, rsa, sizeof(*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) { @@ -826,14 +825,13 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { return (DST_R_INVALIDPUBLICKEY); } exponent = r.base; - r.base += e_bytes; - r.length -= e_bytes; + isc_region_consume(&r, e_bytes); modulus = r.base; mod_bytes = r.length; key->key_size = pk11_numbits(modulus, mod_bytes); - isc_buffer_forward(data, r.length); + isc_buffer_forward(data, length); rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); if (rsa->repr == NULL) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 843ff1a43a..bd93b52755 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -9678,6 +9678,12 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name, 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 @@ -9697,6 +9703,7 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name, #endif if (found) return (ISC_FALSE); + return (dst_algorithm_supported(alg)); }