X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=providers%2Fimplementations%2Fkdfs%2Fsskdf.c;h=56ac1e6334027393d030049392ff36de638bcedc;hp=22c65d26ba736dd0cf14b99b46f7b815efde32f1;hb=HEAD;hpb=2b9e4e956b37ee49b29a73c7782f525ac8c58cc5 diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c index 22c65d26ba..db750a4f23 100644 --- a/providers/implementations/kdfs/sskdf.c +++ b/providers/implementations/kdfs/sskdf.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -42,14 +42,15 @@ #include #include #include +#include #include "internal/cryptlib.h" #include "internal/numbers.h" #include "crypto/evp.h" #include "prov/provider_ctx.h" #include "prov/providercommon.h" -#include "prov/providercommonerr.h" #include "prov/implementations.h" #include "prov/provider_util.h" +#include "internal/params.h" typedef struct { void *provctx; @@ -62,6 +63,7 @@ typedef struct { unsigned char *salt; size_t salt_len; size_t out_len; /* optional KMAC parameter */ + int is_kmac; } KDF_SSKDF; #define SSKDF_MAX_INLEN (1<<30) @@ -72,6 +74,7 @@ typedef struct { static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; static OSSL_FUNC_kdf_newctx_fn sskdf_new; +static OSSL_FUNC_kdf_dupctx_fn sskdf_dup; static OSSL_FUNC_kdf_freectx_fn sskdf_free; static OSSL_FUNC_kdf_reset_fn sskdf_reset; static OSSL_FUNC_kdf_derive_fn sskdf_derive; @@ -108,7 +111,7 @@ static int SSKDF_hash_kdm(const EVP_MD *kdf_md, || derived_key_len == 0) return 0; - hlen = EVP_MD_size(kdf_md); + hlen = EVP_MD_get_size(kdf_md); if (hlen <= 0) return 0; out_len = (size_t)hlen; @@ -223,31 +226,23 @@ static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, unsigned char *out = derived_key; EVP_MAC_CTX *ctx = NULL; unsigned char *mac = mac_buf, *kmac_buffer = NULL; - OSSL_PARAM params[2], *p = params; if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN || derived_key_len > SSKDF_MAX_INLEN || derived_key_len == 0) return 0; - *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - (void *)salt, salt_len); - *p = OSSL_PARAM_construct_end(); - - if (!EVP_MAC_CTX_set_params(ctx_init, params)) - goto end; - if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, derived_key_len, &kmac_buffer)) goto end; if (kmac_buffer != NULL) mac = kmac_buffer; - if (!EVP_MAC_init(ctx_init)) + if (!EVP_MAC_init(ctx_init, salt, salt_len, NULL)) goto end; - out_len = EVP_MAC_size(ctx_init); /* output size */ - if (out_len <= 0) + out_len = EVP_MAC_CTX_get_mac_size(ctx_init); /* output size */ + if (out_len <= 0 || (mac == mac_buf && out_len > sizeof(mac_buf))) goto end; len = derived_key_len; @@ -271,7 +266,7 @@ static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, if (len == 0) break; } else { - if (!EVP_MAC_final(ctx, mac, NULL, len)) + if (!EVP_MAC_final(ctx, mac, NULL, out_len)) goto end; memcpy(out, mac, len); break; @@ -297,9 +292,8 @@ static void *sskdf_new(void *provctx) if (!ossl_prov_is_running()) return NULL; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - ctx->provctx = provctx; + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) + ctx->provctx = provctx; return ctx; } @@ -327,35 +321,60 @@ static void sskdf_free(void *vctx) } } -static int sskdf_set_buffer(unsigned char **out, size_t *out_len, - const OSSL_PARAM *p) +static void *sskdf_dup(void *vctx) { - if (p->data == NULL || p->data_size == 0) - return 1; - OPENSSL_free(*out); - *out = NULL; - return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); + const KDF_SSKDF *src = (const KDF_SSKDF *)vctx; + KDF_SSKDF *dest; + + dest = sskdf_new(src->provctx); + if (dest != NULL) { + if (src->macctx != NULL) { + dest->macctx = EVP_MAC_CTX_dup(src->macctx); + if (dest->macctx == NULL) + goto err; + } + if (!ossl_prov_memdup(src->info, src->info_len, + &dest->info, &dest->info_len) + || !ossl_prov_memdup(src->salt, src->salt_len, + &dest->salt , &dest->salt_len) + || !ossl_prov_memdup(src->secret, src->secret_len, + &dest->secret, &dest->secret_len) + || !ossl_prov_digest_copy(&dest->digest, &src->digest)) + goto err; + dest->out_len = src->out_len; + dest->is_kmac = src->is_kmac; + } + return dest; + + err: + sskdf_free(dest); + return NULL; } static size_t sskdf_size(KDF_SSKDF *ctx) { int len; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + const EVP_MD *md = NULL; + + if (ctx->is_kmac) + return SIZE_MAX; + md = ossl_prov_digest_md(&ctx->digest); if (md == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); return 0; } - len = EVP_MD_size(md); + len = EVP_MD_get_size(md); return (len <= 0) ? 0 : (size_t)len; } -static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) +static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen, + const OSSL_PARAM params[]) { KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; const EVP_MD *md; - if (!ossl_prov_is_running()) + if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params)) return 0; if (ctx->secret == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); @@ -369,24 +388,18 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) const unsigned char *custom = NULL; size_t custom_len = 0; int default_salt_len; - EVP_MAC *mac = EVP_MAC_CTX_mac(ctx->macctx); + EVP_MAC *mac = EVP_MAC_CTX_get0_mac(ctx->macctx); - /* - * TODO(3.0) investigate the necessity to have all these controls. - * Why does KMAC require a salt length that's shorter than the MD - * block size? - */ if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) { /* H(x) = HMAC(x, salt, hash) */ if (md == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); return 0; } - default_salt_len = EVP_MD_size(md); + default_salt_len = EVP_MD_get_size(md); if (default_salt_len <= 0) return 0; - } else if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128) - || EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC256)) { + } else if (ctx->is_kmac) { /* H(x) = KMACzzz(x, salt, custom) */ custom = kmac_custom_str; custom_len = sizeof(kmac_custom_str); @@ -401,10 +414,8 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) /* If no salt is set then use a default_salt of zeros */ if (ctx->salt == NULL || ctx->salt_len <= 0) { ctx->salt = OPENSSL_zalloc(default_salt_len); - if (ctx->salt == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + if (ctx->salt == NULL) return 0; - } ctx->salt_len = default_salt_len; } ret = SSKDF_mac_kdm(ctx->macctx, @@ -424,12 +435,13 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) } } -static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen) +static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen, + const OSSL_PARAM params[]) { KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; const EVP_MD *md; - if (!ossl_prov_is_running()) + if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params)) return 0; if (ctx->secret == NULL) { @@ -457,27 +469,42 @@ static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { const OSSL_PARAM *p; KDF_SSKDF *ctx = vctx; - OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); size_t sz; + int r; - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) - return 0; + if (params == NULL) + return 1; if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params, NULL, NULL, NULL, libctx)) return 0; + if (ctx->macctx != NULL) { + if (EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), + OSSL_MAC_NAME_KMAC128) + || EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), + OSSL_MAC_NAME_KMAC256)) { + ctx->is_kmac = 1; + } + } - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL - || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) - if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) - return 0; + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) + return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) - if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p)) - return 0; + r = ossl_param_get1_octet_string(params, OSSL_KDF_PARAM_SECRET, + &ctx->secret, &ctx->secret_len); + if (r == -1) + r = ossl_param_get1_octet_string(params, OSSL_KDF_PARAM_KEY, + &ctx->secret, &ctx->secret_len); + if (r == 0) + return 0; + + if (ossl_param_get1_concat_octet_string(params, OSSL_KDF_PARAM_INFO, + &ctx->info, &ctx->info_len, 0) == 0) + return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) - if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p)) + if (ossl_param_get1_octet_string(params, OSSL_KDF_PARAM_SALT, + &ctx->salt, &ctx->salt_len) == 0) return 0; if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE)) @@ -489,7 +516,8 @@ static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 1; } -static const OSSL_PARAM *sskdf_settable_ctx_params(ossl_unused void *provctx) +static const OSSL_PARAM *sskdf_settable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) { static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), @@ -515,7 +543,8 @@ static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) return -2; } -static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *provctx) +static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) { static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), @@ -524,8 +553,9 @@ static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *provctx) return known_gettable_ctx_params; } -const OSSL_DISPATCH kdf_sskdf_functions[] = { +const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = { { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, + { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup }, { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive }, @@ -535,11 +565,12 @@ const OSSL_DISPATCH kdf_sskdf_functions[] = { { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void(*)(void))sskdf_gettable_ctx_params }, { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, - { 0, NULL } + OSSL_DISPATCH_END }; -const OSSL_DISPATCH kdf_x963_kdf_functions[] = { +const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = { { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, + { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup }, { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, @@ -549,5 +580,5 @@ const OSSL_DISPATCH kdf_x963_kdf_functions[] = { { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void(*)(void))sskdf_gettable_ctx_params }, { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, - { 0, NULL } + OSSL_DISPATCH_END };