]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
OpenSSL EDDSA introduce and use openssleddsa_alg_info()
authorTimo Teräs <timo.teras@iki.fi>
Sat, 28 Jan 2023 10:53:14 +0000 (12:53 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 8 Mar 2023 12:50:46 +0000 (13:50 +0100)
Move the common code into a helper function that returns the EDDSA
parameters (pkey type, nid, keysize, sigsize).

lib/dns/openssleddsa_link.c

index f89672b26e125019b70c02405b7915a7bf8c6f5c..331292f01581691349c176774631535f80905d61 100644 (file)
 #endif /* ifndef NID_ED448 */
 #endif /* HAVE_OPENSSL_ED448 */
 
-static isc_result_t
-raw_key_to_ossl(unsigned int key_alg, int private, const unsigned char *key,
-               size_t *key_len, EVP_PKEY **pkey) {
-       isc_result_t ret;
-       int pkey_type = EVP_PKEY_NONE;
-       size_t len = 0;
+typedef struct eddsa_alginfo {
+       int pkey_type, nid;
+       unsigned int key_size, sig_size;
+} eddsa_alginfo_t;
 
+static const eddsa_alginfo_t *
+openssleddsa_alg_info(unsigned int key_alg) {
 #if HAVE_OPENSSL_ED25519
        if (key_alg == DST_ALG_ED25519) {
-               pkey_type = EVP_PKEY_ED25519;
-               len = DNS_KEY_ED25519SIZE;
+               static const eddsa_alginfo_t ed25519_alginfo = {
+                       .pkey_type = EVP_PKEY_ED25519,
+                       .nid = NID_ED25519,
+                       .key_size = DNS_KEY_ED25519SIZE,
+                       .sig_size = DNS_SIG_ED25519SIZE,
+               };
+               return &ed25519_alginfo;
        }
 #endif /* HAVE_OPENSSL_ED25519 */
 #if HAVE_OPENSSL_ED448
        if (key_alg == DST_ALG_ED448) {
-               pkey_type = EVP_PKEY_ED448;
-               len = DNS_KEY_ED448SIZE;
+               static const eddsa_alginfo_t ed448_alginfo = {
+                       .pkey_type = EVP_PKEY_ED448,
+                       .nid = NID_ED448,
+                       .key_size = DNS_KEY_ED448SIZE,
+                       .sig_size = DNS_SIG_ED448SIZE,
+               };
+               return &ed448_alginfo;
        }
 #endif /* HAVE_OPENSSL_ED448 */
-       if (pkey_type == EVP_PKEY_NONE) {
-               return (ISC_R_NOTIMPLEMENTED);
-       }
+       return NULL;
+}
+
+static isc_result_t
+raw_key_to_ossl(const eddsa_alginfo_t *alginfo, int private,
+               const unsigned char *key, size_t *key_len, EVP_PKEY **pkey) {
+       isc_result_t ret;
+       int pkey_type = alginfo->pkey_type;
+       size_t len = alginfo->key_size;
 
        ret = (private ? DST_R_INVALIDPRIVATEKEY : DST_R_INVALIDPUBLICKEY);
        if (*key_len < len) {
@@ -104,10 +120,11 @@ openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
 static isc_result_t
 openssleddsa_createctx(dst_key_t *key, dst_context_t *dctx) {
        isc_buffer_t *buf = NULL;
+       const eddsa_alginfo_t *alginfo =
+               openssleddsa_alg_info(dctx->key->key_alg);
 
        UNUSED(key);
-       REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
-               dctx->key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        isc_buffer_allocate(dctx->mctx, &buf, 64);
        dctx->ctxdata.generic = buf;
@@ -118,9 +135,10 @@ openssleddsa_createctx(dst_key_t *key, dst_context_t *dctx) {
 static void
 openssleddsa_destroyctx(dst_context_t *dctx) {
        isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
+       const eddsa_alginfo_t *alginfo =
+               openssleddsa_alg_info(dctx->key->key_alg);
 
-       REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
-               dctx->key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
        if (buf != NULL) {
                isc_buffer_free(&buf);
        }
@@ -134,9 +152,10 @@ openssleddsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
        isc_region_t r;
        unsigned int length;
        isc_result_t result;
+       const eddsa_alginfo_t *alginfo =
+               openssleddsa_alg_info(dctx->key->key_alg);
 
-       REQUIRE(dctx->key->key_alg == DST_ALG_ED25519 ||
-               dctx->key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        result = isc_buffer_copyregion(buf, data);
        if (result == ISC_R_SUCCESS) {
@@ -163,21 +182,16 @@ openssleddsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
        EVP_PKEY *pkey = key->keydata.pkey;
        EVP_MD_CTX *ctx = EVP_MD_CTX_new();
        isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        size_t siglen;
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        if (ctx == NULL) {
                return (ISC_R_NOMEMORY);
        }
 
-       if (key->key_alg == DST_ALG_ED25519) {
-               siglen = DNS_SIG_ED25519SIZE;
-       } else {
-               siglen = DNS_SIG_ED448SIZE;
-       }
-
+       siglen = alginfo->sig_size;
        isc_buffer_availableregion(sig, &sigreg);
        if (sigreg.length < (unsigned int)siglen) {
                DST_RET(ISC_R_NOSPACE);
@@ -215,30 +229,15 @@ openssleddsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
        EVP_PKEY *pkey = key->keydata.pkey;
        EVP_MD_CTX *ctx = EVP_MD_CTX_new();
        isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
-       unsigned int siglen = 0;
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        if (ctx == NULL) {
                return (ISC_R_NOMEMORY);
        }
 
-#if HAVE_OPENSSL_ED25519
-       if (key->key_alg == DST_ALG_ED25519) {
-               siglen = DNS_SIG_ED25519SIZE;
-       }
-#endif /* if HAVE_OPENSSL_ED25519 */
-#if HAVE_OPENSSL_ED448
-       if (key->key_alg == DST_ALG_ED448) {
-               siglen = DNS_SIG_ED448SIZE;
-       }
-#endif /* if HAVE_OPENSSL_ED448 */
-       if (siglen == 0) {
-               DST_RET(ISC_R_NOTIMPLEMENTED);
-       }
-
-       if (sig->length != siglen) {
+       if (sig->length != alginfo->sig_size) {
                DST_RET(DST_R_VERIFYFAILURE);
        }
 
@@ -249,7 +248,7 @@ openssleddsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
                        dctx->category, "EVP_DigestVerifyInit", ISC_R_FAILURE));
        }
 
-       status = EVP_DigestVerify(ctx, sig->base, siglen, tbsreg.base,
+       status = EVP_DigestVerify(ctx, sig->base, sig->length, tbsreg.base,
                                  tbsreg.length);
 
        switch (status) {
@@ -297,30 +296,14 @@ openssleddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
        isc_result_t ret;
        EVP_PKEY *pkey = NULL;
        EVP_PKEY_CTX *ctx = NULL;
-       int nid = 0, status;
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
+       int status;
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
        UNUSED(unused);
        UNUSED(callback);
 
-#if HAVE_OPENSSL_ED25519
-       if (key->key_alg == DST_ALG_ED25519) {
-               nid = NID_ED25519;
-               key->key_size = DNS_KEY_ED25519SIZE * 8;
-       }
-#endif /* if HAVE_OPENSSL_ED25519 */
-#if HAVE_OPENSSL_ED448
-       if (key->key_alg == DST_ALG_ED448) {
-               nid = NID_ED448;
-               key->key_size = DNS_KEY_ED448SIZE * 8;
-       }
-#endif /* if HAVE_OPENSSL_ED448 */
-       if (nid == 0) {
-               return (ISC_R_NOTIMPLEMENTED);
-       }
-
-       ctx = EVP_PKEY_CTX_new_id(nid, NULL);
+       ctx = EVP_PKEY_CTX_new_id(alginfo->nid, NULL);
        if (ctx == NULL) {
                return (dst__openssl_toresult2("EVP_PKEY_CTX_new_id",
                                               DST_R_OPENSSLFAILURE));
@@ -338,6 +321,7 @@ openssleddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
                                               DST_R_OPENSSLFAILURE));
        }
 
+       key->key_size = alginfo->key_size * 8;
        key->keydata.pkey = pkey;
        ret = ISC_R_SUCCESS;
 
@@ -376,20 +360,15 @@ openssleddsa_destroy(dst_key_t *key) {
 
 static isc_result_t
 openssleddsa_todns(const dst_key_t *key, isc_buffer_t *data) {
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        EVP_PKEY *pkey = key->keydata.pkey;
        isc_region_t r;
        size_t len;
 
        REQUIRE(pkey != NULL);
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
-
-       if (key->key_alg == DST_ALG_ED25519) {
-               len = DNS_KEY_ED25519SIZE;
-       } else {
-               len = DNS_KEY_ED448SIZE;
-       }
+       REQUIRE(alginfo != NULL);
 
+       len = alginfo->key_size;
        isc_buffer_availableregion(data, &r);
        if (r.length < len) {
                return (ISC_R_NOSPACE);
@@ -405,13 +384,13 @@ openssleddsa_todns(const dst_key_t *key, isc_buffer_t *data) {
 
 static isc_result_t
 openssleddsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        isc_result_t ret;
        isc_region_t r;
        size_t len;
        EVP_PKEY *pkey;
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        isc_buffer_remainingregion(data, &r);
        if (r.length == 0) {
@@ -419,7 +398,7 @@ openssleddsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
        }
 
        len = r.length;
-       ret = raw_key_to_ossl(key->key_alg, 0, r.base, &len, &pkey);
+       ret = raw_key_to_ossl(alginfo, 0, r.base, &len, &pkey);
        if (ret != ISC_R_SUCCESS) {
                return ret;
        }
@@ -432,14 +411,14 @@ openssleddsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
 
 static isc_result_t
 openssleddsa_tofile(const dst_key_t *key, const char *directory) {
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        isc_result_t ret;
        dst_private_t priv;
        unsigned char *buf = NULL;
        size_t len;
        int i;
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        if (key->keydata.pkey == NULL) {
                return (DST_R_NULLKEY);
@@ -453,11 +432,7 @@ openssleddsa_tofile(const dst_key_t *key, const char *directory) {
        i = 0;
 
        if (openssleddsa_isprivate(key)) {
-               if (key->key_alg == DST_ALG_ED25519) {
-                       len = DNS_KEY_ED25519SIZE;
-               } else {
-                       len = DNS_KEY_ED448SIZE;
-               }
+               len = alginfo->key_size;
                buf = isc_mem_get(key->mctx, len);
                if (EVP_PKEY_get_raw_private_key(key->keydata.pkey, buf,
                                                 &len) != 1)
@@ -507,6 +482,7 @@ eddsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) {
 
 static isc_result_t
 openssleddsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        dst_private_t priv;
        isc_result_t ret;
        int i, privkey_index = -1;
@@ -515,8 +491,7 @@ openssleddsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        size_t len;
        isc_mem_t *mctx = key->mctx;
 
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
+       REQUIRE(alginfo != NULL);
 
        /* read private key file */
        ret = dst__privstruct_parse(key, DST_ALG_ED25519, lexer, mctx, &priv);
@@ -574,8 +549,8 @@ openssleddsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        }
 
        len = priv.elements[privkey_index].length;
-       ret = raw_key_to_ossl(key->key_alg, 1,
-                             priv.elements[privkey_index].data, &len, &pkey);
+       ret = raw_key_to_ossl(alginfo, 1, priv.elements[privkey_index].data,
+                             &len, &pkey);
        if (ret != ISC_R_SUCCESS) {
                goto err;
        }
@@ -597,29 +572,13 @@ static isc_result_t
 openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
                       const char *pin) {
 #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
+       const eddsa_alginfo_t *alginfo = openssleddsa_alg_info(key->key_alg);
        isc_result_t ret;
        ENGINE *e;
        EVP_PKEY *pkey = NULL, *pubpkey = NULL;
-       int baseid = EVP_PKEY_NONE;
 
        UNUSED(pin);
-
-       REQUIRE(key->key_alg == DST_ALG_ED25519 ||
-               key->key_alg == DST_ALG_ED448);
-
-#if HAVE_OPENSSL_ED25519
-       if (key->key_alg == DST_ALG_ED25519) {
-               baseid = EVP_PKEY_ED25519;
-       }
-#endif /* if HAVE_OPENSSL_ED25519 */
-#if HAVE_OPENSSL_ED448
-       if (key->key_alg == DST_ALG_ED448) {
-               baseid = EVP_PKEY_ED448;
-       }
-#endif /* if HAVE_OPENSSL_ED448 */
-       if (baseid == EVP_PKEY_NONE) {
-               return (ISC_R_NOTIMPLEMENTED);
-       }
+       REQUIRE(alginfo != NULL);
 
        if (engine == NULL) {
                return (DST_R_NOENGINE);
@@ -633,7 +592,7 @@ openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
                return (dst__openssl_toresult2("ENGINE_load_private_key",
                                               ISC_R_NOTFOUND));
        }
-       if (EVP_PKEY_base_id(pkey) != baseid) {
+       if (EVP_PKEY_base_id(pkey) != alginfo->pkey_type) {
                DST_RET(DST_R_INVALIDPRIVATEKEY);
        }