From: Mark Andrews Date: Mon, 31 Mar 2025 13:12:52 +0000 (+1100) Subject: Add PRIVATEOIDs for RSASHA256 and RSASHA512 X-Git-Tag: v9.21.10~47^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e687710dc7f0c215b1184f2cad56ecbfbc938b5f;p=thirdparty%2Fbind9.git Add PRIVATEOIDs for RSASHA256 and RSASHA512 Use the existing RSASHA256 and RSASHA512 implementation to provide working PRIVATEOID example implementations. We are using the OID values normally associated with RSASHA256 (1.2.840.113549.1.1.11) and RSASHA512 (1.2.840.113549.1.1.13). --- diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 500b11fd033..c3e24a39e7e 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -286,6 +286,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: case DST_ALG_ECDSA256: case DST_ALG_ECDSA384: case DST_ALG_ED25519: @@ -309,6 +311,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { FALLTHROUGH; case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: ctx->size = 2048; if (verbose > 0) { fprintf(stderr, @@ -462,6 +466,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { FALLTHROUGH; case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: if (ctx->size != 0 && (ctx->size < min_rsa || ctx->size > MAX_RSA)) { diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c index 14def762193..ea96d41c11d 100644 --- a/bin/dnssec/dnssec-ksr.c +++ b/bin/dnssec/dnssec-ksr.c @@ -356,6 +356,8 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey, FALLTHROUGH; case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: if (ksr->size != 0 && (ksr->size < min_rsa || ksr->size > MAX_RSA)) { diff --git a/bin/tests/system/conf.sh b/bin/tests/system/conf.sh index 86059196dd8..dddf5dac20f 100644 --- a/bin/tests/system/conf.sh +++ b/bin/tests/system/conf.sh @@ -212,6 +212,10 @@ private_type_record() { _algorithm=$2 _keyfile=$3 _secalg=$2 + case $_secalg in + 256) _secalg=254 ;; # RSASHA256OID + 257) _secalg=254 ;; # RSASHA512OID + esac _id=$(keyfile_to_key_id "$_keyfile") diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 746dc57ed9b..3d248469521 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -3481,7 +3481,7 @@ status=$((status + ret)) echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)" ret=0 alg=1 -until test $alg -eq 256; do +until test $alg -eq 258; do zone="keygen-$alg." case $alg in 2) # Diffie Helman @@ -3498,10 +3498,20 @@ until test $alg -eq 256; do 15 | 16) key1=$($KEYGEN -a "$alg" "$zone" 2>"keygen-$alg.err" || true) ;; + 256) + key1=$($KEYGEN -a "RSASHA256OID" "$zone" 2>"keygen-$alg.err" || true) + ;; + 257) + key1=$($KEYGEN -a "RSASHA512OID" "$zone" 2>"keygen-$alg.err" || true) + ;; *) key1=$($KEYGEN -a "$alg" "$zone" 2>"keygen-$alg.err" || true) ;; esac + if grep "unknown algorithm" "keygen-$alg.err" >/dev/null; then + alg=$((alg + 1)) + continue + fi if grep "unsupported algorithm" "keygen-$alg.err" >/dev/null; then alg=$((alg + 1)) continue diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index e334ee3ac50..86e05ebac97 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -392,6 +392,10 @@ class Key: def get_dnsalg(self) -> int: alg = int(self.get_metadata("Algorithm")) + if alg == isctest.vars.algorithms.RSASHA256OID.dst: + return isctest.vars.algorithms.RSASHA256OID.number + if alg == isctest.vars.algorithms.RSASHA512OID.dst: + return isctest.vars.algorithms.RSASHA512OID.number return alg def ttl(self) -> int: diff --git a/bin/tests/system/isctest/vars/algorithms.py b/bin/tests/system/isctest/vars/algorithms.py index 86741e14a2a..58b5a9a652c 100644 --- a/bin/tests/system/isctest/vars/algorithms.py +++ b/bin/tests/system/isctest/vars/algorithms.py @@ -83,6 +83,8 @@ ECDSAP256SHA256 = Algorithm("ECDSAP256SHA256", 13, 13, 256) ECDSAP384SHA384 = Algorithm("ECDSAP384SHA384", 14, 14, 384) ED25519 = Algorithm("ED25519", 15, 15, 256) ED448 = Algorithm("ED448", 16, 16, 456) +RSASHA256OID = Algorithm("RSASHA256OID", 254, 256, 2048) +RSASHA512OID = Algorithm("RSASHA512OID", 254, 257, 2048) ALL_ALGORITHMS = [ RSASHA1, @@ -92,6 +94,8 @@ ALL_ALGORITHMS = [ ECDSAP384SHA384, ED25519, ED448, + RSASHA256OID, + RSASHA512OID, ] ALL_ALGORITHMS_BY_NUM = {alg.number: alg for alg in ALL_ALGORITHMS} @@ -153,6 +157,8 @@ CRYPTO_SUPPORTED_VARS = { "ECDSAP384SHA384_SUPPORTED": "0", "ED25519_SUPPORTED": "0", "ED448_SUPPORTED": "0", + "RSASHA256OID_SUPPORTED": "0", + "RSASHA512OID_SUPPORTED": "0", } SUPPORTED_ALGORITHMS: List[Algorithm] = [] diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 4f8f9dc9583..e3d70827066 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -140,6 +140,14 @@ static const char *keystates[KEYSTATES_NVALUES] = { static dst_func_t *dst_t_func[DST_MAX_ALGS] = { 0 }; +/* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */ +static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b }; + +/* length byte + 1.2.840.113549.1.1.13 BER encoded RFC 4055 */ +static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d }; + void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); @@ -215,6 +223,18 @@ dst__lib_initialize(void) { #if HAVE_GSSAPI dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]); #endif /* HAVE_GSSAPI */ + /* + * RSASHA256 using assigned OID 1.2.840.113549.1.1.11 as + * a private OID example. + */ + dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256PRIVATEOID], + DST_ALG_RSASHA256PRIVATEOID); + /* + * RSASHA512 using assigned OID 1.2.840.113549.1.1.13 as + * a private OID example. + */ + dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512PRIVATEOID], + DST_ALG_RSASHA512PRIVATEOID); } void @@ -1311,6 +1331,12 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) { case DST_ALG_RSASHA512: *n = (key->key_size + 7) / 8; break; + case DST_ALG_RSASHA256PRIVATEOID: + *n = (key->key_size + 7) / 8 + sizeof(oid_rsasha256); + break; + case DST_ALG_RSASHA512PRIVATEOID: + *n = (key->key_size + 7) / 8 + sizeof(oid_rsasha512); + break; case DST_ALG_ECDSA256: *n = DNS_SIG_ECDSA256SIZE; break; @@ -2664,7 +2690,10 @@ dst_hmac_algorithm_totext(dst_algorithm_t alg) { dns_secalg_t dst_algorithm_tosecalg(dst_algorithm_t dst_alg) { - static dns_secalg_t dns_alg[DST_MAX_ALGS] = { 0 }; + static dns_secalg_t dns_alg[DST_MAX_ALGS] = { + [DST_ALG_RSASHA256PRIVATEOID] = DNS_KEYALG_PRIVATEOID, + [DST_ALG_RSASHA512PRIVATEOID] = DNS_KEYALG_PRIVATEOID, + }; if (dst_alg < 256) { return dst_alg; @@ -2703,8 +2732,19 @@ dst_algorithm_fromprivateoid(isc_buffer_t *buffer) { * length byte followed by the OID of that length. */ if (r.length > 0 && ((unsigned int)r.base[0] + 1) <= r.length) { - return 0; + if (r.base[0] + 1 == sizeof(oid_rsasha256) && + memcmp(oid_rsasha256, r.base, sizeof(oid_rsasha256)) == 0) + { + return DST_ALG_RSASHA256PRIVATEOID; + } + + if (r.base[0] + 1 == sizeof(oid_rsasha512) && + memcmp(oid_rsasha512, r.base, sizeof(oid_rsasha512)) == 0) + { + return DST_ALG_RSASHA512PRIVATEOID; + } } + return 0; } diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index b897407c413..5e53a19e494 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -332,6 +332,8 @@ check_data(const dst_private_t *priv, const unsigned int alg, bool old, case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: return check_rsa(priv, external); case DST_ALG_ECDSA256: case DST_ALG_ECDSA384: @@ -694,6 +696,12 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, case DST_ALG_HMACSHA512: fprintf(fp, "(HMAC_SHA512)\n"); break; + case DST_ALG_RSASHA256PRIVATEOID: + fprintf(fp, "(OID:RSASHA256)\n"); + break; + case DST_ALG_RSASHA512PRIVATEOID: + fprintf(fp, "(OID:RSASHA512)\n"); + break; default: fprintf(fp, "(?)\n"); break; diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 2e959461b48..8ba5fe13600 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -116,7 +116,9 @@ typedef enum dst_algorithm { /* * Put PRIVATE DNS and PRIVATE OID identifiers here. */ - DST_MAX_ALGS = 256, + DST_ALG_RSASHA256PRIVATEOID = 256, /* 1.2.840.113549.1.1.11 */ + DST_ALG_RSASHA512PRIVATEOID = 257, /* 1.2.840.113549.1.1.13 */ + DST_MAX_ALGS = 258, } dst_algorithm_t; /*% A buffer of this size is large enough to hold any key */ diff --git a/lib/dns/kasp.c b/lib/dns/kasp.c index f0b61fd499c..8fac378ce67 100644 --- a/lib/dns/kasp.c +++ b/lib/dns/kasp.c @@ -430,6 +430,8 @@ dns_kasp_key_size(dns_kasp_key_t *key) { case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: min = (key->algorithm == DST_ALG_RSASHA512) ? 1024 : 512; if (key->length > -1) { size = (unsigned int)key->length; diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index bfeb7bba768..e31ba6b15d9 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -50,6 +50,14 @@ typedef struct rsa_components { const BIGNUM *e, *n, *d, *p, *q, *dmp1, *dmq1, *iqmp; } rsa_components_t; +/* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */ +static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b }; + +/* length byte + 1.2.840.113549.1.1.13 BER encoded RFC 4055 */ +static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d }; + static isc_result_t opensslrsa_components_get(const dst_key_t *key, rsa_components_t *c, bool private) { @@ -154,6 +162,8 @@ opensslrsa_valid_key_alg(unsigned int key_alg) { case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: return true; default: return false; @@ -181,12 +191,14 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { } break; case DST_ALG_RSASHA256: + case DST_ALG_RSASHA256PRIVATEOID: /* From RFC 5702 */ if (dctx->key->key_size < 512 || dctx->key->key_size > 4096) { return ISC_R_FAILURE; } break; case DST_ALG_RSASHA512: + case DST_ALG_RSASHA512PRIVATEOID: /* From RFC 5702 */ if (dctx->key->key_size < 1024 || dctx->key->key_size > 4096) { return ISC_R_FAILURE; @@ -207,9 +219,11 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { type = isc__crypto_sha1; /* SHA1 + RSA */ break; case DST_ALG_RSASHA256: + case DST_ALG_RSASHA256PRIVATEOID: type = isc__crypto_sha256; /* SHA256 + RSA */ break; case DST_ALG_RSASHA512: + case DST_ALG_RSASHA512PRIVATEOID: type = isc__crypto_sha512; break; default: @@ -277,6 +291,12 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { * Account to the space the OIDs and DNS names consume. */ switch (key->key_alg) { + case DST_ALG_RSASHA256PRIVATEOID: + len = sizeof(oid_rsasha256); + break; + case DST_ALG_RSASHA512PRIVATEOID: + len = sizeof(oid_rsasha512); + break; } isc_buffer_availableregion(sig, &r); @@ -289,6 +309,14 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { * Add OID and DNS names to start of signature. */ switch (key->key_alg) { + case DST_ALG_RSASHA256PRIVATEOID: + isc_buffer_putmem(sig, oid_rsasha256, sizeof(oid_rsasha256)); + isc_region_consume(&r, sizeof(oid_rsasha256)); + break; + case DST_ALG_RSASHA512PRIVATEOID: + isc_buffer_putmem(sig, oid_rsasha512, sizeof(oid_rsasha512)); + isc_region_consume(&r, sizeof(oid_rsasha512)); + break; } if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) { @@ -348,6 +376,24 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { * Check identifying OID in front of public key material. */ switch (key->key_alg) { + case DST_ALG_RSASHA256PRIVATEOID: + if (length < sizeof(oid_rsasha256) || + memcmp(base, oid_rsasha256, sizeof(oid_rsasha256)) != 0) + { + return DST_R_VERIFYFAILURE; + } + base += sizeof(oid_rsasha256); + length -= sizeof(oid_rsasha256); + break; + case DST_ALG_RSASHA512PRIVATEOID: + if (length < sizeof(oid_rsasha512) || + memcmp(base, oid_rsasha512, sizeof(oid_rsasha512)) != 0) + { + return DST_R_VERIFYFAILURE; + } + base += sizeof(oid_rsasha512); + length -= sizeof(oid_rsasha512); + break; } status = EVP_VerifyFinal(evp_md_ctx, base, length, pkey); @@ -712,12 +758,14 @@ opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { } break; case DST_ALG_RSASHA256: + case DST_ALG_RSASHA256PRIVATEOID: /* From RFC 5702 */ if (key->key_size < 512 || key->key_size > 4096) { DST_RET(DST_R_INVALIDPARAM); } break; case DST_ALG_RSASHA512: + case DST_ALG_RSASHA512PRIVATEOID: /* From RFC 5702 */ if (key->key_size < 1024 || key->key_size > 4096) { DST_RET(DST_R_INVALIDPARAM); @@ -764,6 +812,20 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { * Add identifying OID and DNS names to front of public key material. */ switch (key->key_alg) { + case DST_ALG_RSASHA256PRIVATEOID: + if (r.length < sizeof(oid_rsasha256)) { + DST_RET(ISC_R_NOSPACE); + } + isc_buffer_putmem(data, oid_rsasha256, sizeof(oid_rsasha256)); + isc_region_consume(&r, sizeof(oid_rsasha256)); + break; + case DST_ALG_RSASHA512PRIVATEOID: + if (r.length < sizeof(oid_rsasha512)) { + DST_RET(ISC_R_NOSPACE); + } + isc_buffer_putmem(data, oid_rsasha512, sizeof(oid_rsasha512)); + isc_region_consume(&r, sizeof(oid_rsasha512)); + break; } ret = opensslrsa_components_get(key, &c, false); @@ -825,6 +887,24 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { * Check identifying OID in front of public key material. */ switch (key->key_alg) { + case DST_ALG_RSASHA256PRIVATEOID: + if (r.length < sizeof(oid_rsasha256) || + memcmp(r.base, oid_rsasha256, sizeof(oid_rsasha256)) != 0) + { + DST_RET(DST_R_INVALIDPUBLICKEY); + } + isc_region_consume(&r, sizeof(oid_rsasha256)); + isc_buffer_forward(data, sizeof(oid_rsasha256)); + break; + case DST_ALG_RSASHA512PRIVATEOID: + if (r.length < sizeof(oid_rsasha512) || + memcmp(r.base, oid_rsasha512, sizeof(oid_rsasha512)) != 0) + { + DST_RET(DST_R_INVALIDPUBLICKEY); + } + isc_region_consume(&r, sizeof(oid_rsasha512)); + isc_buffer_forward(data, sizeof(oid_rsasha512)); + break; } length = r.length; @@ -1264,11 +1344,13 @@ check_algorithm(unsigned short algorithm) { len = sizeof(sha1_sig) - 1; break; case DST_ALG_RSASHA256: + case DST_ALG_RSASHA256PRIVATEOID: type = isc__crypto_sha256; /* SHA256 + RSA */ sig = sha256_sig; len = sizeof(sha256_sig) - 1; break; case DST_ALG_RSASHA512: + case DST_ALG_RSASHA512PRIVATEOID: type = isc__crypto_sha512; sig = sha512_sig; len = sizeof(sha512_sig) - 1; diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c index 414a7915387..133f49a99e7 100644 --- a/lib/dns/rcode.c +++ b/lib/dns/rcode.c @@ -125,7 +125,9 @@ /* * PRIVATEOID subtypes we support. */ -#define PRIVATEOIDS /* currently empty */ +#define PRIVATEOIDS \ + { DST_ALG_RSASHA256PRIVATEOID, "RSASHA256OID", 0 }, \ + { DST_ALG_RSASHA512PRIVATEOID, "RSASHA512OID", 0 }, /* RFC2535 section 7.1 */ diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index 21e09b079e7..4b424d4bfb5 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -260,6 +260,8 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp, case DST_ALG_NSEC3RSASHA1: case DST_ALG_RSASHA256: case DST_ALG_RSASHA512: + case DST_ALG_RSASHA256PRIVATEOID: + case DST_ALG_RSASHA512PRIVATEOID: if (isc_crypto_fips_mode()) { min = 2048; } else {