]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add PRIVATEOIDs for RSASHA256 and RSASHA512
authorMark Andrews <marka@isc.org>
Mon, 31 Mar 2025 13:12:52 +0000 (00:12 +1100)
committerMark Andrews <marka@isc.org>
Wed, 18 Jun 2025 21:15:20 +0000 (07:15 +1000)
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).

13 files changed:
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-ksr.c
bin/tests/system/conf.sh
bin/tests/system/dnssec/tests.sh
bin/tests/system/isctest/kasp.py
bin/tests/system/isctest/vars/algorithms.py
lib/dns/dst_api.c
lib/dns/dst_parse.c
lib/dns/include/dst/dst.h
lib/dns/kasp.c
lib/dns/opensslrsa_link.c
lib/dns/rcode.c
lib/isccfg/kaspconf.c

index 500b11fd033f38a517057af8480201fe4ea4ce15..c3e24a39e7e308bb4583b8b984280362e524986e 100644 (file)
@@ -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))
                {
index 14def7621935bee5017badfe0e13dedbda17bd73..ea96d41c11d5668eb04e26e782a40a0e142fe5e7 100644 (file)
@@ -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))
                {
index 86059196dd80b721f43cba81e5e36027a0fc4af4..dddf5dac20ffef9ac2750e97e4d34ecb2d6d5720 100644 (file)
@@ -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")
 
index 746dc57ed9beef421e81f4eddc30c559190d2f80..3d248469521f9e360703f23a5b227980e44eb3f0 100644 (file)
@@ -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
index e334ee3ac50137305860da907aeeb276bfa88141..86e05ebac97ea3c6be8ec0b2dd2321977dfc84a8 100644 (file)
@@ -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:
index 86741e14a2aa1416b11deee7172b18c8ef732c4b..58b5a9a652cbde716fd5d969f03685268333e055 100644 (file)
@@ -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] = []
index 4f8f9dc95831b094469e088ee093184257671a39..e3d70827066bd21457c0d5ef54f3e4fb47150093 100644 (file)
@@ -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;
 }
 
index b897407c41336923b064e652381cd4d7b7213d3e..5e53a19e4943990dfaff3d39949cda608ddbe9da 100644 (file)
@@ -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;
index 2e959461b48bcece15558a9892ad27058f655858..8ba5fe136005c7b37e4737869c653411eb565db6 100644 (file)
@@ -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 */
index f0b61fd499c6909419c6c36f8a2b9ec669503096..8fac378ce67d120494ad685c97d5cb27bc73719b 100644 (file)
@@ -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;
index bfeb7bba768b5108ed8ef6bd5cce853c8c5d69dc..e31ba6b15d9e7499d09673e7feb9396a66e4c48b 100644 (file)
@@ -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;
index 414a7915387c33484ab193db3c5c42ad59aa2354..133f49a99e7ec39712d0f76a649f2a276bedee1d 100644 (file)
 /*
  * PRIVATEOID subtypes we support.
  */
-#define PRIVATEOIDS /* currently empty */
+#define PRIVATEOIDS                                         \
+       { DST_ALG_RSASHA256PRIVATEOID, "RSASHA256OID", 0 }, \
+               { DST_ALG_RSASHA512PRIVATEOID, "RSASHA512OID", 0 },
 
 /* RFC2535 section 7.1 */
 
index 21e09b079e7b23564648562ad1b72395da3ac465..4b424d4bfb5114a8d2fce9278293054f84657bd4 100644 (file)
@@ -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 {