mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 08:59:59 -04:00
[9.20] fix: usr: prevent malicious DNSSEC zones from exhausting validator CPU
A DNSSEC-signed zone could publish a DNSKEY with an unusually large RSA public exponent and force any validator resolving names in that zone to spend disproportionate CPU verifying signatures. The validator now rejects such DNSKEYs, matching the limit already applied to keys read from files or HSMs. Closes #5881 Backport of MR !11917 Merge branch 'backport-5881-rsa-exponent-keytrap-cpu-amplification-9.20' into 'bind-9.20' See merge request isc-projects/bind9!11923
This commit is contained in:
commit
c425827743
2 changed files with 50 additions and 0 deletions
|
|
@ -827,6 +827,9 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
|
|||
if (c.e == NULL || c.n == NULL) {
|
||||
DST_RET(ISC_R_NOMEMORY);
|
||||
}
|
||||
if (BN_num_bits(c.e) > RSA_MAX_PUBEXP_BITS) {
|
||||
DST_RET(ISC_R_RANGE);
|
||||
}
|
||||
isc_buffer_forward(data, length);
|
||||
|
||||
key->key_size = BN_num_bits(c.n);
|
||||
|
|
|
|||
|
|
@ -225,8 +225,55 @@ ISC_RUN_TEST_IMPL(isc_rsa_verify) {
|
|||
dst_key_free(&key);
|
||||
}
|
||||
|
||||
/* dst_key_fromdns rejects oversized RSA public exponents */
|
||||
ISC_RUN_TEST_IMPL(isc_rsa_fromdns_oversized_exponent) {
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fname;
|
||||
dns_name_t *name;
|
||||
dst_key_t *key = NULL;
|
||||
isc_buffer_t buf;
|
||||
unsigned char rdata[300] = { 0 };
|
||||
size_t i = 0;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
name = dns_fixedname_initname(&fname);
|
||||
isc_buffer_constinit(&buf, "rsa.", 4);
|
||||
isc_buffer_add(&buf, 4);
|
||||
result = dns_name_fromtext(name, &buf, NULL, 0, NULL);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/* DNSKEY rdata: flags(2) + proto(1) + alg(1) + key */
|
||||
rdata[i++] = 0x01; /* flags hi (KSK) */
|
||||
rdata[i++] = 0x00; /* flags lo */
|
||||
rdata[i++] = 0x03; /* protocol */
|
||||
rdata[i++] = DST_ALG_RSASHA256;
|
||||
/* RSA wire key: e_bytes + e + n. Use a 6-byte (48-bit) e
|
||||
* with a non-zero leading byte so it exceeds the 35-bit cap. */
|
||||
rdata[i++] = 6;
|
||||
rdata[i++] = 0x01;
|
||||
rdata[i++] = 0x02;
|
||||
rdata[i++] = 0x03;
|
||||
rdata[i++] = 0x04;
|
||||
rdata[i++] = 0x05;
|
||||
rdata[i++] = 0x06;
|
||||
/* 256 bytes of arbitrary modulus (2048-bit). */
|
||||
for (size_t j = 0; j < 256; j++) {
|
||||
rdata[i++] = 0xAB;
|
||||
}
|
||||
|
||||
isc_buffer_init(&buf, rdata, i);
|
||||
isc_buffer_add(&buf, i);
|
||||
|
||||
result = dst_key_fromdns(name, dns_rdataclass_in, &buf, mctx, &key);
|
||||
assert_int_equal(result, ISC_R_RANGE);
|
||||
assert_null(key);
|
||||
}
|
||||
|
||||
ISC_TEST_LIST_START
|
||||
ISC_TEST_ENTRY_CUSTOM(isc_rsa_verify, setup_test, teardown_test)
|
||||
ISC_TEST_ENTRY_CUSTOM(isc_rsa_fromdns_oversized_exponent, setup_test,
|
||||
teardown_test)
|
||||
ISC_TEST_LIST_END
|
||||
|
||||
ISC_TEST_MAIN
|
||||
|
|
|
|||
Loading…
Reference in a new issue