diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 500b11fd03..c3e24a39e7 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 14def76219..ea96d41c11 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 86059196dd..dddf5dac20 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 746dc57ed9..3d24846952 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 e334ee3ac5..86e05ebac9 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 86741e14a2..58b5a9a652 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 4f8f9dc958..e3d7082706 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 b897407c41..5e53a19e49 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 2e959461b4..8ba5fe1360 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 f0b61fd499..8fac378ce6 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 bfeb7bba76..e31ba6b15d 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 414a791538..133f49a99e 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 21e09b079e..4b424d4bfb 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 {