diff options
author | Pauli <paul.dale@oracle.com> | 2019-08-21 13:09:10 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2019-09-06 19:27:57 +1000 |
commit | e3405a4a9a5334cd636940a547a25c09ffc76009 (patch) | |
tree | fdfaa93cd338f93258a50bc376ff99d893497df8 /providers | |
parent | 7707526b8dfa8063c4537c11199c15ad7a3cab1c (diff) |
Add KDFs to providers
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9662)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/common/build.info | 2 | ||||
-rw-r--r-- | providers/common/include/internal/provider_algs.h | 37 | ||||
-rw-r--r-- | providers/common/kdfs/build.info | 4 | ||||
-rw-r--r-- | providers/common/kdfs/hkdf.c | 351 | ||||
-rw-r--r-- | providers/common/kdfs/pbkdf2.c | 322 | ||||
-rw-r--r-- | providers/common/kdfs/sshkdf.c | 292 | ||||
-rw-r--r-- | providers/common/kdfs/sskdf.c | 394 | ||||
-rw-r--r-- | providers/common/kdfs/tls1_prf.c | 281 | ||||
-rw-r--r-- | providers/default/build.info | 1 | ||||
-rw-r--r-- | providers/default/defltprov.c | 18 | ||||
-rw-r--r-- | providers/default/kdfs/build.info | 3 | ||||
-rw-r--r-- | providers/default/kdfs/scrypt.c (renamed from providers/common/kdfs/scrypt.c) | 336 | ||||
-rw-r--r-- | providers/default/kdfs/sshkdf.c | 297 | ||||
-rw-r--r-- | providers/default/kdfs/x942kdf.c (renamed from providers/common/kdfs/x942kdf.c) | 285 | ||||
-rw-r--r-- | providers/fips/fipsprov.c | 15 |
15 files changed, 1406 insertions, 1232 deletions
diff --git a/providers/common/build.info b/providers/common/build.info index 4c977d3f25..4d87b15e8d 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -1,4 +1,4 @@ -SUBDIRS=digests ciphers macs exchange keymgmt +SUBDIRS=digests ciphers macs kdfs exchange keymgmt SOURCE[../../libcrypto]=\ provider_err.c provlib.c diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h index e66c0523e7..b9d257649f 100644 --- a/providers/common/include/internal/provider_algs.h +++ b/providers/common/include/internal/provider_algs.h @@ -115,17 +115,6 @@ extern const OSSL_DISPATCH camellia192ctr_functions[]; extern const OSSL_DISPATCH camellia128ctr_functions[]; #endif /* OPENSSL_NO_CAMELLIA */ -/* MACs */ -extern const OSSL_DISPATCH blake2bmac_functions[]; -extern const OSSL_DISPATCH blake2smac_functions[]; -extern const OSSL_DISPATCH cmac_functions[]; -extern const OSSL_DISPATCH gmac_functions[]; -extern const OSSL_DISPATCH hmac_functions[]; -extern const OSSL_DISPATCH kmac128_functions[]; -extern const OSSL_DISPATCH kmac256_functions[]; -extern const OSSL_DISPATCH siphash_functions[]; -extern const OSSL_DISPATCH poly1305_functions[]; - extern const OSSL_DISPATCH tdes_ede3_ecb_functions[]; extern const OSSL_DISPATCH tdes_ede3_cbc_functions[]; @@ -144,6 +133,32 @@ extern const OSSL_DISPATCH tdes_desx_cbc_functions[]; extern const OSSL_DISPATCH tdes_wrap_cbc_functions[]; #endif /* FIPS_MODE */ +/* MACs */ +extern const OSSL_DISPATCH blake2bmac_functions[]; +extern const OSSL_DISPATCH blake2smac_functions[]; +extern const OSSL_DISPATCH cmac_functions[]; +extern const OSSL_DISPATCH gmac_functions[]; +extern const OSSL_DISPATCH hmac_functions[]; +extern const OSSL_DISPATCH kmac128_functions[]; +extern const OSSL_DISPATCH kmac256_functions[]; +extern const OSSL_DISPATCH siphash_functions[]; +extern const OSSL_DISPATCH poly1305_functions[]; + +/* KDFs / PRFs */ +extern const OSSL_DISPATCH kdf_pbkdf2_functions[]; +#ifndef OPENSSL_NO_SCRYPT +extern const OSSL_DISPATCH kdf_scrypt_functions[]; +#endif +extern const OSSL_DISPATCH kdf_tls1_prf_functions[]; +extern const OSSL_DISPATCH kdf_hkdf_functions[]; +extern const OSSL_DISPATCH kdf_sshkdf_functions[]; +extern const OSSL_DISPATCH kdf_sskdf_functions[]; +extern const OSSL_DISPATCH kdf_x963_kdf_functions[]; +#ifndef OPENSSL_NO_CMS +extern const OSSL_DISPATCH kdf_x942_kdf_functions[]; +#endif + + /* Key management */ extern const OSSL_DISPATCH dh_keymgmt_functions[]; diff --git a/providers/common/kdfs/build.info b/providers/common/kdfs/build.info index 422cf7471e..a881fa00b9 100644 --- a/providers/common/kdfs/build.info +++ b/providers/common/kdfs/build.info @@ -1,7 +1,7 @@ -$COMMON=tls1_prf.c hkdf.c scrypt.c pbkdf2.c sskdf.c +$COMMON=tls1_prf.c hkdf.c pbkdf2.c sskdf.c LIBS=../../../libcrypto -SOURCE[../../../libcrypto]=$COMMON sshkdf.c x942kdf.c +SOURCE[../../../libcrypto]=$COMMON INCLUDE[../../../libcrypto]=. ../../../crypto IF[{- !$disabled{fips} -}] diff --git a/providers/common/kdfs/hkdf.c b/providers/common/kdfs/hkdf.c index 33c74da86a..f5d0295ae3 100644 --- a/providers/common/kdfs/hkdf.c +++ b/providers/common/kdfs/hkdf.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-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 @@ -13,14 +13,26 @@ #include <openssl/hmac.h> #include <openssl/evp.h> #include <openssl/kdf.h> +#include <openssl/core_names.h> #include "internal/cryptlib.h" #include "internal/numbers.h" #include "internal/evp_int.h" -#include "kdf_local.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "e_os.h" #define HKDF_MAXBUF 1024 -static void kdf_hkdf_reset(EVP_KDF_IMPL *impl); +static OSSL_OP_kdf_newctx_fn kdf_hkdf_new; +static OSSL_OP_kdf_freectx_fn kdf_hkdf_free; +static OSSL_OP_kdf_reset_fn kdf_hkdf_reset; +static OSSL_OP_kdf_derive_fn kdf_hkdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params; +static OSSL_OP_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; +static OSSL_OP_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params; + static int HKDF(const EVP_MD *evp_md, const unsigned char *salt, size_t salt_len, const unsigned char *key, size_t key_len, @@ -35,209 +47,236 @@ static int HKDF_Expand(const EVP_MD *evp_md, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); -struct evp_kdf_impl_st { +typedef struct { + void *provctx; int mode; - const EVP_MD *md; + EVP_MD *md; unsigned char *salt; size_t salt_len; unsigned char *key; size_t key_len; unsigned char info[HKDF_MAXBUF]; size_t info_len; -}; +} KDF_HKDF; -static EVP_KDF_IMPL *kdf_hkdf_new(void) +static void *kdf_hkdf_new(void *provctx) { - EVP_KDF_IMPL *impl; + KDF_HKDF *ctx; - if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL) - KDFerr(KDF_F_KDF_HKDF_NEW, ERR_R_MALLOC_FAILURE); - return impl; + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + else + ctx->provctx = provctx; + return ctx; } -static void kdf_hkdf_free(EVP_KDF_IMPL *impl) +static void kdf_hkdf_free(void *vctx) { - kdf_hkdf_reset(impl); - OPENSSL_free(impl); -} + KDF_HKDF *ctx = (KDF_HKDF *)vctx; -static void kdf_hkdf_reset(EVP_KDF_IMPL *impl) -{ - OPENSSL_free(impl->salt); - OPENSSL_clear_free(impl->key, impl->key_len); - OPENSSL_cleanse(impl->info, impl->info_len); - memset(impl, 0, sizeof(*impl)); + kdf_hkdf_reset(ctx); + EVP_MD_meth_free(ctx->md); + OPENSSL_free(ctx); } -static int kdf_hkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) +static void kdf_hkdf_reset(void *vctx) { - const unsigned char *p; - size_t len; - const EVP_MD *md; - - switch (cmd) { - case EVP_KDF_CTRL_SET_MD: - md = va_arg(args, const EVP_MD *); - if (md == NULL) - return 0; - - impl->md = md; - return 1; - - case EVP_KDF_CTRL_SET_HKDF_MODE: - impl->mode = va_arg(args, int); - return 1; - - case EVP_KDF_CTRL_SET_SALT: - p = va_arg(args, const unsigned char *); - len = va_arg(args, size_t); - if (len == 0 || p == NULL) - return 1; - - OPENSSL_free(impl->salt); - impl->salt = OPENSSL_memdup(p, len); - if (impl->salt == NULL) - return 0; - - impl->salt_len = len; - return 1; - - case EVP_KDF_CTRL_SET_KEY: - p = va_arg(args, const unsigned char *); - len = va_arg(args, size_t); - OPENSSL_clear_free(impl->key, impl->key_len); - impl->key = OPENSSL_memdup(p, len); - if (impl->key == NULL) - return 0; - - impl->key_len = len; - return 1; - - case EVP_KDF_CTRL_RESET_HKDF_INFO: - OPENSSL_cleanse(impl->info, impl->info_len); - impl->info_len = 0; - return 1; - - case EVP_KDF_CTRL_ADD_HKDF_INFO: - p = va_arg(args, const unsigned char *); - len = va_arg(args, size_t); - if (len == 0 || p == NULL) - return 1; - - if (len > (HKDF_MAXBUF - impl->info_len)) - return 0; + KDF_HKDF *ctx = (KDF_HKDF *)vctx; - memcpy(impl->info + impl->info_len, p, len); - impl->info_len += len; - return 1; - - default: - return -2; - } + OPENSSL_free(ctx->salt); + OPENSSL_clear_free(ctx->key, ctx->key_len); + OPENSSL_cleanse(ctx->info, ctx->info_len); + memset(ctx, 0, sizeof(*ctx)); } -static int kdf_hkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, - const char *value) -{ - if (strcmp(type, "mode") == 0) { - int mode; - - if (strcmp(value, "EXTRACT_AND_EXPAND") == 0) - mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; - else if (strcmp(value, "EXTRACT_ONLY") == 0) - mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; - else if (strcmp(value, "EXPAND_ONLY") == 0) - mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; - else - return 0; - - return call_ctrl(kdf_hkdf_ctrl, impl, EVP_KDF_CTRL_SET_HKDF_MODE, mode); - } - - if (strcmp(type, "digest") == 0) - return kdf_md2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_MD, value); - - if (strcmp(type, "salt") == 0) - return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value); - - if (strcmp(type, "hexsalt") == 0) - return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value); - - if (strcmp(type, "key") == 0) - return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value); - - if (strcmp(type, "hexkey") == 0) - return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value); - - if (strcmp(type, "info") == 0) - return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO, - value); - - if (strcmp(type, "hexinfo") == 0) - return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO, - value); - - return -2; -} - -static size_t kdf_hkdf_size(EVP_KDF_IMPL *impl) +static size_t kdf_hkdf_size(KDF_HKDF *ctx) { int sz; - if (impl->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) + if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) return SIZE_MAX; - if (impl->md == NULL) { - KDFerr(KDF_F_KDF_HKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST); + if (ctx->md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); return 0; } - sz = EVP_MD_size(impl->md); + sz = EVP_MD_size(ctx->md); if (sz < 0) return 0; return sz; } -static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, - size_t keylen) +static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen) { - if (impl->md == NULL) { - KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + + if (ctx->md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); return 0; } - if (impl->key == NULL) { - KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_KEY); + if (ctx->key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return 0; } - switch (impl->mode) { + switch (ctx->mode) { case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: - return HKDF(impl->md, impl->salt, impl->salt_len, impl->key, - impl->key_len, impl->info, impl->info_len, key, + return HKDF(ctx->md, ctx->salt, ctx->salt_len, ctx->key, + ctx->key_len, ctx->info, ctx->info_len, key, keylen); case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: - return HKDF_Extract(impl->md, impl->salt, impl->salt_len, impl->key, - impl->key_len, key, keylen); + return HKDF_Extract(ctx->md, ctx->salt, ctx->salt_len, ctx->key, + ctx->key_len, key, keylen); case EVP_KDF_HKDF_MODE_EXPAND_ONLY: - return HKDF_Expand(impl->md, impl->key, impl->key_len, impl->info, - impl->info_len, key, keylen); + return HKDF_Expand(ctx->md, ctx->key, ctx->key_len, ctx->info, + ctx->info_len, key, keylen); default: return 0; } } -const EVP_KDF hkdf_kdf_meth = { - EVP_KDF_HKDF, - kdf_hkdf_new, - kdf_hkdf_free, - kdf_hkdf_reset, - kdf_hkdf_ctrl, - kdf_hkdf_ctrl_str, - kdf_hkdf_size, - kdf_hkdf_derive +static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_HKDF *ctx = vctx; + EVP_MD *md; + int n; + const char *properties = NULL; + + /* Grab search properties, this should be before the digest lookup */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES)) + != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + properties = p->data; + } + /* Handle aliasing of digest parameter names */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data, + properties); + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return 0; + } + EVP_MD_meth_free(ctx->md); + ctx->md = md; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) { + if (p->data_type == OSSL_PARAM_UTF8_STRING) { + if (strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; + } else if (strcasecmp(p->data, "EXTRACT_ONLY") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; + } else if (strcasecmp(p->data, "EXPAND_ONLY") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + } else if (OSSL_PARAM_get_int(p, &n)) { + if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND + && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY + && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + ctx->mode = n; + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) { + OPENSSL_clear_free(ctx->key, ctx->key_len); + ctx->key = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0, + &ctx->key_len)) + return 0; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { + if (p->data_size != 0 && p->data != NULL) { + OPENSSL_free(ctx->salt); + ctx->salt = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, + &ctx->salt_len)) + return 0; + } + } + /* The info fields concatenate, so process them all */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) { + ctx->info_len = 0; + for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, + OSSL_KDF_PARAM_INFO)) { + const void *q = ctx->info + ctx->info_len; + size_t sz = 0; + + if (p->data_size != 0 + && p->data != NULL + && !OSSL_PARAM_get_octet_string(p, (void **)&q, + HKDF_MAXBUF - ctx->info_len, + &sz)) + return 0; + ctx->info_len += sz; + } + } + return 1; +} + +static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), + OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, kdf_hkdf_size(ctx)); + return -2; +} + +static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_hkdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_hkdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_hkdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, + { 0, NULL } }; /* @@ -325,7 +364,7 @@ static int HKDF_Extract(const EVP_MD *evp_md, if (sz < 0) return 0; if (prk_len != (size_t)sz) { - KDFerr(KDF_F_HKDF_EXTRACT, KDF_R_WRONG_OUTPUT_BUFFER_SIZE); + ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); return 0; } /* calc: PRK = HMAC-Hash(salt, IKM) */ diff --git a/providers/common/kdfs/pbkdf2.c b/providers/common/kdfs/pbkdf2.c index d41689773c..e0b4550d62 100644 --- a/providers/common/kdfs/pbkdf2.c +++ b/providers/common/kdfs/pbkdf2.c @@ -13,9 +13,13 @@ #include <openssl/hmac.h> #include <openssl/evp.h> #include <openssl/kdf.h> +#include <openssl/core_names.h> #include "internal/cryptlib.h" +#include "internal/numbers.h" #include "internal/evp_int.h" -#include "kdf_local.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" /* Constants specified in SP800-132 */ #define KDF_PBKDF2_MIN_KEY_LEN_BITS 112 @@ -32,195 +36,216 @@ # define KDF_PBKDF2_DEFAULT_CHECKS 0 #endif /* FIPS_MODE */ -static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl); -static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl); +static OSSL_OP_kdf_newctx_fn kdf_pbkdf2_new; +static OSSL_OP_kdf_freectx_fn kdf_pbkdf2_free; +static OSSL_OP_kdf_reset_fn kdf_pbkdf2_reset; +static OSSL_OP_kdf_derive_fn kdf_pbkdf2_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_pbkdf2_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params; + static int pbkdf2_derive(const char *pass, size_t passlen, - const unsigned char *salt, int saltlen, int iter, + const unsigned char *salt, int saltlen, uint64_t iter, const EVP_MD *digest, unsigned char *key, size_t keylen, int extra_checks); -struct evp_kdf_impl_st { +typedef struct { + void *provctx; unsigned char *pass; size_t pass_len; unsigned char *salt; size_t salt_len; - int iter; - const EVP_MD *md; + uint64_t iter; + EVP_MD *md; int lower_bound_checks; -}; +} KDF_PBKDF2; -static EVP_KDF_IMPL *kdf_pbkdf2_new(void) +static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx); + +static void *kdf_pbkdf2_new(void *provctx) { - EVP_KDF_IMPL *impl; + KDF_PBKDF2 *ctx; - impl = OPENSSL_zalloc(sizeof(*impl)); - if (impl == NULL) { - KDFerr(KDF_F_KDF_PBKDF2_NEW, ERR_R_MALLOC_FAILURE); + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return NULL; } - kdf_pbkdf2_init(impl); - return impl; + ctx->provctx = provctx; + kdf_pbkdf2_init(ctx); + return ctx; } -static void kdf_pbkdf2_free(EVP_KDF_IMPL *impl) +static void kdf_pbkdf2_free(void *vctx) { - kdf_pbkdf2_reset(impl); - OPENSSL_free(impl); + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; + + kdf_pbkdf2_reset(ctx); + EVP_MD_meth_free(ctx->md); + OPENSSL_free(ctx); } -static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl) +static void kdf_pbkdf2_reset(void *vctx) { - OPENSSL_free(impl->salt); - OPENSSL_clear_free(impl->pass, impl->pass_len); - memset(impl, 0, sizeof(*impl)); - kdf_pbkdf2_init(impl); + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; + + OPENSSL_free(ctx->salt); + OPENSSL_clear_free(ctx->pass, ctx->pass_len); + memset(ctx, 0, sizeof(*ctx)); + kdf_pbkdf2_init(ctx); } -static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl) +static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx) { - impl->iter = PKCS5_DEFAULT_ITER; - impl->md = EVP_sha1(); - impl->lower_bound_checks = KDF_PBKDF2_DEFAULT_CHECKS; + ctx->iter = PKCS5_DEFAULT_ITER; + ctx->md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), SN_sha1, + NULL); + ctx->lower_bound_checks = KDF_PBKDF2_DEFAULT_CHECKS; } static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen, - const unsigned char *new_buffer, - size_t new_buflen) + const OSSL_PARAM *p) { - if (new_buffer == NULL) - return 1; - OPENSSL_clear_free(*buffer, *buflen); + if (p->data_size == 0) { + if ((*buffer = OPENSSL_malloc(1)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + } else if (p->data != NULL) { + *buffer = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen)) + return 0; + } + return 1; +} + +static int kdf_pbkdf2_derive(void *vctx, unsigned char *key, + size_t keylen) +{ + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; - if (new_buflen > 0) { - *buffer = OPENSSL_memdup(new_buffer, new_buflen); - } else { - *buffer = OPENSSL_malloc(1); + if (ctx->pass == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS); + return 0; } - if (*buffer == NULL) { - KDFerr(KDF_F_PBKDF2_SET_MEMBUF, ERR_R_MALLOC_FAILURE); + + if (ctx->salt == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT); return 0; } - *buflen = new_buflen; - return 1; + return pbkdf2_derive((char *)ctx->pass, ctx->pass_len, + ctx->salt, ctx->salt_len, ctx->iter, + ctx->md, key, keylen, ctx->lower_bound_checks); } -static int kdf_pbkdf2_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) +static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { - int iter, pkcs5, min_iter; - const unsigned char *p; - size_t len; - const EVP_MD *md; - - switch (cmd) { - case EVP_KDF_CTRL_SET_PBKDF2_PKCS5_MODE: - pkcs5 = va_arg(args, int); - impl->lower_bound_checks = (pkcs5 == 0) ? 1 : 0; - return 1; - case EVP_KDF_CTRL_SET_PASS: - p = va_arg(args, const unsigned char *); - len = va_arg(args, size_t); - return pbkdf2_set_membuf(&impl->pass, &impl->pass_len, p, len); - - case EVP_KDF_CTRL_SET_SALT: - p = va_arg(args, const unsigned char *); - len = va_arg(args, size_t); - if (impl->lower_bound_checks != 0 && len < KDF_PBKDF2_MIN_SALT_LEN) { - KDFerr(KDF_F_KDF_PBKDF2_CTRL, KDF_R_INVALID_SALT_LEN); + const OSSL_PARAM *p; + KDF_PBKDF2 *ctx = vctx; + EVP_MD *md; + int pkcs5; + uint64_t iter, min_iter; + const char *properties = NULL; + + /* Grab search properties, this should be before the digest lookup */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES)) + != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; - } - return pbkdf2_set_membuf(&impl->salt, &impl->salt_len, p, len); - - case EVP_KDF_CTRL_SET_ITER: - iter = va_arg(args, int); - min_iter = impl->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1; - if (iter < min_iter) { - KDFerr(KDF_F_KDF_PBKDF2_CTRL, KDF_R_INVALID_ITERATION_COUNT); + properties = p->data; + } + /* Handle aliasing of digest parameter names */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) return 0; - } - impl->iter = iter; - return 1; - - case EVP_KDF_CTRL_SET_MD: - md = va_arg(args, const EVP_MD *); + md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data, + properties); if (md == NULL) { - KDFerr(KDF_F_KDF_PBKDF2_CTRL, KDF_R_VALUE_MISSING); + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); return 0; } - - impl->md = md; - return 1; - - default: - return -2; + EVP_MD_meth_free(ctx->md); + ctx->md = md; } -} -static int kdf_pbkdf2_ctrl_str(EVP_KDF_IMPL *impl, const char *type, - const char *value) -{ - if (value == NULL) { - KDFerr(KDF_F_KDF_PBKDF2_CTRL_STR, KDF_R_VALUE_MISSING); - return 0; + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) { + if (!OSSL_PARAM_get_int(p, &pkcs5)) + return 0; + ctx->lower_bound_checks = pkcs5 == 0; } - if (strcmp(type, "pass") == 0) - return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS, - value); - - if (strcmp(type, "hexpass") == 0) - return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS, - value); + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) + if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p)) + return 0; - if (strcmp(type, "salt") == 0) - return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT, - value); + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { + if (ctx->lower_bound_checks != 0 + && p->data_size < KDF_PBKDF2_MIN_SALT_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } + if (!pbkdf2_set_membuf(&ctx->salt, &ctx->salt_len,p)) + return 0; + } - if (strcmp(type, "hexsalt") == 0) - return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT, - value); + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) { + if (!OSSL_PARAM_get_uint64(p, &iter)) + return 0; + min_iter = ctx->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1; + if (iter < min_iter) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT); + return 0; + } + ctx->iter = iter; + } + return 1; +} - if (strcmp(type, "iter") == 0) - return call_ctrl(kdf_pbkdf2_ctrl, impl, EVP_KDF_CTRL_SET_ITER, - atoi(value)); +static const OSSL_PARAM *kdf_pbkdf2_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL), + OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS5, NULL), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} - if (strcmp(type, "digest") == 0) - return kdf_md2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_MD, value); +static int kdf_pbkdf2_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; - if (strcmp(type, "pkcs5") == 0) - return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, - EVP_KDF_CTRL_SET_PBKDF2_PKCS5_MODE, value); + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, SIZE_MAX); return -2; } -static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key, - size_t keylen) +static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(void) { - if (impl->pass == NULL) { - KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_PASS); - return 0; - } - - if (impl->salt == NULL) { - KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_SALT); - return 0; - } - - return pbkdf2_derive((char *)impl->pass, impl->pass_len, - impl->salt, impl->salt_len, impl->iter, - impl->md, key, keylen, impl->lower_bound_checks); + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; } -const EVP_KDF pbkdf2_kdf_meth = { - EVP_KDF_PBKDF2, - kdf_pbkdf2_new, - kdf_pbkdf2_free, - kdf_pbkdf2_reset, - kdf_pbkdf2_ctrl, - kdf_pbkdf2_ctrl_str, - NULL, - kdf_pbkdf2_derive +const OSSL_DISPATCH kdf_pbkdf2_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free }, + { OSSL_FUNC_KDF_RE |