From: Matthijs Mekking Date: Tue, 5 Jan 2021 10:09:38 +0000 (+0100) Subject: Make opensslecdsa_parse use fromlabel X-Git-Tag: v9.17.10~21^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=57ac70ad4651f9a6ecac57bb4cbd5e57a234954e;p=thirdparty%2Fbind9.git Make opensslecdsa_parse use fromlabel When 'opensslecdsa_parse()' encounters a label tag in the private key file, load the private key with 'opensslecdsa_fromlabel()'. Otherwise load it from the private structure. This was attempted before with 'load_privkey()' and 'uses_engine()', but had the same flaw as 'opensslecdsa_fromlabel()' had previously, that is getting the private and public key separately, juggling with pointers between EC_KEY and EVP_PKEY, did not create a valid cryptographic key that could be used for signing. --- diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c index 05ce6079e27..3d74630ff95 100644 --- a/lib/dns/opensslecdsa_link.c +++ b/lib/dns/opensslecdsa_link.c @@ -579,28 +579,6 @@ ecdsa_check(EC_KEY *eckey, EC_KEY *pubeckey) { return (ISC_R_FAILURE); } -static bool -uses_engine(const dst_private_t *priv, const char **engine, - const char **label) { - for (unsigned short i = 0; i < priv->nelements; i++) { - switch (priv->elements[i].tag) { - case TAG_ECDSA_ENGINE: - *engine = (char *)priv->elements[i].data; - break; - case TAG_ECDSA_LABEL: - *label = (char *)priv->elements[i].data; - break; - default: - break; - } - } - if (*label != NULL) { - return (true); - } - - return (false); -} - static isc_result_t load_privkey_from_privstruct(EC_KEY *eckey, dst_private_t *priv) { BIGNUM *privkey = BN_bin2bn(priv->elements[0].data, @@ -619,60 +597,6 @@ load_privkey_from_privstruct(EC_KEY *eckey, dst_private_t *priv) { return (result); } -#if !defined(OPENSSL_NO_ENGINE) -static isc_result_t -load_privkey_from_engine(EC_KEY *eckey, const char *engine, const char *label) { - EC_KEY *key; - ENGINE *ep; - EVP_PKEY *privkey; - - if (engine == NULL || label == NULL) { - return (DST_R_NOENGINE); - } - - ep = dst__openssl_getengine(engine); - if (ep == NULL) { - return (DST_R_NOENGINE); - } - - privkey = ENGINE_load_private_key(ep, label, NULL, NULL); - if (privkey == NULL) { - return (dst__openssl_toresult2("ENGINE_load_private_key", - ISC_R_NOTFOUND)); - } - - key = EVP_PKEY_get1_EC_KEY(privkey); - EVP_PKEY_free(privkey); - - if (key == NULL) { - return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); - } - - EC_KEY_set_private_key(eckey, EC_KEY_get0_private_key(key)); - - return (ISC_R_SUCCESS); -} -#else -static isc_result_t -load_privkey_from_engine(EC_KEY *eckey, const char *engine, const char *label) { - UNUSED(eckey); - UNUSED(engine); - UNUSED(label); - - return (DST_R_NOENGINE); -} -#endif - -static isc_result_t -load_privkey(EC_KEY *eckey, dst_private_t *priv, const char **engine, - const char **label) { - if (uses_engine(priv, engine, label)) { - return (load_privkey_from_engine(eckey, *engine, *label)); - } else { - return (load_privkey_from_privstruct(eckey, priv)); - } -} - static isc_result_t eckey_to_pkey(EC_KEY *eckey, EVP_PKEY **pkey) { REQUIRE(pkey != NULL && *pkey == NULL); @@ -739,6 +663,10 @@ dst__key_to_eckey(dst_key_t *key, EC_KEY **eckey) { return (ISC_R_SUCCESS); } +static isc_result_t +opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label, + const char *pin); + static isc_result_t opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; @@ -747,6 +675,8 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { EC_KEY *pubeckey = NULL; const char *engine = NULL; const char *label = NULL; + int i, privkey_index = -1; + bool finalize_key = false; /* read private key file */ result = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, key->mctx, @@ -765,18 +695,55 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { goto end; } - if (pub != NULL && pub->keydata.pkey != NULL) { - pubeckey = EVP_PKEY_get1_EC_KEY(pub->keydata.pkey); + for (i = 0; i < priv.nelements; i++) { + switch (priv.elements[i].tag) { + case TAG_ECDSA_ENGINE: + engine = (char *)priv.elements[i].data; + break; + case TAG_ECDSA_LABEL: + label = (char *)priv.elements[i].data; + break; + case TAG_ECDSA_PRIVATEKEY: + privkey_index = i; + break; + default: + break; + } } - result = dst__key_to_eckey(key, &eckey); - if (result != ISC_R_SUCCESS) { + if (privkey_index < 0) { + result = DST_R_INVALIDPRIVATEKEY; goto end; } - result = load_privkey(eckey, &priv, &engine, &label); - if (result != ISC_R_SUCCESS) { - goto end; + if (label != NULL) { + result = opensslecdsa_fromlabel(key, engine, label, NULL); + if (result != ISC_R_SUCCESS) { + goto end; + } + + eckey = EVP_PKEY_get1_EC_KEY(key->keydata.pkey); + if (eckey == NULL) { + result = dst__openssl_toresult(DST_R_OPENSSLFAILURE); + goto end; + } + + } else { + result = dst__key_to_eckey(key, &eckey); + if (result != ISC_R_SUCCESS) { + goto end; + } + + result = load_privkey_from_privstruct(eckey, &priv); + if (result != ISC_R_SUCCESS) { + goto end; + } + + finalize_key = true; + } + + if (pub != NULL && pub->keydata.pkey != NULL) { + pubeckey = EVP_PKEY_get1_EC_KEY(pub->keydata.pkey); } if (ecdsa_check(eckey, pubeckey) != ISC_R_SUCCESS) { @@ -784,7 +751,9 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { goto end; } - result = finalize_eckey(key, eckey, engine, label); + if (finalize_key) { + result = finalize_eckey(key, eckey, engine, label); + } end: if (pubeckey != NULL) {