X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fp_lib.c;h=95dd96e86bce03b1071a30d263f073602210dbbc;hp=59cadb4aad1143f091ca92113775fb5893c86ad8;hb=b305452f69fc97c586f2f9310014e332ae1d5cd5;hpb=5310a4e616f9f0268048c6a8c4dec4cf2c493bb8 diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 59cadb4aad..95dd96e86b 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -27,13 +27,20 @@ #include "crypto/asn1.h" #include "crypto/evp.h" #include "internal/provider.h" +#include "evp_local.h" -static void EVP_PKEY_free_it(EVP_PKEY *x); +static void evp_pkey_free_it(EVP_PKEY *key); + +#ifndef FIPS_MODE int EVP_PKEY_bits(const EVP_PKEY *pkey) { - if (pkey && pkey->ameth && pkey->ameth->pkey_bits) - return pkey->ameth->pkey_bits(pkey); + if (pkey != NULL) { + if (pkey->ameth == NULL) + return pkey->cache.bits; + else if (pkey->ameth->pkey_bits) + return pkey->ameth->pkey_bits(pkey); + } return 0; } @@ -41,21 +48,16 @@ int EVP_PKEY_security_bits(const EVP_PKEY *pkey) { if (pkey == NULL) return 0; - if (pkey->ameth == NULL || pkey->ameth->pkey_security_bits == NULL) + if (pkey->ameth == NULL) + return pkey->cache.security_bits; + if (pkey->ameth->pkey_security_bits == NULL) return -2; return pkey->ameth->pkey_security_bits(pkey); } -int EVP_PKEY_size(const EVP_PKEY *pkey) -{ - if (pkey && pkey->ameth && pkey->ameth->pkey_size) - return pkey->ameth->pkey_size(pkey); - return 0; -} - int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) { -#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { int ret = pkey->save_parameters; @@ -63,8 +65,8 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) pkey->save_parameters = mode; return ret; } -#endif -#ifndef OPENSSL_NO_EC +# endif +# ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { int ret = pkey->save_parameters; @@ -72,7 +74,7 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) pkey->save_parameters = mode; return ret; } -#endif +# endif return 0; } @@ -141,38 +143,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -EVP_PKEY *EVP_PKEY_new(void) -{ - EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); - - if (ret == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - return NULL; - } - ret->type = EVP_PKEY_NONE; - ret->save_type = EVP_PKEY_NONE; - ret->references = 1; - ret->save_parameters = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); - OPENSSL_free(ret); - return NULL; - } - return ret; -} - -int EVP_PKEY_up_ref(EVP_PKEY *pkey) -{ - int i; - - if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) - return 0; - - REF_PRINT_COUNT("EVP_PKEY", pkey); - REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); -} /* * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey @@ -187,29 +157,29 @@ static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str, if (pkey) { if (pkey->pkey.ptr) - EVP_PKEY_free_it(pkey); + evp_pkey_free_it(pkey); /* * If key type matches and a method exists then this lookup has * succeeded once so just indicate success. */ if ((type == pkey->save_type) && pkey->ameth) return 1; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE /* If we have ENGINEs release them */ ENGINE_finish(pkey->engine); pkey->engine = NULL; ENGINE_finish(pkey->pmeth_engine); pkey->pmeth_engine = NULL; -#endif +# endif } if (str) ameth = EVP_PKEY_asn1_find_str(eptr, str, len); else ameth = EVP_PKEY_asn1_find(eptr, type); -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE if (pkey == NULL && eptr != NULL) ENGINE_finish(e); -#endif +# endif if (ameth == NULL) { EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); return 0; @@ -321,10 +291,10 @@ int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, size_t len, const EVP_CIPHER *cipher) { -#ifndef OPENSSL_NO_CMAC -# ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_CMAC +# ifndef OPENSSL_NO_ENGINE const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL; -# endif +# endif const char *cipher_name = EVP_CIPHER_name(cipher); const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher); OPENSSL_CTX *libctx = @@ -342,11 +312,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, goto err; } -# ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE if (engine_id != NULL) params[paramsn++] = OSSL_PARAM_construct_utf8_string("engine", (char *)engine_id, 0); -# endif +# endif params[paramsn++] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, @@ -369,11 +339,11 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, EVP_MAC_CTX_free(cmctx); EVP_MAC_free(cmac); return NULL; -#else +# else EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return NULL; -#endif +# endif } int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) @@ -405,7 +375,7 @@ int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type) return 1; } -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) { if (e != NULL) { @@ -428,11 +398,22 @@ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey) { return pkey->engine; } -#endif +# endif int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { + int alias = type; + + if (EVP_PKEY_type(type) == EVP_PKEY_EC) { + const EC_GROUP *group = EC_KEY_get0_group(key); + + if (group != NULL && EC_GROUP_get_curve_name(group) == NID_sm2) + alias = EVP_PKEY_SM2; + } + if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) return 0; + if (!EVP_PKEY_set_alias_type(pkey, alias)) + return 0; pkey->pkey.ptr = key; return (key != NULL); } @@ -454,7 +435,7 @@ const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len) return os->data; } -#ifndef OPENSSL_NO_POLY1305 +# ifndef OPENSSL_NO_POLY1305 const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) { ASN1_OCTET_STRING *os = NULL; @@ -466,9 +447,9 @@ const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len) *len = os->length; return os->data; } -#endif +# endif -#ifndef OPENSSL_NO_SIPHASH +# ifndef OPENSSL_NO_SIPHASH const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) { ASN1_OCTET_STRING *os = NULL; @@ -481,9 +462,9 @@ const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len) *len = os->length; return os->data; } -#endif +# endif -#ifndef OPENSSL_NO_RSA +# ifndef OPENSSL_NO_RSA int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { int ret = EVP_PKEY_assign_RSA(pkey, key); @@ -508,9 +489,9 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) RSA_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) { int ret = EVP_PKEY_assign_DSA(pkey, key); @@ -535,9 +516,9 @@ DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) DSA_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_EC int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) { @@ -549,7 +530,7 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) { - if (pkey->type != EVP_PKEY_EC) { + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); return NULL; } @@ -563,9 +544,9 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) EC_KEY_up_ref(ret); return ret; } -#endif +# endif -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) { @@ -593,7 +574,7 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) DH_up_ref(ret); return ret; } -#endif +# endif int EVP_PKEY_type(int type) { @@ -605,9 +586,9 @@ int EVP_PKEY_type(int type) ret = ameth->pkey_id; else ret = NID_undef; -#ifndef OPENSSL_NO_ENGINE +# ifndef OPENSSL_NO_ENGINE ENGINE_finish(e); -#endif +# endif return ret; } @@ -621,41 +602,6 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey) return EVP_PKEY_type(pkey->type); } -void EVP_PKEY_free(EVP_PKEY *x) -{ - int i; - - if (x == NULL) - return; - - CRYPTO_DOWN_REF(&x->references, &i, x->lock); - REF_PRINT_COUNT("EVP_PKEY", x); - if (i > 0) - return; - REF_ASSERT_ISNT(i < 0); - EVP_PKEY_free_it(x); - CRYPTO_THREAD_lock_free(x->lock); - sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); - OPENSSL_free(x); -} - -static void EVP_PKEY_free_it(EVP_PKEY *x) -{ - /* internal function; x is never NULL */ - - evp_keymgmt_clear_pkey_cache(x); - - if (x->ameth && x->ameth->pkey_free) { - x->ameth->pkey_free(x); - x->pkey.ptr = NULL; - } -#ifndef OPENSSL_NO_ENGINE - ENGINE_finish(x->engine); - x->engine = NULL; - ENGINE_finish(x->pmeth_engine); - x->pmeth_engine = NULL; -#endif -} static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent) { @@ -756,9 +702,39 @@ int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, pctx); } +static int legacy_asn1_ctrl_to_param(EVP_PKEY *pkey, int op, + int arg1, void *arg2) +{ + if (pkey->pkeys[0].keymgmt == NULL) + return 0; + switch (op) { + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + { + char mdname[80] = ""; + int nid; + int rv = EVP_PKEY_get_default_digest_name(pkey, mdname, + sizeof(mdname)); + + if (rv <= 0) + return rv; + nid = OBJ_sn2nid(mdname); + if (nid == NID_undef) + nid = OBJ_ln2nid(mdname); + if (nid == NID_undef) + return 0; + *(int *)arg2 = nid; + return 1; + } + default: + return -2; + } +} + static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2) { - if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) + if (pkey->ameth == NULL) + return legacy_asn1_ctrl_to_param(pkey, op, arg1, arg2); + if (pkey->ameth->pkey_ctrl == NULL) return -2; return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2); } @@ -768,6 +744,45 @@ int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid); } +int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey, + char *mdname, size_t mdname_sz) +{ + if (pkey->ameth == NULL) { + OSSL_PARAM params[3]; + char mddefault[100] = ""; + char mdmandatory[100] = ""; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, + mddefault, sizeof(mddefault)); + params[1] = + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, + mdmandatory, + sizeof(mdmandatory)); + params[2] = OSSL_PARAM_construct_end(); + if (!evp_keymgmt_get_params(pkey->pkeys[0].keymgmt, + pkey->pkeys[0].keydata, + params)) + return 0; + if (mdmandatory[0] != '\0') { + OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz); + return 2; + } + OPENSSL_strlcpy(mdname, mddefault, mdname_sz); + return 1; + } + + { + int nid = NID_undef; + int rv = EVP_PKEY_get_default_digest_nid(pkey, &nid); + const char *name = rv > 0 ? OBJ_nid2sn(nid) : NULL; + + if (rv > 0) + OPENSSL_strlcpy(mdname, name, mdname_sz); + return rv; + } +} + int EVP_PKEY_supports_digest_nid(EVP_PKEY *pkey, int nid) { int rv, default_nid; @@ -807,3 +822,132 @@ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) return 0; return rv; } + +#endif /* FIPS_MODE */ + +/*- All methods below can also be used in FIPS_MODE */ + +EVP_PKEY *EVP_PKEY_new(void) +{ + EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->type = EVP_PKEY_NONE; + ret->save_type = EVP_PKEY_NONE; + ret->references = 1; + ret->save_parameters = 1; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; +} + +int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ + int i; + + if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) + return 0; + + REF_PRINT_COUNT("EVP_PKEY", pkey); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +static void evp_pkey_free_it(EVP_PKEY *x) +{ + /* internal function; x is never NULL */ + + evp_keymgmt_util_clear_pkey_cache(x); + + if (x->ameth && x->ameth->pkey_free) { + x->ameth->pkey_free(x); + x->pkey.ptr = NULL; + } +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) + ENGINE_finish(x->engine); + x->engine = NULL; + ENGINE_finish(x->pmeth_engine); + x->pmeth_engine = NULL; +#endif +} + +void EVP_PKEY_free(EVP_PKEY *x) +{ + int i; + + if (x == NULL) + return; + + CRYPTO_DOWN_REF(&x->references, &i, x->lock); + REF_PRINT_COUNT("EVP_PKEY", x); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + evp_pkey_free_it(x); + CRYPTO_THREAD_lock_free(x->lock); +#ifndef FIPS_MODE + sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); +#endif + OPENSSL_free(x); +} + +int EVP_PKEY_size(const EVP_PKEY *pkey) +{ + if (pkey != NULL) { + if (pkey->ameth == NULL) + return pkey->cache.size; + else if (pkey->ameth->pkey_size != NULL) + return pkey->ameth->pkey_size(pkey); + } + return 0; +} + +void *evp_pkey_make_provided(EVP_PKEY *pk, OPENSSL_CTX *libctx, + EVP_KEYMGMT **keymgmt, const char *propquery) +{ + EVP_KEYMGMT *allocated_keymgmt = NULL; + EVP_KEYMGMT *tmp_keymgmt = NULL; + void *keydata = NULL; + + if (pk == NULL) + return NULL; + + if (keymgmt != NULL) { + tmp_keymgmt = *keymgmt; + *keymgmt = NULL; + } + + if (tmp_keymgmt == NULL) { + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery); + + if (ctx != NULL && ctx->keytype != NULL) + tmp_keymgmt = allocated_keymgmt = + EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery); + EVP_PKEY_CTX_free(ctx); + } + + if (tmp_keymgmt != NULL) + keydata = + evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt); + + /* + * If nothing was exported, |tmp_keymgmt| might point at a freed + * EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for + * the caller either way in that case. + */ + if (keydata == NULL) + tmp_keymgmt = NULL; + + if (keymgmt != NULL) + *keymgmt = tmp_keymgmt; + + EVP_KEYMGMT_free(allocated_keymgmt); + return keydata; +}