From: Ondřej Surý Date: Wed, 29 Apr 2026 14:23:10 +0000 (+0200) Subject: Size HMAC key generation buffers to the maximum block size X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=141f278a03c7963da2d0fa1b586f297b15252b8a;p=thirdparty%2Fbind9.git Size HMAC key generation buffers to the maximum block size hmac_generate() declared its on-stack nonce buffer as unsigned char data[ISC_MAX_MD_SIZE], i.e. 64 bytes. That is the maximum digest size, but the buffer is filled up to the algorithm's HMAC block size, which is 128 bytes for SHA-384 and SHA-512. Asking rndc-confgen for an HMAC-SHA-384 or HMAC-SHA-512 key with -b > 512 (the documented range allows up to 1024) wrote past the end of the stack buffer; on hardened builds this aborted with a stack-smash detector firing instead of producing a key. Use the existing ISC_MAX_BLOCK_SIZE (128) for the buffer so the full 1..1024 range advertised by -A hmac-sha{384,512} works as documented. The matching key_rawsecret[64] in confgen's generate_key() is enlarged the same way so the generated key fits when dumped to the buffer. Add a system test that exercises rndc-confgen across the previously overflowing keysizes; with -Db_sanitize=address it caught the abort before the fix. Assisted-by: Claude:claude-opus-4-7 (cherry picked from commit 46f6bb6364db1dcbbfb2a2add72cff45fd1bda22) --- diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c index c8832b5c4e0..c5cce21a57c 100644 --- a/bin/confgen/keygen.c +++ b/bin/confgen/keygen.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -97,7 +98,7 @@ generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize, isc_result_t result = ISC_R_SUCCESS; isc_buffer_t key_rawbuffer; isc_region_t key_rawregion; - char key_rawsecret[64]; + char key_rawsecret[ISC_MAX_BLOCK_SIZE]; dst_key_t *key = NULL; switch (alg) { diff --git a/bin/tests/system/rndc_confgen/tests_rndc_confgen.py b/bin/tests/system/rndc_confgen/tests_rndc_confgen.py new file mode 100644 index 00000000000..585e933e792 --- /dev/null +++ b/bin/tests/system/rndc_confgen/tests_rndc_confgen.py @@ -0,0 +1,48 @@ +# 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. + +import base64 +import os +import re + +import pytest + +import isctest + + +def _extract_secret(stdout: bytes) -> bytes: + match = re.search(rb'secret\s+"([^"]+)"', stdout) + assert match is not None, f"no secret in output: {stdout!r}" + return base64.b64decode(match.group(1)) + + +@pytest.mark.parametrize( + "algorithm,bits", + [ + ("hmac-sha256", 1), + ("hmac-sha256", 256), + ("hmac-sha256", 512), + ("hmac-sha384", 1), + ("hmac-sha384", 384), + ("hmac-sha384", 513), + ("hmac-sha384", 768), + ("hmac-sha384", 1024), + ("hmac-sha512", 1), + ("hmac-sha512", 512), + ("hmac-sha512", 513), + ("hmac-sha512", 1024), + ], +) +def test_rndc_confgen_hmac_keysize(algorithm, bits): + cmd = isctest.run.cmd([os.environ["RNDCCONFGEN"], "-A", algorithm, "-b", str(bits)]) + secret = _extract_secret(cmd.proc.stdout) + assert len(secret) == (bits + 7) // 8 + assert f"algorithm {algorithm};".encode() in cmd.proc.stdout diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c index 07c3090de9d..60ad0de6329 100644 --- a/lib/dns/hmac_link.c +++ b/lib/dns/hmac_link.c @@ -280,7 +280,7 @@ hmac_generate(const isc_md_type_t *type, dst_key_t *key) { isc_buffer_t b; isc_result_t ret; unsigned int bytes, len; - unsigned char data[ISC_MAX_MD_SIZE] = { 0 }; + unsigned char data[ISC_MAX_BLOCK_SIZE] = { 0 }; len = isc_md_type_get_block_size(type);