Commit e0ca243a93 for bind
commit e0ca243a937d3a5cb9503d6197eb266e495b7a4e
Author: Martin Basti <mbasti@isc.org>
Date: Mon Sep 7 13:20:50 2026 +0000
Fix the minimum RSA key length check in dnssec-policy
The non-FIPS minimum key length for RSA algorithms was computed as
"DST_ALG_RSASHA512 ? 1024 : 512", testing the constant instead of the
key's algorithm, so the intended 512-bit floor was unreachable and
1024 was always enforced. Compare the algorithm instead: 1024 for the
RSASHA512 based algorithms and 512 for the other RSA algorithms,
matching the limits dnssec-keygen enforces.
Assisted-by: Claude:claude-fable-5
diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c
index 297fa2ed0d..3156bb13a7 100644
--- a/lib/isccfg/kaspconf.c
+++ b/lib/isccfg/kaspconf.c
@@ -327,8 +327,14 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
case DST_ALG_RSASHA512PRIVATEOID:
if (isc_crypto_fips_mode()) {
min = 2048;
+ } else if (key->algorithm ==
+ DST_ALG_RSASHA512 ||
+ key->algorithm ==
+ DST_ALG_RSASHA512PRIVATEOID)
+ {
+ min = 1024;
} else {
- min = DST_ALG_RSASHA512 ? 1024 : 512;
+ min = 512;
}
if (size < min || size > 4096) {
if (log_errors) {
diff --git a/tests/isccfg/kaspconf_test.c b/tests/isccfg/kaspconf_test.c
new file mode 100644
index 0000000000..f3d1f99a18
--- /dev/null
+++ b/tests/isccfg/kaspconf_test.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <sched.h> /* IWYU pragma: keep */
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define UNIT_TESTING
+#include <cmocka.h>
+
+#include <isc/buffer.h>
+#include <isc/crypto.h>
+#include <isc/lib.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/kasp.h>
+#include <dns/keystore.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/kaspconf.h>
+#include <isccfg/namedconf.h>
+
+#include <tests/isc.h>
+
+ISC_SETUP_TEST_IMPL(group) {
+ isc_logconfig_t *logconfig = isc_logconfig_get();
+ isc_log_createandusechannel(
+ logconfig, "default_stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, ISC_LOGDESTINATION_STDERR, 0,
+ ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_DEFAULT);
+
+ return 0;
+}
+
+/* Parse a dnssec-policy statement and configure a kasp from it. */
+static isc_result_t
+kasp_fromtext(const char *conftext) {
+ isc_result_t result;
+ isc_buffer_t b;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *kasps = NULL;
+ dns_kasp_t *kasp = NULL;
+ dns_kasplist_t kasplist;
+ dns_keystorelist_t keystores;
+
+ ISC_LIST_INIT(kasplist);
+ ISC_LIST_INIT(keystores);
+
+ /* Add default key-store "key-directory". */
+ result = cfg_keystore_fromconfig(NULL, isc_g_mctx, &keystores, NULL);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ isc_buffer_constinit(&b, conftext, strlen(conftext));
+ isc_buffer_add(&b, strlen(conftext));
+ result = cfg_parse_buffer(&b, "text", 0, &cfg_type_namedconf, 0,
+ &config);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = cfg_map_get(config, "dnssec-policy", &kasps);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = cfg_kasp_fromconfig(cfg_listelt_value(cfg_list_first(kasps)),
+ NULL, 0, isc_g_mctx, &keystores, &kasplist,
+ &kasp);
+ if (kasp != NULL) {
+ dns_kasp_detach(&kasp);
+ }
+
+ ISC_LIST_FOREACH(kasplist, k, link) {
+ ISC_LIST_UNLINK(kasplist, k, link);
+ dns_kasp_detach(&k);
+ }
+ ISC_LIST_FOREACH(keystores, ks, link) {
+ ISC_LIST_UNLINK(keystores, ks, link);
+ dns_keystore_detach(&ks);
+ }
+ cfg_obj_detach(&config);
+
+ return result;
+}
+
+#define CSK_POLICY(alg) \
+ "dnssec-policy \"p\" {\n" \
+ " keys {\n" \
+ " csk lifetime unlimited algorithm " alg ";\n" \
+ " };\n" \
+ "};\n"
+
+ISC_RUN_TEST_IMPL(kaspkey_rsa_length) {
+ struct {
+ const char *conftext;
+ isc_result_t expected;
+ } testcases[] = {
+ /* The minimum for RSASHA512 based algorithms is 1024... */
+ { CSK_POLICY("rsasha512 512"), ISC_R_RANGE },
+ { CSK_POLICY("rsasha512 1024"), ISC_R_SUCCESS },
+ { CSK_POLICY("rsasha512oid 512"), ISC_R_RANGE },
+ { CSK_POLICY("rsasha512oid 1024"), ISC_R_SUCCESS },
+ /* ...but 512 for the other RSA algorithms. */
+ { CSK_POLICY("rsasha256 512"), ISC_R_SUCCESS },
+ { CSK_POLICY("rsasha256 511"), ISC_R_RANGE },
+ { CSK_POLICY("rsasha256oid 512"), ISC_R_SUCCESS },
+ { CSK_POLICY("rsasha1 512"), ISC_R_SUCCESS },
+ /* The maximum is 4096 for all of them. */
+ { CSK_POLICY("rsasha256 4097"), ISC_R_RANGE },
+ };
+
+ if (isc_crypto_fips_mode()) {
+ skip();
+ return;
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
+ isc_result_t result = kasp_fromtext(testcases[i].conftext);
+ assert_int_equal(result, testcases[i].expected);
+ }
+}
+
+ISC_TEST_LIST_START
+ISC_TEST_ENTRY(kaspkey_rsa_length)
+ISC_TEST_LIST_END
+
+ISC_TEST_MAIN_CUSTOM(setup_test_group, NULL)
diff --git a/tests/isccfg/meson.build b/tests/isccfg/meson.build
index 66adda5ccd..741fa4fa7a 100644
--- a/tests/isccfg/meson.build
+++ b/tests/isccfg/meson.build
@@ -12,6 +12,7 @@
isccfg_tests = [
'duration',
'grammar',
+ 'kaspconf',
'parser',
]
@@ -32,6 +33,7 @@ foreach unit : isccfg_tests
sources: default_sanitize_options,
dependencies: [
libisc_dep,
+ libdns_dep,
libisccfg_dep,
libtest_dep,