diff options
-rw-r--r-- | crypto/err/openssl.txt | 2 | ||||
-rw-r--r-- | crypto/evp/evp_err.c | 4 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 26 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 126 | ||||
-rw-r--r-- | include/openssl/evperr.h | 2 | ||||
-rw-r--r-- | include/openssl/kdf.h | 14 | ||||
-rw-r--r-- | providers/defltprov.c | 2 | ||||
-rw-r--r-- | providers/implementations/exchange/build.info | 3 | ||||
-rw-r--r-- | providers/implementations/exchange/kdf_exch.c | 148 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 2 | ||||
-rw-r--r-- | providers/implementations/include/prov/kdfexchange.h | 24 | ||||
-rw-r--r-- | providers/implementations/kdfs/tls1_prf.c | 3 | ||||
-rw-r--r-- | providers/implementations/keymgmt/build.info | 3 | ||||
-rw-r--r-- | providers/implementations/keymgmt/kdf_legacy_kmgmt.c | 90 | ||||
-rw-r--r-- | test/pkey_meth_kdf_test.c | 6 | ||||
-rw-r--r-- | util/libcrypto.num | 3 |
16 files changed, 435 insertions, 23 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index af19ab26cd..d9512bc569 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2558,6 +2558,8 @@ EVP_R_INVALID_NULL_ALGORITHM:218:invalid null algorithm EVP_R_INVALID_OPERATION:148:invalid operation EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions EVP_R_INVALID_SALT_LENGTH:186:invalid salt length +EVP_R_INVALID_SECRET_LENGTH:221:invalid secret length +EVP_R_INVALID_SEED_LENGTH:220:invalid seed length EVP_R_KEYGEN_FAILURE:120:keygen failure EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure EVP_R_KEY_SETUP_FAILED:180:key setup failed diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index d13cd05faa..4e9970d573 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -97,6 +97,10 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { "invalid provider functions"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH), "invalid salt length"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SECRET_LENGTH), + "invalid secret length"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SEED_LENGTH), + "invalid seed length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE), "keymgmt export failure"}, diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index 28e1f88db9..a47a0f0367 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -202,11 +202,31 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) /* * Ensure that the key is provided, either natively, or as a cached export. - * If not, go legacy + * If not, goto legacy */ tmp_keymgmt = ctx->keymgmt; - provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, - &tmp_keymgmt, ctx->propquery); + if (ctx->pkey == NULL) { + /* + * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create + * a blank one. + */ + EVP_PKEY *pkey = EVP_PKEY_new(); + + if (pkey == NULL || !EVP_PKEY_set_type_by_keymgmt(pkey, tmp_keymgmt)) { + ERR_clear_last_mark(); + EVP_PKEY_free(pkey); + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + provkey = pkey->keydata = evp_keymgmt_newdata(tmp_keymgmt); + if (provkey == NULL) + EVP_PKEY_free(pkey); + else + ctx->pkey = pkey; + } else { + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + } if (provkey == NULL) goto legacy; if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 17e73e05ba..0fabaf4788 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -21,6 +21,7 @@ #include <openssl/core_names.h> #include <openssl/dh.h> #include <openssl/rsa.h> +#include <openssl/kdf.h> #include "internal/cryptlib.h" #include "crypto/asn1.h" #include "crypto/evp.h" @@ -156,7 +157,6 @@ static int is_legacy_alg(int id, const char *keytype) case EVP_PKEY_SM2: case EVP_PKEY_DHX: case EVP_PKEY_SCRYPT: - case EVP_PKEY_TLS1_PRF: case EVP_PKEY_HKDF: case EVP_PKEY_CMAC: case EVP_PKEY_HMAC: @@ -241,7 +241,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * If an ENGINE handled this method look it up. Otherwise use internal * tables. */ - if (e) + if (e != NULL) { pmeth = ENGINE_get_pkey_meth(e, id); else # endif @@ -759,7 +759,7 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md) { - OSSL_PARAM sig_md_params[3], *p = sig_md_params; + OSSL_PARAM sig_md_params[2], *p = sig_md_params; /* 80 should be big enough */ char name[80] = ""; const EVP_MD *tmp; @@ -778,7 +778,7 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, name, sizeof(name)); - *p++ = OSSL_PARAM_construct_end(); + *p = OSSL_PARAM_construct_end(); if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params)) return 0; @@ -820,11 +820,113 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) * only so should be safe */ (char *)name, 0); - *p++ = OSSL_PARAM_construct_end(); + *p = OSSL_PARAM_construct_end(); return EVP_PKEY_CTX_set_params(ctx, sig_md_params); } +int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +{ + OSSL_PARAM tls1_prf_md_params[2], *p = tls1_prf_md_params; + const char *name; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.kex.exchprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md)); + + if (md == NULL) { + name = ""; + } else { + name = EVP_MD_name(md); + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + /* + * Cast away the const. This is read + * only so should be safe + */ + (char *)name, 0); + *p++ = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, tls1_prf_md_params); +} + +int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *ctx, + const unsigned char *sec, int seclen) +{ + OSSL_PARAM tls1_prf_secret_params[2], *p = tls1_prf_secret_params; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.kex.exchprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_TLS_SECRET, seclen, + (void *)(sec)); + + + if (seclen < 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_SECRET_LENGTH); + return 0; + } + + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET, + /* + * Cast away the const. This is read + * only so should be safe + */ + (unsigned char *)sec, + (size_t)seclen); + *p++ = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, tls1_prf_secret_params); +} + +int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *ctx, + const unsigned char *seed, int seedlen) +{ + OSSL_PARAM tls1_prf_seed_params[2], *p = tls1_prf_seed_params; + + if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { + ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); + /* Uses the same return values as EVP_PKEY_CTX_ctrl */ + return -2; + } + + /* TODO(3.0): Remove this eventually when no more legacy */ + if (ctx->op.kex.exchprovctx == NULL) + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_TLS_SEED, seedlen, + (void *)(seed)); + + if (seedlen < 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_SEED_LENGTH); + return 0; + } + + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED, + /* + * Cast away the const. This is read + * only so should be safe + */ + (unsigned char *)seed, + (size_t)seedlen); + *p++ = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, tls1_prf_seed_params); +} + static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2) { @@ -926,6 +1028,16 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, * or for generic controls that are the same across multiple key types. */ if (keytype == -1) { + if (optype == EVP_PKEY_OP_DERIVE) { + switch (cmd) { + case EVP_PKEY_CTRL_TLS_MD: + return EVP_PKEY_CTX_set_tls1_prf_md(ctx, p2); + case EVP_PKEY_CTRL_TLS_SECRET: + return EVP_PKEY_CTX_set1_tls1_prf_secret(ctx, p2, p1); + case EVP_PKEY_CTRL_TLS_SEED: + return EVP_PKEY_CTX_add1_tls1_prf_seed(ctx, p2, p1); + } + } switch (cmd) { case EVP_PKEY_CTRL_MD: return EVP_PKEY_CTX_set_signature_md(ctx, p2); @@ -1034,7 +1146,9 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name, } # endif - if (strcmp(name, "rsa_padding_mode") == 0) + if (strcmp(name, "md") == 0) + name = OSSL_ALG_PARAM_DIGEST; + else if (strcmp(name, "rsa_padding_mode") == 0) name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE; else if (strcmp(name, "rsa_mgf1_md") == 0) name = OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST; diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h index 5aa002815a..a4dd4c757d 100644 --- a/include/openssl/evperr.h +++ b/include/openssl/evperr.h @@ -210,6 +210,8 @@ int ERR_load_EVP_strings(void); # define EVP_R_INVALID_OPERATION 148 # define EVP_R_INVALID_PROVIDER_FUNCTIONS 193 # define EVP_R_INVALID_SALT_LENGTH 186 +# define EVP_R_INVALID_SECRET_LENGTH 221 +# define EVP_R_INVALID_SEED_LENGTH 220 # define EVP_R_KEYGEN_FAILURE 120 # define EVP_R_KEYMGMT_EXPORT_FAILURE 205 # define EVP_R_KEY_SETUP_FAILED 180 diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h index b3dee525dc..1be54afc60 100644 --- a/include/openssl/kdf.h +++ b/include/openssl/kdf.h @@ -115,17 +115,13 @@ void EVP_KDF_names_do_all(const EVP_KDF *kdf, # define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY \ EVP_KDF_HKDF_MODE_EXPAND_ONLY -# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \ - EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ - EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md)) +int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); -# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \ - EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ - EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)(sec)) +int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *pctx, + const unsigned char *sec, int seclen); -# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \ - EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ - EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)(seed)) +int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *pctx, + const unsigned char *seed, int seedlen); # define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \ EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ diff --git a/providers/defltprov.c b/providers/defltprov.c index 4ab39e6531..5b6d6a677e 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -339,6 +339,7 @@ static const OSSL_ALGORITHM deflt_keyexch[] = { { "X25519", "provider=default", x25519_keyexch_functions }, { "X448", "provider=default", x448_keyexch_functions }, #endif + { "TLS1-PRF", "provider=default", kdf_keyexch_functions }, { NULL, NULL, NULL } }; @@ -384,6 +385,7 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = { { "ED25519", "provider=default", ed25519_keymgmt_functions }, { "ED448", "provider=default", ed448_keymgmt_functions }, #endif + { "TLS1-PRF", "provider=default", kdf_keymgmt_functions }, { NULL, NULL, NULL } }; diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info index 3127f9a3e7..92932b9d28 100644 --- a/providers/implementations/exchange/build.info +++ b/providers/implementations/exchange/build.info @@ -4,6 +4,7 @@ $DH_GOAL=../../libimplementations.a $ECX_GOAL=../../libimplementations.a $ECDH_GOAL=../../libimplementations.a +$KDF_GOAL=../../libimplementations.a IF[{- !$disabled{dh} -}] SOURCE[$DH_GOAL]=dh_exch.c @@ -25,3 +26,5 @@ IF[{- !$disabled{ec} -}] SOURCE[../../libfips.a]=ecdh_exch.c SOURCE[../../libnonfips.a]=ecdh_exch.c ENDIF + +SOURCE[$KDF_GOAL]=kdf_exch.c diff --git a/providers/implementations/exchange/kdf_exch.c b/providers/implementations/exchange/kdf_exch.c new file mode 100644 index 0000000000..41278e6389 --- /dev/null +++ b/providers/implementations/exchange/kdf_exch.c @@ -0,0 +1,148 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/crypto.h> +#include <openssl/kdf.h> +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +#include <openssl/params.h> +#include "prov/implementations.h" +#include "prov/provider_ctx.h" +#include "prov/kdfexchange.h" + +static OSSL_FUNC_keyexch_newctx_fn kdf_newctx; +static OSSL_FUNC_keyexch_init_fn kdf_init; +static OSSL_FUNC_keyexch_derive_fn kdf_derive; +static OSSL_FUNC_keyexch_freectx_fn kdf_freectx; +static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx; +static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params; +static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_settable_ctx_params; + +typedef struct { + void *provctx; + EVP_KDF_CTX *kdfctx; + KDF_DATA *kdfdata; +} PROV_KDF_CTX; + +static void *kdf_newctx(void *provctx) +{ + PROV_KDF_CTX *kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX)); + EVP_KDF *kdf = NULL; + + if (kdfctx == NULL) + return NULL; + + kdfctx->provctx = provctx; + + kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), "TLS1-PRF", NULL); + if (kdf == NULL) + goto err; + kdfctx->kdfctx = EVP_KDF_new_ctx(kdf); + EVP_KDF_free(kdf); + + if (kdfctx->kdfctx == NULL) + goto err; + + return kdfctx; + err: + OPENSSL_free(kdfctx); + return NULL; +} + +static int kdf_init(void *vpkdfctx, void *vkdf) +{ + PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; + + if (pkdfctx == NULL || vkdf == NULL || !kdf_data_up_ref(vkdf)) + return 0; + pkdfctx->kdfdata = vkdf; + + return 1; +} + +static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen, + size_t outlen) +{ + PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; + + return EVP_KDF_derive(pkdfctx->kdfctx, secret, *secretlen); +} + +static void kdf_freectx(void *vpkdfctx) +{ + PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; + + EVP_KDF_CTX_free(pkdfctx->kdfctx); + kdf_data_free(pkdfctx->kdfdata); + + OPENSSL_free(pkdfctx); +} + +static void *kdf_dupctx(void *vpkdfctx) +{ + PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx; + PROV_KDF_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + + dstctx->kdfctx = EVP_KDF_dup_ctx(srcctx->kdfctx); + if (dstctx->kdfctx == NULL) { + OPENSSL_free(dstctx); + return NULL; + } + if (!kdf_data_up_ref(dstctx->kdfdata)) { + EVP_KDF_CTX_free(dstctx->kdfctx); + OPENSSL_free(dstctx); + return NULL; + } + + return dstctx; +} + +static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[]) +{ + PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; + + return EVP_KDF_set_ctx_params(pkdfctx->kdfctx, params); +} + + +static const OSSL_PARAM *kdf_settable_ctx_params(void) +{ + /* + * TODO(3.0): FIXME FIXME!! These settable_ctx_params functions should + * should have a provctx argument so we can get hold of the libctx. + */ + EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL); + const OSSL_PARAM *params; + + if (kdf == NULL) + return NULL; + + params = EVP_KDF_settable_ctx_params(kdf); + EVP_KDF_free(kdf); + + return params; +} + +const OSSL_DISPATCH kdf_keyexch_functions[] = { + { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_newctx }, + { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, + { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, + { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, + { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, + { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, + { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, + (void (*)(void))kdf_settable_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 7e470044cd..e862e3f8e8 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -275,12 +275,14 @@ extern const OSSL_DISPATCH x448_keymgmt_functions[]; extern const OSSL_DISPATCH ed25519_keymgmt_functions[]; extern const OSSL_DISPATCH ed448_keymgmt_functions[]; extern const OSSL_DISPATCH ec_keymgmt_functions[]; +extern const OSSL_DISPATCH kdf_keymgmt_functions[]; /* Key Exchange */ extern const OSSL_DISPATCH dh_keyexch_functions[]; extern const OSSL_DISPATCH x25519_keyexch_functions[]; extern const OSSL_DISPATCH x448_keyexch_functions[]; extern const OSSL_DISPATCH ecdh_keyexch_functions[]; +extern const OSSL_DISPATCH kdf_keyexch_functions[]; /* Signature */ extern const OSSL_DISPATCH dsa_signature_functions[]; diff --git a/providers/implementations/include/prov/kdfexchange.h b/providers/implementations/include/prov/kdfexchange.h new file mode 100644 index 0000000000..5c817bb929 --- /dev/null +++ b/providers/implementations/include/prov/kdfexchange.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdlib.h> +#include <openssl/crypto.h> +#include "internal/refcount.h" + +struct kdf_data_st { + OPENSSL_CTX *libctx; + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; +}; + +typedef struct kdf_data_st KDF_DATA; + +KDF_DATA *kdf_data_new(void *provctx); +void kdf_data_free(KDF_DATA *kdfdata); +int kdf_data_up_ref(KDF_DATA *kdfdata); diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c index bc7d7fd721..46a1253ee8 100644 --- a/providers/implementations/kdfs/tls1_prf.c +++ b/providers/implementations/kdfs/tls1_prf.c @@ -183,9 +183,6 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) } /* The seed fields concatenate, so process them all */ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) { - OPENSSL_cleanse(ctx->seed, ctx->seedlen); - ctx->seedlen = 0; - for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_SEED)) { const void *q = ctx->seed + ctx->seedlen; diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info index 73597c7cea..53c84ac3d4 100644 --- a/providers/implementations/keymgmt/build.info +++ b/providers/implementations/keymgmt/build.info @@ -5,6 +5,7 @@ $DH_GOAL=../../libimplementations.a $DSA_GOAL=../../libimplementations.a $EC_GOAL=../../libimplementations.a $ECX_GOAL=../../libimplementations.a +$KDF_GOAL=../../libimplementations.a IF[{- !$disabled{dh} -}] SOURCE[$DH_GOAL]=dh_kmgmt.c @@ -33,3 +34,5 @@ ENDIF SOURCE[../../libfips.a]=rsa_kmgmt.c SOURCE[../../libnonfips.a]=rsa_kmgmt.c + +SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c new file mode 100644 index 0000000000..33cf87e350 --- /dev/null +++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c @@ -0,0 +1,90 @@ +/* + * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This implemments a dummy key manager for legacy KDFs that still support the + * old way of performing a KDF via EVP_PKEY_derive(). New KDFs should not be + * implemented this way. In reality there is no key data for such KDFs, so this + * key manager does very little. + */ + +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +#include <openssl/err.h> +#include "prov/implementations.h" +#include "prov/providercommon.h" +#include "prov/provider_ctx.h" +#include "prov/kdfexchange.h" + +static OSSL_FUNC_keymgmt_new_fn kdf_newdata; +static OSSL_FUNC_keymgmt_free_fn kdf_freedata; +static OSSL_FUNC_keymgmt_has_fn kdf_has; + +KDF_DATA *kdf_data_new(void *provctx) +{ + KDF_DATA *kdfdata = OPENSSL_zalloc(sizeof(*kdfdata)); + + if (kdfdata == NULL) + return NULL; + + kdfdata->lock = CRYPTO_THREAD_lock_new(); + if (kdfdata->lock == NULL) { + OPENSSL_free(kdfdata); + return NULL; + } + kdfdata->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); + kdfdata->refcnt = 1; + + return kdfdata; +} + +void kdf_data_free(KDF_DATA *kdfdata) +{ + int ref = 0; + + if (kdfdata == NULL) + return; + + CRYPTO_DOWN_REF(&kdfdata->refcnt, &ref, kdfdata->lock); + if (ref > 0) + return; + + CRYPTO_THREAD_lock_free(kdfdata->lock); + OPENSSL_free(kdfdata); +} + +int kdf_data_up_ref(KDF_DATA *kdfdata) +{ + int ref = 0; + + CRYPTO_UP_REF(&kdfdata->refcnt, &ref, kdfdata->lock); + return 1; +} + +static void *kdf_newdata(void *provctx) +{ + return kdf_data_new(provctx); +} + +static void kdf_freedata(void *kdfdata) +{ + kdf_data_free(kdfdata); +} + +static int kdf_has(void *keydata, int selection) +{ + return 0; +} + +const OSSL_DISPATCH kdf_keymgmt_functions[] = { + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))kdf_newdata }, + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))kdf_freedata }, + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))kdf_has }, + { 0, NULL } +}; diff --git a/test/pkey_meth_kdf_test.c b/test/pkey_meth_kdf_test.c index cdc3d9f61a..55b10f546e 100644 --- a/test/pkey_meth_kdf_test.c +++ b/test/pkey_meth_kdf_test.c @@ -35,11 +35,13 @@ static int test_kdf_tls1_prf(void) TEST_error("EVP_PKEY_CTX_set_tls1_prf_md"); goto err; } - if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) { + if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, + (unsigned char *)"secret", 6) <= 0) { TEST_error("EVP_PKEY_CTX_set1_tls1_prf_secret"); goto err; } - if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) { + if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, + (unsigned char *)"seed", 4) <= 0) { TEST_error("EVP_PKEY_CTX_add1_tls1_prf_seed"); goto err; } diff --git a/util/libcrypto.num b/util/libcrypto.num index fe875f188d..7a31db8bb5 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5226,3 +5226,6 @@ PKCS7_sign_with_libctx ? 3_0_0 EXIST::FUNCTION: PKCS7_encrypt_with_libctx ? 3_0_0 EXIST::FUNCTION: SMIME_read_PKCS7_ex ? 3_0_0 EXIST::FUNCTION: OSSL_PROVIDER_self_test ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set_tls1_prf_md ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_set1_tls1_prf_secret ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_CTX_add1_tls1_prf_seed ? 3_0_0 EXIST::FUNCTION: |