is used.
Fixes #19934
The existing code was looking for the digest size, and then returned
zero.
The example code in EVP_KDF-SS.pod has been corrected to not use a
digest.
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19935)
=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
+This parameter is ignored for KMAC.
+
=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string>
=item "maclen" (B<OSSL_KDF_PARAM_MAC_SIZE>) <unsigned integer>
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[10];
- OSSL_PARAM params[7], *p = params;
+ OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
kctx = EVP_KDF_CTX_new(kdf);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
SN_kmac128, strlen(SN_kmac128));
- *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
- SN_sha256, strlen(SN_sha256));
*p++ = OSSL_PARAM_construct_octet_string(EVP_KDF_CTRL_SET_KEY,
"secret", (size_t)6);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
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)
|| !ossl_prov_digest_copy(&dest->digest, &src->digest))
goto err;
dest->out_len = src->out_len;
+ dest->is_kmac = src->is_kmac;
}
return dest;
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;
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);
if (params == NULL)
return 1;
- if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
- return 0;
-
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 (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
+ return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL
|| (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
+ && TEST_size_t_eq(EVP_KDF_CTX_get_kdf_size(kctx), SIZE_MAX)
&& TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result), params), 0)
&& TEST_mem_eq(result, sizeof(result), output, sizeof(output));
{
int ret;
EVP_KDF_CTX *kctx;
- OSSL_PARAM params[6], *p = params;
+ OSSL_PARAM params[7], *p = params;
unsigned char out[64];
size_t mac_size = 20;
static unsigned char z[] = {
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
(char *)OSSL_MAC_NAME_KMAC128, 0);
+ /* The digest parameter is not needed here and should be ignored */
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)"SHA256", 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, z, sizeof(z));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, other,
sizeof(other));
ret =
TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SSKDF))
- && TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
+ && TEST_size_t_eq(EVP_KDF_CTX_get_kdf_size(kctx), 0)
+ && TEST_int_eq(EVP_KDF_CTX_set_params(kctx, params), 1)
+ /* The bug fix for KMAC returning SIZE_MAX was added in 3.0.8 */
+ && (fips_provider_version_lt(NULL, 3, 0, 8)
+ || TEST_size_t_eq(EVP_KDF_CTX_get_kdf_size(kctx), SIZE_MAX))
+ && TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
EVP_KDF_CTX_free(kctx);