Add support for making all of KBKDF FixedInput fields optional.
Added settable integer parameters OSSL_KDF_PARAM_KBKDF_USE_L, OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR. This is required for CAVS tests that only use a combined blob of inputdata. A test showing this use case has been added. Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/13258)
This commit is contained in:
parent
2c90e80dec
commit
4757a34751
@ -21,15 +21,21 @@ The supported parameters are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
|
||||
|
||||
=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string>
|
||||
|
||||
The mode parameter determines which flavor of KBKDF to use - currently the
|
||||
choices are "counter" and "feedback". "counter" is the default, and will be
|
||||
used if unspecified.
|
||||
|
||||
=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
|
||||
|
||||
The value is either CMAC or HMAC.
|
||||
|
||||
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
|
||||
|
||||
=item "cipher" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
|
||||
=item "cipher" (B<OSSL_KDF_PARAM_CIPHER>) <UTF8 string>
|
||||
|
||||
=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
|
||||
|
||||
=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string>
|
||||
|
||||
@ -39,18 +45,30 @@ The supported parameters are:
|
||||
|
||||
=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string>
|
||||
|
||||
The seed parameter is unused in counter mode.
|
||||
|
||||
=item "use-l" (B<OSSL_KDF_PARAM_KBKDF_USE_L>) <int>
|
||||
|
||||
Set to B<0> to disable use of the optional Fixed Input data 'L' (see SP800-108).
|
||||
The default value of B<1> will be used if unspecified.
|
||||
|
||||
=item "use-separator" (B<OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR>) <int>
|
||||
|
||||
Set to B<0> to disable use of the optional Fixed Input data 'zero separator'
|
||||
(see SP800-108) that is placed between the Label and Context.
|
||||
The default value of B<1> will be used if unspecified.
|
||||
|
||||
=back
|
||||
|
||||
The mode parameter determines which flavor of KBKDF to use - currently the
|
||||
choices are "counter" and "feedback". Counter is the default, and will be
|
||||
used if unspecified. The seed parameter is unused in counter mode.
|
||||
Depending on whether mac is CMAC or HMAC, either digest or cipher is required
|
||||
(respectively) and the other is unused.
|
||||
|
||||
The parameters key, salt, info, and seed correspond to KI, Label, Context, and
|
||||
IV (respectively) in SP800-108. As in that document, salt, info, and seed are
|
||||
optional and may be omitted.
|
||||
|
||||
Depending on whether mac is CMAC or HMAC, either digest or cipher is required
|
||||
(respectively) and the other is unused.
|
||||
"mac", "digest", cipher" and "properties" are described in
|
||||
L<EVP_KDF(3)/PARAMETERS>.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
|
@ -200,6 +200,8 @@ extern "C" {
|
||||
#define OSSL_KDF_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */
|
||||
#define OSSL_KDF_PARAM_CONSTANT "constant" /* octet string */
|
||||
#define OSSL_KDF_PARAM_PKCS12_ID "id" /* int */
|
||||
#define OSSL_KDF_PARAM_KBKDF_USE_L "use-l" /* int */
|
||||
#define OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR "use-separator" /* int */
|
||||
|
||||
/* Known KDF names */
|
||||
#define OSSL_KDF_NAME_HKDF "HKDF"
|
||||
|
@ -68,6 +68,8 @@ typedef struct {
|
||||
size_t context_len;
|
||||
unsigned char *iv;
|
||||
size_t iv_len;
|
||||
int use_l;
|
||||
int use_separator;
|
||||
} KBKDF;
|
||||
|
||||
/* Definitions needed for typechecking. */
|
||||
@ -96,6 +98,12 @@ 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;
|
||||
@ -110,6 +118,7 @@ static void *kbkdf_new(void *provctx)
|
||||
}
|
||||
|
||||
ctx->provctx = provctx;
|
||||
init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@ -135,20 +144,32 @@ static void kbkdf_reset(void *vctx)
|
||||
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)
|
||||
@ -167,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;
|
||||
|
||||
@ -193,7 +214,7 @@ 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())
|
||||
@ -226,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);
|
||||
@ -297,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,
|
||||
@ -322,8 +354,9 @@ static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *provctx)
|
||||
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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018-2020, Oracle and/or its affiliates. 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
|
||||
@ -1051,6 +1051,68 @@ static int test_kdf_kbkdf_8009_prf2(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_CMAC)
|
||||
/*
|
||||
* Test vector taken from
|
||||
* https://csrc.nist.gov/CSRC/media/Projects/
|
||||
* Cryptographic-Algorithm-Validation-Program/documents/KBKDF800-108/CounterMode.zip
|
||||
* Note: Only 32 bit counter is supported ([RLEN=32_BITS])
|
||||
*/
|
||||
static int test_kdf_kbkdf_fixedinfo(void)
|
||||
{
|
||||
int ret;
|
||||
EVP_KDF_CTX *kctx;
|
||||
OSSL_PARAM params[8], *p = params;
|
||||
static char *cipher = "AES128";
|
||||
static char *mac = "CMAC";
|
||||
static char *mode = "COUNTER";
|
||||
int use_l = 0;
|
||||
int use_separator = 0;
|
||||
|
||||
static unsigned char input_key[] = {
|
||||
0xc1, 0x0b, 0x15, 0x2e, 0x8c, 0x97, 0xb7, 0x7e,
|
||||
0x18, 0x70, 0x4e, 0x0f, 0x0b, 0xd3, 0x83, 0x05,
|
||||
};
|
||||
static unsigned char fixed_input[] = {
|
||||
0x98, 0xcd, 0x4c, 0xbb, 0xbe, 0xbe, 0x15, 0xd1,
|
||||
0x7d, 0xc8, 0x6e, 0x6d, 0xba, 0xd8, 0x00, 0xa2,
|
||||
0xdc, 0xbd, 0x64, 0xf7, 0xc7, 0xad, 0x0e, 0x78,
|
||||
0xe9, 0xcf, 0x94, 0xff, 0xdb, 0xa8, 0x9d, 0x03,
|
||||
0xe9, 0x7e, 0xad, 0xf6, 0xc4, 0xf7, 0xb8, 0x06,
|
||||
0xca, 0xf5, 0x2a, 0xa3, 0x8f, 0x09, 0xd0, 0xeb,
|
||||
0x71, 0xd7, 0x1f, 0x49, 0x7b, 0xcc, 0x69, 0x06,
|
||||
0xb4, 0x8d, 0x36, 0xc4,
|
||||
|
||||
};
|
||||
static unsigned char output[] = {
|
||||
0x26, 0xfa, 0xf6, 0x19, 0x08, 0xad, 0x9e, 0xe8,
|
||||
0x81, 0xb8, 0x30, 0x5c, 0x22, 0x1d, 0xb5, 0x3f,
|
||||
};
|
||||
unsigned char result[sizeof(output)] = { 0 };
|
||||
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, cipher, 0);
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, mac, 0);
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, mode, 0);
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, input_key,
|
||||
sizeof(input_key));
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
|
||||
fixed_input, sizeof(fixed_input));
|
||||
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_USE_L, &use_l);
|
||||
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR,
|
||||
&use_separator);
|
||||
*p = OSSL_PARAM_construct_end();
|
||||
|
||||
kctx = get_kdfbyname("KBKDF");
|
||||
ret = TEST_ptr(kctx)
|
||||
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|
||||
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0)
|
||||
&& TEST_mem_eq(result, sizeof(result), output, sizeof(output));
|
||||
|
||||
EVP_KDF_CTX_free(kctx);
|
||||
return ret;
|
||||
}
|
||||
#endif /* OPENSSL_NO_CMAC */
|
||||
|
||||
static int test_kdf_ss_hmac(void)
|
||||
{
|
||||
int ret;
|
||||
@ -1322,6 +1384,9 @@ int setup_tests(void)
|
||||
ADD_TEST(test_kdf_kbkdf_1byte_key);
|
||||
ADD_TEST(test_kdf_kbkdf_8009_prf1);
|
||||
ADD_TEST(test_kdf_kbkdf_8009_prf2);
|
||||
#if !defined(OPENSSL_NO_CMAC)
|
||||
ADD_TEST(test_kdf_kbkdf_fixedinfo);
|
||||
#endif
|
||||
ADD_TEST(test_kdf_get_kdf);
|
||||
ADD_TEST(test_kdf_tls1_prf);
|
||||
ADD_TEST(test_kdf_tls1_prf_invalid_digest);
|
||||
|
Loading…
x
Reference in New Issue
Block a user