diff options
author | Pauli <paul.dale@oracle.com> | 2019-08-21 18:54:35 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2019-09-06 19:27:57 +1000 |
commit | fb9e6dd6f8b1de99c880ff3b458d6bc0dec907bb (patch) | |
tree | 60daa87494f3243dc9cce72284843ba8981b21cf /crypto/evp | |
parent | 55accfd2f11d02cf4cfdc6077216ae59f1748f6a (diff) |
KDF/PRF updates to libcrypto
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9662)
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/build.info | 6 | ||||
-rw-r--r-- | crypto/evp/evp_locl.h | 4 | ||||
-rw-r--r-- | crypto/evp/kdf_lib.c | 140 | ||||
-rw-r--r-- | crypto/evp/kdf_meth.c | 192 | ||||
-rw-r--r-- | crypto/evp/names.c | 29 |
5 files changed, 280 insertions, 91 deletions
diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 688e6fc94e..d9df71959c 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -1,6 +1,6 @@ LIBS=../../libcrypto $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \ - mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c + mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c SOURCE[../../libcrypto]=$COMMON\ encode.c evp_key.c evp_cnf.c \ e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ @@ -11,8 +11,8 @@ SOURCE[../../libcrypto]=$COMMON\ p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \ c_allc.c c_alld.c bio_ok.c \ - evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ - pkey_kdf.c c_allkdf.c \ + evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ + pkey_kdf.c \ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ e_chacha20_poly1305.c \ diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index 87f54bdc5f..750e593b66 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -61,8 +61,8 @@ struct evp_mac_ctx_st { } /* EVP_MAC_CTX */; struct evp_kdf_ctx_st { - const EVP_KDF *meth; /* Method structure */ - EVP_KDF_IMPL *impl; /* Algorithm-specific data */ + EVP_KDF *meth; /* Method structure */ + void *data; /* Algorithm-specific data */ } /* EVP_KDF_CTX */ ; struct evp_keymgmt_st { diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index 6131d8ef77..aa0c5e341f 100644 --- a/crypto/evp/kdf_lib.c +++ b/crypto/evp/kdf_lib.c @@ -15,12 +15,15 @@ #include <openssl/evp.h> #include <openssl/x509v3.h> #include <openssl/kdf.h> +#include <openssl/core.h> +#include <openssl/core_names.h> #include "internal/asn1_int.h" #include "internal/evp_int.h" #include "internal/numbers.h" +#include "internal/provider.h" #include "evp_locl.h" -EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf) +EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf) { EVP_KDF_CTX *ctx = NULL; @@ -28,8 +31,12 @@ EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf) return NULL; ctx = OPENSSL_zalloc(sizeof(EVP_KDF_CTX)); - if (ctx == NULL || (ctx->impl = kdf->new()) == NULL) { + if (ctx == NULL + || (ctx->data = kdf->newctx(ossl_provider_ctx(kdf->prov))) == NULL + || !EVP_KDF_up_ref(kdf)) { EVPerr(EVP_F_EVP_KDF_CTX_NEW, ERR_R_MALLOC_FAILURE); + if (ctx != NULL) + kdf->freectx(ctx->data); OPENSSL_free(ctx); ctx = NULL; } else { @@ -38,30 +45,57 @@ EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf) return ctx; } -EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id) +void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx) { - const EVP_KDF *kdf = EVP_get_kdfbynid(id); - - return EVP_KDF_CTX_new(kdf); + if (ctx != NULL) { + ctx->meth->freectx(ctx->data); + ctx->data = NULL; + EVP_KDF_free(ctx->meth); + OPENSSL_free(ctx); + } } -int EVP_KDF_nid(const EVP_KDF *kdf) +EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src) { - return kdf->type; + EVP_KDF_CTX *dst; + + if (src->data == NULL || src == NULL || src->meth->dupctx == NULL) + return NULL; + + dst = OPENSSL_malloc(sizeof(*dst)); + if (dst == NULL) { + EVPerr(EVP_F_EVP_KDF_CTX_DUP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + memcpy(dst, src, sizeof(*dst)); + if (!EVP_KDF_up_ref(dst->meth)) { + EVPerr(EVP_F_EVP_KDF_CTX_DUP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(dst); + return NULL; + } + + dst->data = src->meth->dupctx(src->data); + if (dst->data == NULL) { + EVP_KDF_CTX_free(dst); + return NULL; + } + return dst; } -const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx) +const char *EVP_KDF_name(const EVP_KDF *kdf) { - return ctx->meth; + return kdf->name; } -void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx) +const OSSL_PROVIDER *EVP_KDF_provider(const EVP_KDF *kdf) { - if (ctx == NULL) - return; + return kdf->prov; +} - ctx->meth->free(ctx->impl); - OPENSSL_free(ctx); +const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx) +{ + return ctx->meth; } void EVP_KDF_reset(EVP_KDF_CTX *ctx) @@ -70,66 +104,58 @@ void EVP_KDF_reset(EVP_KDF_CTX *ctx) return; if (ctx->meth->reset != NULL) - ctx->meth->reset(ctx->impl); + ctx->meth->reset(ctx->data); } -int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...) +size_t EVP_KDF_size(EVP_KDF_CTX *ctx) { - int ret; - va_list args; - - va_start(args, cmd); - ret = EVP_KDF_vctrl(ctx, cmd, args); - va_end(args); - - if (ret == -2) - EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t s; - return ret; -} - -int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args) -{ if (ctx == NULL) return 0; - return ctx->meth->ctrl(ctx->impl, cmd, args); + *params = OSSL_PARAM_construct_size_t(OSSL_KDF_PARAM_SIZE, &s); + if (ctx->meth->get_ctx_params != NULL + && ctx->meth->get_ctx_params(ctx, params)) + return s; + if (ctx->meth->get_params != NULL + && ctx->meth->get_params(params)) + return s; + return 0; } -int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value) +int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen) { - int ret; - if (ctx == NULL) return 0; - if (ctx->meth->ctrl_str == NULL) { - EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); - return -2; - } - - ret = ctx->meth->ctrl_str(ctx->impl, type, value); - if (ret == -2) - EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); - - return ret; + return ctx->meth->derive(ctx->data, key, keylen); } -size_t EVP_KDF_size(EVP_KDF_CTX *ctx) +/* + * The {get,set}_params functions return 1 if there is no corresponding + * function in the implementation. This is the same as if there was one, + * but it didn't recognise any of the given params, i.e. nothing in the + * bag of parameters was useful. + */ +int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]) { - if (ctx == NULL) - return 0; - - if (ctx->meth->size == NULL) - return SIZE_MAX; - - return ctx->meth->size(ctx->impl); + if (kdf->get_params != NULL) + return kdf->get_params(params); + return 1; } -int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen) +int EVP_KDF_CTX_get_params(EVP_KDF_CTX *ctx, OSSL_PARAM params[]) { - if (ctx == NULL) - return 0; + if (ctx->meth->get_ctx_params != NULL) + return ctx->meth->get_ctx_params(ctx->data, params); + return 1; +} - return ctx->meth->derive(ctx->impl, key, keylen); +int EVP_KDF_CTX_set_params(EVP_KDF_CTX *ctx, const OSSL_PARAM params[]) +{ + if (ctx->meth->set_ctx_params != NULL) + return ctx->meth->set_ctx_params(ctx->data, params); + return 1; } diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c new file mode 100644 index 0000000000..f45fa3f74f --- /dev/null +++ b/crypto/evp/kdf_meth.c @@ -0,0 +1,192 @@ +/* + * Copyright 2019 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/evp.h> +#include <openssl/err.h> +#include <openssl/core.h> +#include <openssl/core_numbers.h> +#include <openssl/kdf.h> +#include "internal/evp_int.h" +#include "internal/provider.h" +#include "evp_locl.h" + +static int evp_kdf_up_ref(void *vkdf) +{ + EVP_KDF *kdf = (EVP_KDF *)vkdf; + int ref = 0; + + CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock); + return 1; +} + +static void evp_kdf_free(void *vkdf){ + EVP_KDF *kdf = (EVP_KDF *)vkdf; + int ref = 0; + + if (kdf != NULL) { + CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock); + if (ref <= 0) { + ossl_provider_free(kdf->prov); + OPENSSL_free(kdf->name); + CRYPTO_THREAD_lock_free(kdf->lock); + OPENSSL_free(kdf); + } + } +} + +static void *evp_kdf_new(void) +{ + EVP_KDF *kdf = NULL; + + if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL + || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) { + OPENSSL_free(kdf); + return NULL; + } + kdf->refcnt = 1; + return kdf; +} + +static void *evp_kdf_from_dispatch(const char *name, const OSSL_DISPATCH *fns, + OSSL_PROVIDER *prov, void *method_data) +{ + EVP_KDF *kdf = NULL; + int fnkdfcnt = 0, fnctxcnt = 0; + + if ((kdf = evp_kdf_new()) == NULL + || (kdf->name = OPENSSL_strdup(name)) == NULL) { + evp_kdf_free(kdf); + EVPerr(0, ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_KDF_NEWCTX: + if (kdf->newctx != NULL) + break; + kdf->newctx = OSSL_get_OP_kdf_newctx(fns); + fnctxcnt++; + break; + case OSSL_FUNC_KDF_DUPCTX: + if (kdf->dupctx != NULL) + break; + kdf->dupctx = OSSL_get_OP_kdf_dupctx(fns); + break; + case OSSL_FUNC_KDF_FREECTX: + if (kdf->freectx != NULL) + break; + kdf->freectx = OSSL_get_OP_kdf_freectx(fns); + fnctxcnt++; + break; + case OSSL_FUNC_KDF_DERIVE: + if (kdf->derive != NULL) + break; + kdf->derive = OSSL_get_OP_kdf_derive(fns); + fnkdfcnt++; + break; + case OSSL_FUNC_KDF_GETTABLE_PARAMS: + if (kdf->gettable_params != NULL) + break; + kdf->gettable_params = + OSSL_get_OP_kdf_gettable_params(fns); + break; + case OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS: + if (kdf->gettable_ctx_params != NULL) + break; + kdf->gettable_ctx_params = + OSSL_get_OP_kdf_gettable_ctx_params(fns); + break; + case OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS: + if (kdf->settable_ctx_params != NULL) + break; + kdf->settable_ctx_params = + OSSL_get_OP_kdf_settable_ctx_params(fns); + break; + case OSSL_FUNC_KDF_GET_PARAMS: + if (kdf->get_params != NULL) + break; + kdf->get_params = OSSL_get_OP_kdf_get_params(fns); + break; + case OSSL_FUNC_KDF_GET_CTX_PARAMS: + if (kdf->get_ctx_params != NULL) + break; + kdf->get_ctx_params = OSSL_get_OP_kdf_get_ctx_params(fns); + break; + case OSSL_FUNC_KDF_SET_CTX_PARAMS: + if (kdf->set_ctx_params != NULL) + break; + kdf->set_ctx_params = OSSL_get_OP_kdf_set_ctx_params(fns); + break; + } + } + if (fnkdfcnt != 1 || fnctxcnt != 2) { + /* + * In order to be a consistent set of functions we must have at least + * a derive function, and a complete set of context management + * functions. + */ + evp_kdf_free(kdf); + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); + return NULL; + } + kdf->prov = prov; + if (prov != NULL) + ossl_provider_up_ref(prov); + + return kdf; +} + +EVP_KDF *EVP_KDF_fetch(OPENSSL_CTX *libctx, const char *algorithm, + const char *properties) +{ + return evp_generic_fetch(libctx, OSSL_OP_KDF, algorithm, properties, + evp_kdf_from_dispatch, NULL, evp_kdf_up_ref, + evp_kdf_free); +} + +int EVP_KDF_up_ref(EVP_KDF *kdf) +{ + return evp_kdf_up_ref(kdf); +} + +void EVP_KDF_free(EVP_KDF *kdf) +{ + evp_kdf_free(kdf); +} + +const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf) +{ + if (kdf->gettable_params == NULL) + return NULL; + return kdf->gettable_params(); +} + +const OSSL_PARAM *EVP_KDF_CTX_gettable_params(const EVP_KDF *kdf) +{ + if (kdf->gettable_ctx_params == NULL) + return NULL; + return kdf->gettable_ctx_params(); +} + +const OSSL_PARAM *EVP_KDF_CTX_settable_params(const EVP_KDF *kdf) +{ + if (kdf->settable_ctx_params == NULL) + return NULL; + return kdf->settable_ctx_params(); +} + +void EVP_KDF_do_all_ex(OPENSSL_CTX *libctx, + void (*fn)(EVP_KDF *kdf, void *arg), + void *arg) +{ + evp_generic_do_all(libctx, OSSL_OP_KDF, + (void (*)(void *, void *))fn, arg, + evp_kdf_from_dispatch, NULL, evp_kdf_free); +} diff --git a/crypto/evp/names.c b/crypto/evp/names.c index 82db98a1f2..7c2f4f061c 100644 --- a/crypto/evp/names.c +++ b/crypto/evp/names.c @@ -56,23 +56,6 @@ int EVP_add_digest(const EVP_MD *md) return r; } -/* TODO(3.0) Is this needed after changing to providers? */ -int EVP_add_kdf(const EVP_KDF *k) -{ - int r; - - if (k == NULL) - return 0; - - r = OBJ_NAME_add(OBJ_nid2sn(k->type), OBJ_NAME_TYPE_KDF_METH, - (const char *)k); - if (r == 0) - return 0; - r = OBJ_NAME_add(OBJ_nid2ln(k->type), OBJ_NAME_TYPE_KDF_METH, - (const char *)k); - return r; -} - const EVP_CIPHER *EVP_get_cipherbyname(const char *name) { const EVP_CIPHER *cp; @@ -95,18 +78,6 @@ const EVP_MD *EVP_get_digestbyname(const char *name) return cp; } -/* TODO(3.0) Is this API needed after implementing providers? */ -const EVP_KDF *EVP_get_kdfbyname(const char *name) -{ - const EVP_KDF *kdf; - - if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_KDFS, NULL)) - return NULL; - - kdf = (const EVP_KDF *)OBJ_NAME_get(name, OBJ_NAME_TYPE_KDF_METH); - return kdf; -} - void evp_cleanup_int(void) { OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH); |