X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=providers%2Fimplementations%2Fkdfs%2Fkbkdf.c;h=1dfae38d376d4b8d6509a124f0bded740ec057a9;hb=a28d06f3e9cbc5594c7985c99a0c6bac5261ae67;hp=acc7d7f47b8f37118f8fd53100e1de6d26d203fe;hpb=3c659415465a29d41cdfb6866683af8690de1527;p=openssl.git diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c index acc7d7f47b..1dfae38d37 100644 --- a/providers/implementations/kdfs/kbkdf.c +++ b/providers/implementations/kdfs/kbkdf.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2019 Red Hat, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -33,14 +33,16 @@ #include #include #include +#include #include "internal/cryptlib.h" #include "crypto/evp.h" #include "internal/numbers.h" +#include "internal/endian.h" #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/provider_util.h" -#include "prov/providercommonerr.h" +#include "prov/providercommon.h" #include "e_os.h" @@ -66,26 +68,27 @@ typedef struct { size_t context_len; unsigned char *iv; size_t iv_len; + int use_l; + int use_separator; } KBKDF; /* Definitions needed for typechecking. */ -static OSSL_OP_kdf_newctx_fn kbkdf_new; -static OSSL_OP_kdf_freectx_fn kbkdf_free; -static OSSL_OP_kdf_reset_fn kbkdf_reset; -static OSSL_OP_kdf_derive_fn kbkdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kbkdf_set_ctx_params; +static OSSL_FUNC_kdf_newctx_fn kbkdf_new; +static OSSL_FUNC_kdf_freectx_fn kbkdf_free; +static OSSL_FUNC_kdf_reset_fn kbkdf_reset; +static OSSL_FUNC_kdf_derive_fn kbkdf_derive; +static OSSL_FUNC_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; +static OSSL_FUNC_kdf_set_ctx_params_fn kbkdf_set_ctx_params; +static OSSL_FUNC_kdf_gettable_ctx_params_fn kbkdf_gettable_ctx_params; +static OSSL_FUNC_kdf_get_ctx_params_fn kbkdf_get_ctx_params; /* Not all platforms have htobe32(). */ static uint32_t be32(uint32_t host) { uint32_t big = 0; - const union { - long one; - char little; - } is_endian = { 1 }; + DECLARE_IS_ENDIAN; - if (!is_endian.little) + if (!IS_LITTLE_ENDIAN) return host; big |= (host & 0xff000000) >> 24; @@ -95,10 +98,19 @@ static uint32_t be32(uint32_t host) return big; } +static void init(KBKDF *ctx) +{ + ctx->use_l = 1; + ctx->use_separator = 1; +} + static void *kbkdf_new(void *provctx) { KBKDF *ctx; + if (!ossl_prov_is_running()) + return NULL; + ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -106,6 +118,7 @@ static void *kbkdf_new(void *provctx) } ctx->provctx = provctx; + init(ctx); return ctx; } @@ -122,6 +135,7 @@ static void kbkdf_free(void *vctx) static void kbkdf_reset(void *vctx) { KBKDF *ctx = (KBKDF *)vctx; + void *provctx = ctx->provctx; EVP_MAC_CTX_free(ctx->ctx_init); OPENSSL_clear_free(ctx->context, ctx->context_len); @@ -129,20 +143,33 @@ static void kbkdf_reset(void *vctx) OPENSSL_clear_free(ctx->ki, ctx->ki_len); OPENSSL_clear_free(ctx->iv, ctx->iv_len); memset(ctx, 0, sizeof(*ctx)); + ctx->provctx = provctx; + init(ctx); } /* SP800-108 section 5.1 or section 5.2 depending on mode. */ static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv, size_t iv_len, unsigned char *label, size_t label_len, unsigned char *context, size_t context_len, - unsigned char *k_i, size_t h, uint32_t l, unsigned char *ko, - size_t ko_len) + unsigned char *k_i, size_t h, uint32_t l, int has_separator, + unsigned char *ko, size_t ko_len) { int ret = 0; EVP_MAC_CTX *ctx = NULL; size_t written = 0, to_write, k_i_len = iv_len; const unsigned char zero = 0; uint32_t counter, i; + /* + * From SP800-108: + * The fixed input data is a concatenation of a Label, + * a separation indicator 0x00, the Context, and L. + * One or more of these fixed input data fields may be omitted. + * + * has_separator == 0 means that the separator is omitted. + * Passing a value of l == 0 means that L is omitted. + * The Context and L are omitted automatically if a NULL buffer is passed. + */ + int has_l = (l != 0); /* Setup K(0) for feedback mode. */ if (iv_len > 0) @@ -161,9 +188,9 @@ static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv, if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4) || !EVP_MAC_update(ctx, label, label_len) - || !EVP_MAC_update(ctx, &zero, 1) + || (has_separator && !EVP_MAC_update(ctx, &zero, 1)) || !EVP_MAC_update(ctx, context, context_len) - || !EVP_MAC_update(ctx, (unsigned char *)&l, 4) + || (has_l && !EVP_MAC_update(ctx, (unsigned char *)&l, 4)) || !EVP_MAC_final(ctx, k_i, NULL, h)) goto done; @@ -187,9 +214,12 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) KBKDF *ctx = (KBKDF *)vctx; int ret = 0; unsigned char *k_i = NULL; - uint32_t l = be32(keylen * 8); + uint32_t l = 0; size_t h = 0; + if (!ossl_prov_is_running()) + return 0; + /* label, context, and iv are permitted to be empty. Check everything * else. */ if (ctx->ctx_init == NULL) { @@ -203,7 +233,13 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) return 0; } - h = EVP_MAC_size(ctx->ctx_init); + /* Fail if the output length is zero */ + if (keylen == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + + h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init); if (h == 0) goto done; if (ctx->iv_len != 0 && ctx->iv_len != h) { @@ -211,13 +247,16 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) goto done; } + if (ctx->use_l != 0) + l = be32(keylen * 8); + k_i = OPENSSL_zalloc(h); if (k_i == NULL) goto done; ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label, ctx->label_len, ctx->context, ctx->context_len, k_i, h, l, - key, keylen); + ctx->use_separator, key, keylen); done: if (ret != 1) OPENSSL_cleanse(key, keylen); @@ -239,7 +278,7 @@ static int kbkdf_set_buffer(unsigned char **out, size_t *out_len, static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { KBKDF *ctx = (KBKDF *)vctx; - OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); const OSSL_PARAM *p; OSSL_PARAM mparams[2]; @@ -282,6 +321,14 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (p != NULL && !kbkdf_set_buffer(&ctx->iv, &ctx->iv_len, p)) return 0; + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_L); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_l)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_separator)) + return 0; + /* Set up digest context, if we can. */ if (ctx->ctx_init != NULL && ctx->ki_len != 0) { mparams[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, @@ -296,7 +343,7 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 1; } -static const OSSL_PARAM *kbkdf_settable_ctx_params(void) +static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *provctx) { static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), @@ -307,8 +354,9 @@ static const OSSL_PARAM *kbkdf_settable_ctx_params(void) OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_L, NULL), + OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR, NULL), OSSL_PARAM_END, }; return known_settable_ctx_params; @@ -326,14 +374,14 @@ static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) return OSSL_PARAM_set_size_t(p, SIZE_MAX); } -static const OSSL_PARAM *kbkdf_gettable_ctx_params(void) +static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *provctx) { 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_kbkdf_functions[] = { +const OSSL_DISPATCH ossl_kdf_kbkdf_functions[] = { { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new }, { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free }, { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset },