#include "prov/securitycheck.h"
#include "internal/e_os.h"
#include "internal/params.h"
+#include "internal/sizes.h"
#define HKDF_MAXBUF 2048
#define HKDF_MAXINFO (32*1024)
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
-/* Gettable context parameters that are common across HKDF and the TLS KDF */
+/*
+ * Gettable context parameters that are common across HKDF and the TLS KDF.
+ * OSSL_KDF_PARAM_KEY is not gettable because it is a secret value.
+ */
#define HKDF_COMMON_GETTABLES \
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), \
+ 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_DIGEST, NULL, 0), \
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0)
typedef struct {
return 0;
}
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
+ const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
+
+ if (md == NULL)
+ return 0;
+ else if (!OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
+ return 0;
+ }
+
+ /* OSSL_KDF_PARAM_MODE has multiple parameter types, so look for all instances */
+ p = params;
+ while ((p = OSSL_PARAM_locate(p, OSSL_KDF_PARAM_MODE)) != NULL) {
+ if (p->data_type == OSSL_PARAM_UTF8_STRING) {
+ switch (ctx->mode) {
+ case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
+ if (!OSSL_PARAM_set_utf8_string(p, "EXTRACT_AND_EXPAND"))
+ return 0;
+ break;
+ case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
+ if (!OSSL_PARAM_set_utf8_string(p, "EXTRACT_ONLY"))
+ return 0;
+ break;
+ case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
+ if (!OSSL_PARAM_set_utf8_string(p, "EXPAND_ONLY"))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ } else if (p->data_type == OSSL_PARAM_INTEGER) {
+ if (!OSSL_PARAM_set_int(p, ctx->mode))
+ return 0;
+ }
+ p++;
+ }
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SALT)) != NULL) {
+ if (ctx->salt == NULL || ctx->salt_len == 0)
+ p->return_size = 0;
+ if (!OSSL_PARAM_set_octet_string(p, ctx->salt, ctx->salt_len))
+ return 0;
+ }
+
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_INFO)) != NULL) {
if (ctx->info == NULL || ctx->info_len == 0)
p->return_size = 0;
#include <openssl/kdf.h>
#include <openssl/core_names.h>
#include "internal/numbers.h"
+#include "internal/sizes.h"
#include "testutil.h"
return ret;
}
-static int do_kdf_hkdf_gettables(int expand_only, int has_digest)
+static int do_kdf_hkdf_gettables(int extract_only, int has_digest)
{
int ret = 0;
size_t sz = 0;
OSSL_PARAM *params;
- OSSL_PARAM params_get[2];
+ OSSL_PARAM params_get[5];
+ char digest[OSSL_MAX_NAME_SIZE];
+ char mode_utf8[OSSL_MAX_NAME_SIZE];
+ int mode_int = -1;
+ char salt[16] = { 0 };
+ char info[16] = { 0 };
const OSSL_PARAM *gettables, *p;
EVP_KDF_CTX *kctx = NULL;
if (!TEST_ptr(params = construct_hkdf_params(
has_digest ? "sha256" : NULL,
"secret", 6, "salt",
- expand_only ? NULL : "label"))
+ extract_only ? NULL : "label"))
|| !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
/* Check OSSL_KDF_PARAM_SIZE is gettable */
if (!TEST_ptr(gettables = EVP_KDF_CTX_gettable_params(kctx))
- || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_SIZE)))
+ || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_SIZE))
+ || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_MODE))
+ || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_DIGEST))
+ || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_SALT))
+ || !TEST_ptr(p = OSSL_PARAM_locate_const(gettables, OSSL_KDF_PARAM_INFO)))
goto err;
/* Get OSSL_KDF_PARAM_SIZE as a size_t */
params_get[1] = OSSL_PARAM_construct_end();
if (has_digest) {
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 1)
- || !TEST_size_t_eq(sz, expand_only ? SHA256_DIGEST_LENGTH : SIZE_MAX))
+ || !TEST_size_t_eq(sz, extract_only ? SHA256_DIGEST_LENGTH : SIZE_MAX))
goto err;
} else {
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 0))
goto err;
}
+ params_get[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, digest,
+ sizeof(digest));
+ params_get[1] = OSSL_PARAM_construct_end();
+ if (has_digest) {
+ if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 1)
+ || !TEST_str_eq(digest, "SHA2-256"))
+ goto err;
+ } else {
+ if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 0))
+ goto err;
+ }
+
+ params_get[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, mode_utf8,
+ sizeof(mode_utf8));
+ params_get[1] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode_int);
+ params_get[2] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, salt, sizeof(salt));
+ params_get[3] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, info, sizeof(info));
+ params_get[4] = OSSL_PARAM_construct_end();
+ if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 1)
+ || !TEST_str_eq(mode_utf8, extract_only ? "EXTRACT_ONLY" : "EXTRACT_AND_EXPAND")
+ || !TEST_int_eq(mode_int, extract_only ? EVP_KDF_HKDF_MODE_EXTRACT_ONLY :
+ EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND)
+ || !TEST_str_eq(info, extract_only ? "" : "label")
+ || !TEST_str_eq(salt, "salt"))
+ goto err;
+
/* Get params returns 1 if an unsupported parameter is requested */
params_get[0] = OSSL_PARAM_construct_end();
if (!TEST_int_eq(EVP_KDF_CTX_get_params(kctx, params_get), 1))
return do_kdf_hkdf_gettables(0, 1);
}
-static int test_kdf_hkdf_gettables_expandonly(void)
+static int test_kdf_hkdf_gettables_extractonly(void)
{
return do_kdf_hkdf_gettables(1, 1);
}
ADD_TEST(test_kdf_hkdf_1byte_key);
ADD_TEST(test_kdf_hkdf_empty_salt);
ADD_TEST(test_kdf_hkdf_gettables);
- ADD_TEST(test_kdf_hkdf_gettables_expandonly);
+ ADD_TEST(test_kdf_hkdf_gettables_extractonly);
ADD_TEST(test_kdf_hkdf_gettables_no_digest);
ADD_TEST(test_kdf_hkdf_derive_set_params_fail);
ADD_TEST(test_kdf_hkdf_set_invalid_mode);