2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

Check that we can verify a signature at initialisation time

Fedora 33 doesn't support RSASHA1 in future mode.  There is no easy
check for this other than by attempting to perform a verification
using known good signatures.  We don't attempt to sign with RSASHA1
as that would not work in FIPS mode.  RSASHA1 is verify only.

The test vectors were generated using OpenSSL 3.0 and
util/gen-rsa-sha-vectors.c.  Rerunning will generate a new set of
test vectors as the private key is not preserved.

e.g.
	cc util/gen-rsa-sha-vectors.c -I /opt/local/include \
		-L /opt/local/lib -lcrypto
This commit is contained in:
Mark Andrews
2022-03-22 16:16:57 +11:00
parent 33acff2c67
commit edfbe5c30f
2 changed files with 370 additions and 4 deletions

View File

@@ -1562,14 +1562,251 @@ static dst_func_t opensslrsa_functions = {
NULL, /*%< restore */
};
/*
* An RSA public key with 2048 bits
*/
static const unsigned char e_bytes[] = "\x01\x00\x01";
static const unsigned char n_bytes[] =
"\xc3\x90\x07\xbe\xf1\x85\xfc\x1a\x43\xb1\xa5\x15\xce\x71\x34\xfc\xc1"
"\x87\x27\x28\x38\xa4\xcf\x7c\x1a\x82\xa8\xdc\x04\x14\xd0\x3f\xb4\xfe"
"\x20\x4a\xdd\xd9\x0d\xd7\xcd\x61\x8c\xbd\x61\xa8\x10\xb5\x63\x1c\x29"
"\x15\xcb\x41\xee\x43\x91\x7f\xeb\xa5\x2c\xab\x81\x75\x0d\xa3\x3d\xe4"
"\xc8\x49\xb9\xca\x5a\x55\xa1\xbb\x09\xd1\xfb\xcd\xa2\xd2\x12\xa4\x85"
"\xdf\xa5\x65\xc9\x27\x2d\x8b\xd7\x8b\xfe\x6d\xc4\xd1\xd9\x83\x1c\x91"
"\x7d\x3d\xd0\xa4\xcd\xe1\xe7\xb9\x7a\x11\x38\xf9\x8b\x3c\xec\x30\xb6"
"\x36\xb9\x92\x64\x81\x56\x3c\xbc\xf9\x49\xfb\xba\x82\xb7\xa0\xfa\x65"
"\x79\x83\xb9\x4c\xa7\xfd\x53\x0b\x5a\xe4\xde\xf9\xfc\x38\x7e\xb5\x2c"
"\xa0\xc3\xb2\xfc\x7c\x38\xb0\x63\x50\xaf\x00\xaa\xb2\xad\x49\x54\x1e"
"\x8b\x11\x88\x9b\x6e\xae\x3b\x23\xa3\xdd\x53\x51\x80\x7a\x0b\x91\x4e"
"\x6d\x32\x01\xbd\x17\x81\x12\x64\x9f\x84\xae\x76\x53\x1a\x63\xa0\xda"
"\xcc\x45\x04\x72\xb0\xa7\xfb\xfa\x02\x39\x53\xc1\x83\x1f\x88\x54\x47"
"\x88\x63\x20\x71\x5d\xe2\xaa\x7c\x53\x39\x5e\x35\x25\xee\xe6\x5c\x15"
"\x5e\x14\xbe\x99\xde\x25\x19\xe7\x13\xdb\xce\xa3\xd3\x6c\x5c\xbb\x0e"
"\x6b";
static const unsigned char sha1_sig[] =
"\x69\x99\x89\x28\xe0\x38\x34\x91\x29\xb6\xac\x4b\xe9\x51\xbd\xbe\xc8"
"\x1a\x2d\xb6\xca\x99\xa3\x9f\x6a\x8b\x94\x5a\x51\x37\xd5\x8d\xae\x87"
"\xed\xbc\x8e\xb8\xa3\x60\x6b\xf6\xe6\x72\xfc\x26\x2a\x39\x2b\xfe\x88"
"\x1a\xa9\xd1\x93\xc7\xb9\xf8\xb6\x45\xa1\xf9\xa1\x56\x78\x7b\x00\xec"
"\x33\x83\xd4\x93\x25\x48\xb3\x50\x09\xd0\xbc\x7f\xac\x67\xc7\xa2\x7f"
"\xfc\xf6\x5a\xef\xf8\x5a\xad\x52\x74\xf5\x71\x34\xd9\x3d\x33\x8b\x4d"
"\x99\x64\x7e\x14\x59\xbe\xdf\x26\x8a\x67\x96\x6c\x1f\x79\x85\x10\x0d"
"\x7f\xd6\xa4\xba\x57\x41\x03\x71\x4e\x8c\x17\xd5\xc4\xfb\x4a\xbe\x66"
"\x45\x15\x45\x0c\x02\xe0\x10\xe1\xbb\x33\x8d\x90\x34\x3c\x94\xa4\x4c"
"\x7c\xd0\x5e\x90\x76\x80\x59\xb2\xfa\x54\xbf\xa9\x86\xb8\x84\x1e\x28"
"\x48\x60\x2f\x9e\xa4\xbc\xd4\x9c\x20\x27\x16\xac\x33\xcb\xcf\xab\x93"
"\x7a\x3b\x74\xa0\x18\x92\xa1\x4f\xfc\x52\x19\xee\x7a\x13\x73\xba\x36"
"\xaf\x78\x5d\xb6\x1f\x96\x76\x15\x73\xee\x04\xa8\x70\x27\xf7\xe7\xfa"
"\xe8\xf6\xc8\x5f\x4a\x81\x56\x0a\x94\xf3\xc6\x98\xd2\x93\xc4\x0b\x49"
"\x6b\x44\xd3\x73\xa2\xe3\xef\x5d\x9e\x68\xac\xa7\x42\xb1\xbb\x65\xbe"
"\x59";
static const unsigned char sha256_sig[] =
"\x0f\x8c\xdb\xe6\xb6\x21\xc8\xc5\x28\x76\x7d\xf6\xf2\x3b\x78\x47\x77"
"\x03\x34\xc5\x5e\xc0\xda\x42\x41\xc0\x0f\x97\xd3\xd0\x53\xa1\xd6\x87"
"\xe4\x16\x29\x9a\xa5\x59\xf4\x01\xad\xc9\x04\xe7\x61\xe2\xcb\x79\x73"
"\xce\xe0\xa6\x85\xe5\x10\x8c\x4b\xc5\x68\x3b\x96\x42\x3f\x56\xb3\x6d"
"\x89\xc4\xff\x72\x36\xf2\x3f\xed\xe9\xb8\xe3\xae\xab\x3c\xb7\xaa\xf7"
"\x1f\x8f\x26\x6b\xee\xc1\xac\x72\x89\x23\x8b\x7a\xd7\x8c\x84\xf3\xf5"
"\x97\xa8\x8d\xd3\xef\xb2\x5e\x06\x04\x21\xdd\x28\xa2\x28\x83\x68\x9b"
"\xac\x34\xdd\x36\x33\xda\xdd\xa4\x59\xc7\x5a\x4d\xf3\x83\x06\xd5\xc0"
"\x0d\x1f\x4f\x47\x2f\x9f\xcc\xc2\x0d\x21\x1e\x82\xb9\x3d\xf3\xa4\x1a"
"\xa6\xd8\x0e\x72\x1d\x71\x17\x1c\x54\xad\x37\x3e\xa4\x0e\x70\x86\x53"
"\xfb\x40\xad\xb9\x14\xf8\x8d\x93\xbb\xd7\xe7\x31\xce\xe0\x98\xda\x27"
"\x1c\x18\x8e\xd8\x85\xcb\xa7\xb1\x18\xac\x8c\xa8\x9d\xa9\xe2\xf6\x30"
"\x95\xa4\x81\xf4\x1c\xa0\x31\xd5\xc7\x9d\x28\x33\xee\x7f\x08\x4f\xcb"
"\xd1\x14\x17\xdf\xd0\x88\x78\x47\x29\xaf\x6c\xb2\x62\xa6\x30\x87\x29"
"\xaa\x80\x19\x7d\x2f\x05\xe3\x7e\x23\x73\x88\x08\xcc\xbd\x50\x46\x09"
"\x2a";
static const unsigned char sha512_sig[] =
"\x15\xda\x87\x87\x1f\x76\x08\xd3\x9d\x3a\xb9\xd2\x6a\x0e\x3b\x7d\xdd"
"\xec\x7d\xc4\x6d\x26\xf5\x04\xd3\x76\xc7\x83\xc4\x81\x69\x35\xe9\x47"
"\xbf\x49\xd1\xc0\xf9\x01\x4e\x0a\x34\x5b\xd0\xec\x6e\xe2\x2e\xe9\x2d"
"\x00\xfd\xe0\xa0\x28\x54\x53\x19\x49\x6d\xd2\x58\xb9\x47\xfa\x45\xad"
"\xd2\x1d\x52\xac\x80\xcb\xfc\x91\x97\x84\x58\x5f\xab\x21\x62\x60\x79"
"\xb8\x8a\x83\xe1\xf1\xcb\x05\x4c\x92\x56\x62\xd9\xbf\xa7\x81\x34\x23"
"\xdf\xd7\xa7\xc4\xdf\xde\x96\x00\x57\x4b\x78\x85\xb9\x3b\xdd\x3f\x98"
"\x88\x59\x1d\x48\xcf\x5a\xa8\xb7\x2a\x8b\x77\x93\x8e\x38\x3a\x0c\xa7"
"\x8a\x5f\xe6\x9f\xcb\xf0\x9a\x6b\xb6\x91\x04\x8b\x69\x6a\x37\xee\xa2"
"\xad\x5f\x31\x20\x96\xd6\x51\x80\xbf\x62\x48\xb8\xe4\x94\x10\x86\x4e"
"\xf2\x22\x1e\xa4\xd5\x54\xfe\xe1\x35\x49\xaf\xf8\x62\xfc\x11\xeb\xf7"
"\x3d\xd5\x5e\xaf\x11\xbd\x3d\xa9\x3a\x9f\x7f\xe8\xb4\x0d\xa2\xbb\x1c"
"\xbd\x4c\xed\x9e\x81\xb1\xec\xd3\xea\xaa\x03\xe3\x14\xdf\x8c\xb3\x78"
"\x85\x5e\x87\xad\xec\x41\x1a\xa9\x4f\xd2\xe6\xc6\xbe\xfa\xb8\x10\xea"
"\x74\x25\x36\x0c\x23\xe2\x24\xb7\x21\xb7\x0d\xaf\xf6\xb4\x31\xf5\x75"
"\xf1";
static isc_result_t
check_algorithm(unsigned char algorithm) {
BIGNUM *n = NULL, *e = NULL;
EVP_MD_CTX *evp_md_ctx = EVP_MD_CTX_create();
EVP_PKEY *pkey = NULL;
const EVP_MD *type = NULL;
const unsigned char *sig = NULL;
int status;
isc_result_t ret = ISC_R_SUCCESS;
size_t len;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
RSA *rsa = NULL;
#else
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = NULL;
EVP_PKEY_CTX *ctx = NULL;
#endif
if (evp_md_ctx == NULL) {
DST_RET(ISC_R_NOMEMORY);
}
switch (algorithm) {
case DST_ALG_RSASHA1:
case DST_ALG_NSEC3RSASHA1:
type = EVP_sha1(); /* SHA1 + RSA */
sig = sha1_sig;
len = sizeof(sha1_sig) - 1;
break;
case DST_ALG_RSASHA256:
type = EVP_sha256(); /* SHA256 + RSA */
sig = sha256_sig;
len = sizeof(sha256_sig) - 1;
break;
case DST_ALG_RSASHA512:
type = EVP_sha512();
sig = sha512_sig;
len = sizeof(sha512_sig) - 1;
break;
default:
DST_RET(ISC_R_NOTIMPLEMENTED);
}
if (type == NULL) {
DST_RET(ISC_R_NOTIMPLEMENTED);
}
/*
* Construct pkey.
*/
e = BN_bin2bn(e_bytes, sizeof(e_bytes) - 1, NULL);
n = BN_bin2bn(n_bytes, sizeof(n_bytes) - 1, NULL);
if (e == NULL || n == NULL) {
DST_RET(ISC_R_NOMEMORY);
}
#if OPENSSL_VERSION_NUMBER < 0x30000000L
rsa = RSA_new();
if (rsa == NULL) {
DST_RET(dst__openssl_toresult2("RSA_new",
DST_R_OPENSSLFAILURE));
}
status = RSA_set0_key(rsa, n, e, NULL);
if (status != 1) {
DST_RET(dst__openssl_toresult2("RSA_set0_key",
DST_R_OPENSSLFAILURE));
}
/* These are now managed by OpenSSL. */
n = NULL;
e = NULL;
pkey = EVP_PKEY_new();
if (pkey == NULL) {
DST_RET(dst__openssl_toresult2("EVP_PKEY_new",
DST_R_OPENSSLFAILURE));
}
status = EVP_PKEY_set1_RSA(pkey, rsa);
if (status != 1) {
DST_RET(dst__openssl_toresult2("EVP_PKEY_set1_RSA",
DST_R_OPENSSLFAILURE));
}
#else
bld = OSSL_PARAM_BLD_new();
if (bld == NULL) {
DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_new",
DST_R_OPENSSLFAILURE));
}
if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n) != 1 ||
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e) != 1)
{
DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
DST_R_OPENSSLFAILURE));
}
params = OSSL_PARAM_BLD_to_param(bld);
if (params == NULL) {
DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_to_param",
DST_R_OPENSSLFAILURE));
}
ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
if (ctx == NULL) {
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
DST_R_OPENSSLFAILURE));
}
status = EVP_PKEY_fromdata_init(ctx);
if (status != 1) {
DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
DST_R_OPENSSLFAILURE));
}
status = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params);
if (status != 1 || pkey == NULL) {
DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata",
DST_R_OPENSSLFAILURE));
}
#endif
/*
* Check that we can verify the signature.
*/
if (EVP_DigestInit_ex(evp_md_ctx, type, NULL) != 1 ||
EVP_DigestUpdate(evp_md_ctx, "test", 4) != 1 ||
EVP_VerifyFinal(evp_md_ctx, sig, len, pkey) != 1)
{
DST_RET(ISC_R_NOTIMPLEMENTED);
}
err:
BN_free(e);
BN_free(n);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
if (rsa != NULL) {
RSA_free(rsa);
}
#else
if (bld != NULL) {
OSSL_PARAM_BLD_free(bld);
}
if (ctx != NULL) {
EVP_PKEY_CTX_free(ctx);
}
if (params != NULL) {
OSSL_PARAM_free(params);
}
#endif
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
if (evp_md_ctx != NULL) {
EVP_MD_CTX_destroy(evp_md_ctx);
}
ERR_clear_error();
return (ret);
}
isc_result_t
dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) {
isc_result_t result;
REQUIRE(funcp != NULL);
UNUSED(algorithm);
result = check_algorithm(algorithm);
if (*funcp == NULL) {
*funcp = &opensslrsa_functions;
if (result == ISC_R_SUCCESS) {
if (*funcp == NULL) {
*funcp = &opensslrsa_functions;
}
} else if (result == ISC_R_NOTIMPLEMENTED) {
result = ISC_R_SUCCESS;
}
return (ISC_R_SUCCESS);
return (result);
}

129
util/gen-rsa-sha-vectors.c Normal file
View File

@@ -0,0 +1,129 @@
/*
* 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 <stdio.h>
#include <openssl/bn.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
#include <openssl/param_build.h>
#include <openssl/rsa.h>
/*
* Generate test vectors for lib/dns/opensslrsa_link.c as:
*
* Fedora 33 doesn't support RSASHA1 in future mode. There is no easy
* check for this other than by attempting to perform a verification
* using known good signatures. We don't attempt to sign with RSASHA1
* as that would not work in FIPS mode. RSASHA1 is verify only.
*
* The test vectors were generated using OpenSSL 3.0 and
* util/gen-rsa-sha-vectors.c. Rerunning will generate a new set of
* test vectors as the private key is not preserved.
*
* e.g.
* cc util/gen-rsa-sha-vectors.c -I /opt/local/include \
* -L /opt/local/lib -lcrypto
*/
int
main() {
BIGNUM *e = BN_new();
BIGNUM *n = BN_new();
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
EVP_PKEY *pkey = NULL;
unsigned char buf[512];
size_t bytes;
EVP_MD_CTX *evp_md_ctx = EVP_MD_CTX_create();
unsigned int siglen = sizeof(buf);
if (e == NULL || n == NULL || ctx == NULL || evp_md_ctx == NULL) {
return (1);
}
BN_set_bit(e, 0);
BN_set_bit(e, 16);
if (EVP_PKEY_keygen_init(ctx) != 1 ||
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) != 1 ||
EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) != 1 ||
EVP_PKEY_keygen(ctx, &pkey) != 1 || pkey == NULL)
{
return (1);
}
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n);
if (n == NULL) {
return (1);
}
bytes = BN_num_bytes(e);
BN_bn2bin(e, buf);
printf("unsigned char e_bytes[] = \"");
for (size_t i = 0; i < bytes; i++) {
printf("\\x%02x", buf[i]);
}
printf("\";\n");
bytes = BN_num_bytes(n);
BN_bn2bin(n, buf);
printf("unsigned char n_bytes[] = \"");
for (size_t i = 0; i < bytes; i++) {
printf("\\x%02x", buf[i]);
}
printf("\";\n\n");
if (EVP_DigestInit_ex(evp_md_ctx, EVP_sha1(), NULL) != 1 ||
EVP_DigestUpdate(evp_md_ctx, "test", 4) != 1 ||
EVP_SignFinal(evp_md_ctx, buf, &siglen, pkey) != 1)
{
return (1);
}
bytes = siglen;
printf("unsigned char sha1_sig[] = \"");
for (size_t i = 0; i < bytes; i++) {
printf("\\x%02x", buf[i]);
}
printf("\";\n\n");
if (EVP_DigestInit_ex(evp_md_ctx, EVP_sha256(), NULL) != 1 ||
EVP_DigestUpdate(evp_md_ctx, "test", 4) != 1 ||
EVP_SignFinal(evp_md_ctx, buf, &siglen, pkey) != 1)
{
return (1);
}
bytes = siglen;
printf("unsigned char sha256_sig[] = \"");
for (size_t i = 0; i < bytes; i++) {
printf("\\x%02x", buf[i]);
}
printf("\";\n\n");
if (EVP_DigestInit_ex(evp_md_ctx, EVP_sha512(), NULL) != 1 ||
EVP_DigestUpdate(evp_md_ctx, "test", 4) != 1 ||
EVP_SignFinal(evp_md_ctx, buf, &siglen, pkey) != 1)
{
return (1);
}
bytes = siglen;
printf("unsigned char sha512_sig[] = \"");
for (size_t i = 0; i < bytes; i++) {
printf("\\x%02x", buf[i]);
}
printf("\";\n\n");
return (0);
}