1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci/* 12e1051a39Sopenharmony_ci * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final 13e1051a39Sopenharmony_ci * Section 4.1. 14e1051a39Sopenharmony_ci * 15e1051a39Sopenharmony_ci * The Single Step KDF algorithm is given by: 16e1051a39Sopenharmony_ci * 17e1051a39Sopenharmony_ci * Result(0) = empty bit string (i.e., the null string). 18e1051a39Sopenharmony_ci * For i = 1 to reps, do the following: 19e1051a39Sopenharmony_ci * Increment counter by 1. 20e1051a39Sopenharmony_ci * Result(i) = Result(i - 1) || H(counter || Z || FixedInfo). 21e1051a39Sopenharmony_ci * DKM = LeftmostBits(Result(reps), L)) 22e1051a39Sopenharmony_ci * 23e1051a39Sopenharmony_ci * NOTES: 24e1051a39Sopenharmony_ci * Z is a shared secret required to produce the derived key material. 25e1051a39Sopenharmony_ci * counter is a 4 byte buffer. 26e1051a39Sopenharmony_ci * FixedInfo is a bit string containing context specific data. 27e1051a39Sopenharmony_ci * DKM is the output derived key material. 28e1051a39Sopenharmony_ci * L is the required size of the DKM. 29e1051a39Sopenharmony_ci * reps = [L / H_outputBits] 30e1051a39Sopenharmony_ci * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC. 31e1051a39Sopenharmony_ci * H_outputBits is the length of the output of the auxiliary function H(x). 32e1051a39Sopenharmony_ci * 33e1051a39Sopenharmony_ci * Currently there is not a comprehensive list of test vectors for this 34e1051a39Sopenharmony_ci * algorithm, especially for H(x) = HMAC and H(x) = KMAC. 35e1051a39Sopenharmony_ci * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests. 36e1051a39Sopenharmony_ci */ 37e1051a39Sopenharmony_ci#include <stdlib.h> 38e1051a39Sopenharmony_ci#include <stdarg.h> 39e1051a39Sopenharmony_ci#include <string.h> 40e1051a39Sopenharmony_ci#include <openssl/hmac.h> 41e1051a39Sopenharmony_ci#include <openssl/evp.h> 42e1051a39Sopenharmony_ci#include <openssl/kdf.h> 43e1051a39Sopenharmony_ci#include <openssl/core_names.h> 44e1051a39Sopenharmony_ci#include <openssl/params.h> 45e1051a39Sopenharmony_ci#include <openssl/proverr.h> 46e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 47e1051a39Sopenharmony_ci#include "internal/numbers.h" 48e1051a39Sopenharmony_ci#include "crypto/evp.h" 49e1051a39Sopenharmony_ci#include "prov/provider_ctx.h" 50e1051a39Sopenharmony_ci#include "prov/providercommon.h" 51e1051a39Sopenharmony_ci#include "prov/implementations.h" 52e1051a39Sopenharmony_ci#include "prov/provider_util.h" 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_citypedef struct { 55e1051a39Sopenharmony_ci void *provctx; 56e1051a39Sopenharmony_ci EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */ 57e1051a39Sopenharmony_ci PROV_DIGEST digest; /* H(x) = hash(x) */ 58e1051a39Sopenharmony_ci unsigned char *secret; 59e1051a39Sopenharmony_ci size_t secret_len; 60e1051a39Sopenharmony_ci unsigned char *info; 61e1051a39Sopenharmony_ci size_t info_len; 62e1051a39Sopenharmony_ci unsigned char *salt; 63e1051a39Sopenharmony_ci size_t salt_len; 64e1051a39Sopenharmony_ci size_t out_len; /* optional KMAC parameter */ 65e1051a39Sopenharmony_ci int is_kmac; 66e1051a39Sopenharmony_ci} KDF_SSKDF; 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci#define SSKDF_MAX_INLEN (1<<30) 69e1051a39Sopenharmony_ci#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4) 70e1051a39Sopenharmony_ci#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4) 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci/* KMAC uses a Customisation string of 'KDF' */ 73e1051a39Sopenharmony_cistatic const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_newctx_fn sskdf_new; 76e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_freectx_fn sskdf_free; 77e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_reset_fn sskdf_reset; 78e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn sskdf_derive; 79e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn x963kdf_derive; 80e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_settable_ctx_params_fn sskdf_settable_ctx_params; 81e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_set_ctx_params_fn sskdf_set_ctx_params; 82e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params; 83e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_get_ctx_params_fn sskdf_get_ctx_params; 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci/* 86e1051a39Sopenharmony_ci * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final 87e1051a39Sopenharmony_ci * Section 4. One-Step Key Derivation using H(x) = hash(x) 88e1051a39Sopenharmony_ci * Note: X9.63 also uses this code with the only difference being that the 89e1051a39Sopenharmony_ci * counter is appended to the secret 'z'. 90e1051a39Sopenharmony_ci * i.e. 91e1051a39Sopenharmony_ci * result[i] = Hash(counter || z || info) for One Step OR 92e1051a39Sopenharmony_ci * result[i] = Hash(z || counter || info) for X9.63. 93e1051a39Sopenharmony_ci */ 94e1051a39Sopenharmony_cistatic int SSKDF_hash_kdm(const EVP_MD *kdf_md, 95e1051a39Sopenharmony_ci const unsigned char *z, size_t z_len, 96e1051a39Sopenharmony_ci const unsigned char *info, size_t info_len, 97e1051a39Sopenharmony_ci unsigned int append_ctr, 98e1051a39Sopenharmony_ci unsigned char *derived_key, size_t derived_key_len) 99e1051a39Sopenharmony_ci{ 100e1051a39Sopenharmony_ci int ret = 0, hlen; 101e1051a39Sopenharmony_ci size_t counter, out_len, len = derived_key_len; 102e1051a39Sopenharmony_ci unsigned char c[4]; 103e1051a39Sopenharmony_ci unsigned char mac[EVP_MAX_MD_SIZE]; 104e1051a39Sopenharmony_ci unsigned char *out = derived_key; 105e1051a39Sopenharmony_ci EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN 108e1051a39Sopenharmony_ci || derived_key_len > SSKDF_MAX_INLEN 109e1051a39Sopenharmony_ci || derived_key_len == 0) 110e1051a39Sopenharmony_ci return 0; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci hlen = EVP_MD_get_size(kdf_md); 113e1051a39Sopenharmony_ci if (hlen <= 0) 114e1051a39Sopenharmony_ci return 0; 115e1051a39Sopenharmony_ci out_len = (size_t)hlen; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci ctx = EVP_MD_CTX_create(); 118e1051a39Sopenharmony_ci ctx_init = EVP_MD_CTX_create(); 119e1051a39Sopenharmony_ci if (ctx == NULL || ctx_init == NULL) 120e1051a39Sopenharmony_ci goto end; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci if (!EVP_DigestInit(ctx_init, kdf_md)) 123e1051a39Sopenharmony_ci goto end; 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci for (counter = 1;; counter++) { 126e1051a39Sopenharmony_ci c[0] = (unsigned char)((counter >> 24) & 0xff); 127e1051a39Sopenharmony_ci c[1] = (unsigned char)((counter >> 16) & 0xff); 128e1051a39Sopenharmony_ci c[2] = (unsigned char)((counter >> 8) & 0xff); 129e1051a39Sopenharmony_ci c[3] = (unsigned char)(counter & 0xff); 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init) 132e1051a39Sopenharmony_ci && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) 133e1051a39Sopenharmony_ci && EVP_DigestUpdate(ctx, z, z_len) 134e1051a39Sopenharmony_ci && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) 135e1051a39Sopenharmony_ci && EVP_DigestUpdate(ctx, info, info_len))) 136e1051a39Sopenharmony_ci goto end; 137e1051a39Sopenharmony_ci if (len >= out_len) { 138e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(ctx, out, NULL)) 139e1051a39Sopenharmony_ci goto end; 140e1051a39Sopenharmony_ci out += out_len; 141e1051a39Sopenharmony_ci len -= out_len; 142e1051a39Sopenharmony_ci if (len == 0) 143e1051a39Sopenharmony_ci break; 144e1051a39Sopenharmony_ci } else { 145e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(ctx, mac, NULL)) 146e1051a39Sopenharmony_ci goto end; 147e1051a39Sopenharmony_ci memcpy(out, mac, len); 148e1051a39Sopenharmony_ci break; 149e1051a39Sopenharmony_ci } 150e1051a39Sopenharmony_ci } 151e1051a39Sopenharmony_ci ret = 1; 152e1051a39Sopenharmony_ciend: 153e1051a39Sopenharmony_ci EVP_MD_CTX_destroy(ctx); 154e1051a39Sopenharmony_ci EVP_MD_CTX_destroy(ctx_init); 155e1051a39Sopenharmony_ci OPENSSL_cleanse(mac, sizeof(mac)); 156e1051a39Sopenharmony_ci return ret; 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_cistatic int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, 160e1051a39Sopenharmony_ci size_t custom_len, size_t kmac_out_len, 161e1051a39Sopenharmony_ci size_t derived_key_len, unsigned char **out) 162e1051a39Sopenharmony_ci{ 163e1051a39Sopenharmony_ci OSSL_PARAM params[2]; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci /* Only KMAC has custom data - so return if not KMAC */ 166e1051a39Sopenharmony_ci if (custom == NULL) 167e1051a39Sopenharmony_ci return 1; 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, 170e1051a39Sopenharmony_ci (void *)custom, custom_len); 171e1051a39Sopenharmony_ci params[1] = OSSL_PARAM_construct_end(); 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci if (!EVP_MAC_CTX_set_params(ctx, params)) 174e1051a39Sopenharmony_ci return 0; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci /* By default only do one iteration if kmac_out_len is not specified */ 177e1051a39Sopenharmony_ci if (kmac_out_len == 0) 178e1051a39Sopenharmony_ci kmac_out_len = derived_key_len; 179e1051a39Sopenharmony_ci /* otherwise check the size is valid */ 180e1051a39Sopenharmony_ci else if (!(kmac_out_len == derived_key_len 181e1051a39Sopenharmony_ci || kmac_out_len == 20 182e1051a39Sopenharmony_ci || kmac_out_len == 28 183e1051a39Sopenharmony_ci || kmac_out_len == 32 184e1051a39Sopenharmony_ci || kmac_out_len == 48 185e1051a39Sopenharmony_ci || kmac_out_len == 64)) 186e1051a39Sopenharmony_ci return 0; 187e1051a39Sopenharmony_ci 188e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, 189e1051a39Sopenharmony_ci &kmac_out_len); 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci if (EVP_MAC_CTX_set_params(ctx, params) <= 0) 192e1051a39Sopenharmony_ci return 0; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci /* 195e1051a39Sopenharmony_ci * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so 196e1051a39Sopenharmony_ci * alloc a buffer for this case. 197e1051a39Sopenharmony_ci */ 198e1051a39Sopenharmony_ci if (kmac_out_len > EVP_MAX_MD_SIZE) { 199e1051a39Sopenharmony_ci *out = OPENSSL_zalloc(kmac_out_len); 200e1051a39Sopenharmony_ci if (*out == NULL) 201e1051a39Sopenharmony_ci return 0; 202e1051a39Sopenharmony_ci } 203e1051a39Sopenharmony_ci return 1; 204e1051a39Sopenharmony_ci} 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci/* 207e1051a39Sopenharmony_ci * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final 208e1051a39Sopenharmony_ci * Section 4. One-Step Key Derivation using MAC: i.e either 209e1051a39Sopenharmony_ci * H(x) = HMAC-hash(salt, x) OR 210e1051a39Sopenharmony_ci * H(x) = KMAC#(salt, x, outbits, CustomString='KDF') 211e1051a39Sopenharmony_ci */ 212e1051a39Sopenharmony_cistatic int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, 213e1051a39Sopenharmony_ci const unsigned char *kmac_custom, 214e1051a39Sopenharmony_ci size_t kmac_custom_len, size_t kmac_out_len, 215e1051a39Sopenharmony_ci const unsigned char *salt, size_t salt_len, 216e1051a39Sopenharmony_ci const unsigned char *z, size_t z_len, 217e1051a39Sopenharmony_ci const unsigned char *info, size_t info_len, 218e1051a39Sopenharmony_ci unsigned char *derived_key, size_t derived_key_len) 219e1051a39Sopenharmony_ci{ 220e1051a39Sopenharmony_ci int ret = 0; 221e1051a39Sopenharmony_ci size_t counter, out_len, len; 222e1051a39Sopenharmony_ci unsigned char c[4]; 223e1051a39Sopenharmony_ci unsigned char mac_buf[EVP_MAX_MD_SIZE]; 224e1051a39Sopenharmony_ci unsigned char *out = derived_key; 225e1051a39Sopenharmony_ci EVP_MAC_CTX *ctx = NULL; 226e1051a39Sopenharmony_ci unsigned char *mac = mac_buf, *kmac_buffer = NULL; 227e1051a39Sopenharmony_ci 228e1051a39Sopenharmony_ci if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN 229e1051a39Sopenharmony_ci || derived_key_len > SSKDF_MAX_INLEN 230e1051a39Sopenharmony_ci || derived_key_len == 0) 231e1051a39Sopenharmony_ci return 0; 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, 234e1051a39Sopenharmony_ci derived_key_len, &kmac_buffer)) 235e1051a39Sopenharmony_ci goto end; 236e1051a39Sopenharmony_ci if (kmac_buffer != NULL) 237e1051a39Sopenharmony_ci mac = kmac_buffer; 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci if (!EVP_MAC_init(ctx_init, salt, salt_len, NULL)) 240e1051a39Sopenharmony_ci goto end; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci out_len = EVP_MAC_CTX_get_mac_size(ctx_init); /* output size */ 243e1051a39Sopenharmony_ci if (out_len <= 0 || (mac == mac_buf && out_len > sizeof(mac_buf))) 244e1051a39Sopenharmony_ci goto end; 245e1051a39Sopenharmony_ci len = derived_key_len; 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ci for (counter = 1;; counter++) { 248e1051a39Sopenharmony_ci c[0] = (unsigned char)((counter >> 24) & 0xff); 249e1051a39Sopenharmony_ci c[1] = (unsigned char)((counter >> 16) & 0xff); 250e1051a39Sopenharmony_ci c[2] = (unsigned char)((counter >> 8) & 0xff); 251e1051a39Sopenharmony_ci c[3] = (unsigned char)(counter & 0xff); 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ci ctx = EVP_MAC_CTX_dup(ctx_init); 254e1051a39Sopenharmony_ci if (!(ctx != NULL 255e1051a39Sopenharmony_ci && EVP_MAC_update(ctx, c, sizeof(c)) 256e1051a39Sopenharmony_ci && EVP_MAC_update(ctx, z, z_len) 257e1051a39Sopenharmony_ci && EVP_MAC_update(ctx, info, info_len))) 258e1051a39Sopenharmony_ci goto end; 259e1051a39Sopenharmony_ci if (len >= out_len) { 260e1051a39Sopenharmony_ci if (!EVP_MAC_final(ctx, out, NULL, len)) 261e1051a39Sopenharmony_ci goto end; 262e1051a39Sopenharmony_ci out += out_len; 263e1051a39Sopenharmony_ci len -= out_len; 264e1051a39Sopenharmony_ci if (len == 0) 265e1051a39Sopenharmony_ci break; 266e1051a39Sopenharmony_ci } else { 267e1051a39Sopenharmony_ci if (!EVP_MAC_final(ctx, mac, NULL, out_len)) 268e1051a39Sopenharmony_ci goto end; 269e1051a39Sopenharmony_ci memcpy(out, mac, len); 270e1051a39Sopenharmony_ci break; 271e1051a39Sopenharmony_ci } 272e1051a39Sopenharmony_ci EVP_MAC_CTX_free(ctx); 273e1051a39Sopenharmony_ci ctx = NULL; 274e1051a39Sopenharmony_ci } 275e1051a39Sopenharmony_ci ret = 1; 276e1051a39Sopenharmony_ciend: 277e1051a39Sopenharmony_ci if (kmac_buffer != NULL) 278e1051a39Sopenharmony_ci OPENSSL_clear_free(kmac_buffer, kmac_out_len); 279e1051a39Sopenharmony_ci else 280e1051a39Sopenharmony_ci OPENSSL_cleanse(mac_buf, sizeof(mac_buf)); 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci EVP_MAC_CTX_free(ctx); 283e1051a39Sopenharmony_ci return ret; 284e1051a39Sopenharmony_ci} 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_cistatic void *sskdf_new(void *provctx) 287e1051a39Sopenharmony_ci{ 288e1051a39Sopenharmony_ci KDF_SSKDF *ctx; 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 291e1051a39Sopenharmony_ci return NULL; 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ci if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) 294e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 295e1051a39Sopenharmony_ci ctx->provctx = provctx; 296e1051a39Sopenharmony_ci return ctx; 297e1051a39Sopenharmony_ci} 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_cistatic void sskdf_reset(void *vctx) 300e1051a39Sopenharmony_ci{ 301e1051a39Sopenharmony_ci KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; 302e1051a39Sopenharmony_ci void *provctx = ctx->provctx; 303e1051a39Sopenharmony_ci 304e1051a39Sopenharmony_ci EVP_MAC_CTX_free(ctx->macctx); 305e1051a39Sopenharmony_ci ossl_prov_digest_reset(&ctx->digest); 306e1051a39Sopenharmony_ci OPENSSL_clear_free(ctx->secret, ctx->secret_len); 307e1051a39Sopenharmony_ci OPENSSL_clear_free(ctx->info, ctx->info_len); 308e1051a39Sopenharmony_ci OPENSSL_clear_free(ctx->salt, ctx->salt_len); 309e1051a39Sopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 310e1051a39Sopenharmony_ci ctx->provctx = provctx; 311e1051a39Sopenharmony_ci} 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_cistatic void sskdf_free(void *vctx) 314e1051a39Sopenharmony_ci{ 315e1051a39Sopenharmony_ci KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ci if (ctx != NULL) { 318e1051a39Sopenharmony_ci sskdf_reset(ctx); 319e1051a39Sopenharmony_ci OPENSSL_free(ctx); 320e1051a39Sopenharmony_ci } 321e1051a39Sopenharmony_ci} 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_cistatic int sskdf_set_buffer(unsigned char **out, size_t *out_len, 324e1051a39Sopenharmony_ci const OSSL_PARAM *p) 325e1051a39Sopenharmony_ci{ 326e1051a39Sopenharmony_ci if (p->data == NULL || p->data_size == 0) 327e1051a39Sopenharmony_ci return 1; 328e1051a39Sopenharmony_ci OPENSSL_free(*out); 329e1051a39Sopenharmony_ci *out = NULL; 330e1051a39Sopenharmony_ci return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); 331e1051a39Sopenharmony_ci} 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_cistatic size_t sskdf_size(KDF_SSKDF *ctx) 334e1051a39Sopenharmony_ci{ 335e1051a39Sopenharmony_ci int len; 336e1051a39Sopenharmony_ci const EVP_MD *md = NULL; 337e1051a39Sopenharmony_ci 338e1051a39Sopenharmony_ci if (ctx->is_kmac) 339e1051a39Sopenharmony_ci return SIZE_MAX; 340e1051a39Sopenharmony_ci 341e1051a39Sopenharmony_ci md = ossl_prov_digest_md(&ctx->digest); 342e1051a39Sopenharmony_ci if (md == NULL) { 343e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); 344e1051a39Sopenharmony_ci return 0; 345e1051a39Sopenharmony_ci } 346e1051a39Sopenharmony_ci len = EVP_MD_get_size(md); 347e1051a39Sopenharmony_ci return (len <= 0) ? 0 : (size_t)len; 348e1051a39Sopenharmony_ci} 349e1051a39Sopenharmony_ci 350e1051a39Sopenharmony_cistatic int sskdf_derive(void *vctx, unsigned char *key, size_t keylen, 351e1051a39Sopenharmony_ci const OSSL_PARAM params[]) 352e1051a39Sopenharmony_ci{ 353e1051a39Sopenharmony_ci KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; 354e1051a39Sopenharmony_ci const EVP_MD *md; 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params)) 357e1051a39Sopenharmony_ci return 0; 358e1051a39Sopenharmony_ci if (ctx->secret == NULL) { 359e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); 360e1051a39Sopenharmony_ci return 0; 361e1051a39Sopenharmony_ci } 362e1051a39Sopenharmony_ci md = ossl_prov_digest_md(&ctx->digest); 363e1051a39Sopenharmony_ci 364e1051a39Sopenharmony_ci if (ctx->macctx != NULL) { 365e1051a39Sopenharmony_ci /* H(x) = KMAC or H(x) = HMAC */ 366e1051a39Sopenharmony_ci int ret; 367e1051a39Sopenharmony_ci const unsigned char *custom = NULL; 368e1051a39Sopenharmony_ci size_t custom_len = 0; 369e1051a39Sopenharmony_ci int default_salt_len; 370e1051a39Sopenharmony_ci EVP_MAC *mac = EVP_MAC_CTX_get0_mac(ctx->macctx); 371e1051a39Sopenharmony_ci 372e1051a39Sopenharmony_ci if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) { 373e1051a39Sopenharmony_ci /* H(x) = HMAC(x, salt, hash) */ 374e1051a39Sopenharmony_ci if (md == NULL) { 375e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); 376e1051a39Sopenharmony_ci return 0; 377e1051a39Sopenharmony_ci } 378e1051a39Sopenharmony_ci default_salt_len = EVP_MD_get_size(md); 379e1051a39Sopenharmony_ci if (default_salt_len <= 0) 380e1051a39Sopenharmony_ci return 0; 381e1051a39Sopenharmony_ci } else if (ctx->is_kmac) { 382e1051a39Sopenharmony_ci /* H(x) = KMACzzz(x, salt, custom) */ 383e1051a39Sopenharmony_ci custom = kmac_custom_str; 384e1051a39Sopenharmony_ci custom_len = sizeof(kmac_custom_str); 385e1051a39Sopenharmony_ci if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128)) 386e1051a39Sopenharmony_ci default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; 387e1051a39Sopenharmony_ci else 388e1051a39Sopenharmony_ci default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; 389e1051a39Sopenharmony_ci } else { 390e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE); 391e1051a39Sopenharmony_ci return 0; 392e1051a39Sopenharmony_ci } 393e1051a39Sopenharmony_ci /* If no salt is set then use a default_salt of zeros */ 394e1051a39Sopenharmony_ci if (ctx->salt == NULL || ctx->salt_len <= 0) { 395e1051a39Sopenharmony_ci ctx->salt = OPENSSL_zalloc(default_salt_len); 396e1051a39Sopenharmony_ci if (ctx->salt == NULL) { 397e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 398e1051a39Sopenharmony_ci return 0; 399e1051a39Sopenharmony_ci } 400e1051a39Sopenharmony_ci ctx->salt_len = default_salt_len; 401e1051a39Sopenharmony_ci } 402e1051a39Sopenharmony_ci ret = SSKDF_mac_kdm(ctx->macctx, 403e1051a39Sopenharmony_ci custom, custom_len, ctx->out_len, 404e1051a39Sopenharmony_ci ctx->salt, ctx->salt_len, 405e1051a39Sopenharmony_ci ctx->secret, ctx->secret_len, 406e1051a39Sopenharmony_ci ctx->info, ctx->info_len, key, keylen); 407e1051a39Sopenharmony_ci return ret; 408e1051a39Sopenharmony_ci } else { 409e1051a39Sopenharmony_ci /* H(x) = hash */ 410e1051a39Sopenharmony_ci if (md == NULL) { 411e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); 412e1051a39Sopenharmony_ci return 0; 413e1051a39Sopenharmony_ci } 414e1051a39Sopenharmony_ci return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, 415e1051a39Sopenharmony_ci ctx->info, ctx->info_len, 0, key, keylen); 416e1051a39Sopenharmony_ci } 417e1051a39Sopenharmony_ci} 418e1051a39Sopenharmony_ci 419e1051a39Sopenharmony_cistatic int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen, 420e1051a39Sopenharmony_ci const OSSL_PARAM params[]) 421e1051a39Sopenharmony_ci{ 422e1051a39Sopenharmony_ci KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; 423e1051a39Sopenharmony_ci const EVP_MD *md; 424e1051a39Sopenharmony_ci 425e1051a39Sopenharmony_ci if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params)) 426e1051a39Sopenharmony_ci return 0; 427e1051a39Sopenharmony_ci 428e1051a39Sopenharmony_ci if (ctx->secret == NULL) { 429e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); 430e1051a39Sopenharmony_ci return 0; 431e1051a39Sopenharmony_ci } 432e1051a39Sopenharmony_ci 433e1051a39Sopenharmony_ci if (ctx->macctx != NULL) { 434e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); 435e1051a39Sopenharmony_ci return 0; 436e1051a39Sopenharmony_ci } 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ci /* H(x) = hash */ 439e1051a39Sopenharmony_ci md = ossl_prov_digest_md(&ctx->digest); 440e1051a39Sopenharmony_ci if (md == NULL) { 441e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); 442e1051a39Sopenharmony_ci return 0; 443e1051a39Sopenharmony_ci } 444e1051a39Sopenharmony_ci 445e1051a39Sopenharmony_ci return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, 446e1051a39Sopenharmony_ci ctx->info, ctx->info_len, 1, key, keylen); 447e1051a39Sopenharmony_ci} 448e1051a39Sopenharmony_ci 449e1051a39Sopenharmony_cistatic int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 450e1051a39Sopenharmony_ci{ 451e1051a39Sopenharmony_ci const OSSL_PARAM *p; 452e1051a39Sopenharmony_ci KDF_SSKDF *ctx = vctx; 453e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); 454e1051a39Sopenharmony_ci size_t sz; 455e1051a39Sopenharmony_ci 456e1051a39Sopenharmony_ci if (params == NULL) 457e1051a39Sopenharmony_ci return 1; 458e1051a39Sopenharmony_ci 459e1051a39Sopenharmony_ci if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params, 460e1051a39Sopenharmony_ci NULL, NULL, NULL, libctx)) 461e1051a39Sopenharmony_ci return 0; 462e1051a39Sopenharmony_ci if (ctx->macctx != NULL) { 463e1051a39Sopenharmony_ci if (EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), 464e1051a39Sopenharmony_ci OSSL_MAC_NAME_KMAC128) 465e1051a39Sopenharmony_ci || EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), 466e1051a39Sopenharmony_ci OSSL_MAC_NAME_KMAC256)) { 467e1051a39Sopenharmony_ci ctx->is_kmac = 1; 468e1051a39Sopenharmony_ci } 469e1051a39Sopenharmony_ci } 470e1051a39Sopenharmony_ci 471e1051a39Sopenharmony_ci if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) 472e1051a39Sopenharmony_ci return 0; 473e1051a39Sopenharmony_ci 474e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL 475e1051a39Sopenharmony_ci || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) 476e1051a39Sopenharmony_ci if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) 477e1051a39Sopenharmony_ci return 0; 478e1051a39Sopenharmony_ci 479e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) 480e1051a39Sopenharmony_ci if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p)) 481e1051a39Sopenharmony_ci return 0; 482e1051a39Sopenharmony_ci 483e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) 484e1051a39Sopenharmony_ci if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p)) 485e1051a39Sopenharmony_ci return 0; 486e1051a39Sopenharmony_ci 487e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE)) 488e1051a39Sopenharmony_ci != NULL) { 489e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0) 490e1051a39Sopenharmony_ci return 0; 491e1051a39Sopenharmony_ci ctx->out_len = sz; 492e1051a39Sopenharmony_ci } 493e1051a39Sopenharmony_ci return 1; 494e1051a39Sopenharmony_ci} 495e1051a39Sopenharmony_ci 496e1051a39Sopenharmony_cistatic const OSSL_PARAM *sskdf_settable_ctx_params(ossl_unused void *ctx, 497e1051a39Sopenharmony_ci ossl_unused void *provctx) 498e1051a39Sopenharmony_ci{ 499e1051a39Sopenharmony_ci static const OSSL_PARAM known_settable_ctx_params[] = { 500e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), 501e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), 502e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), 503e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), 504e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), 505e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), 506e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), 507e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL), 508e1051a39Sopenharmony_ci OSSL_PARAM_END 509e1051a39Sopenharmony_ci }; 510e1051a39Sopenharmony_ci return known_settable_ctx_params; 511e1051a39Sopenharmony_ci} 512e1051a39Sopenharmony_ci 513e1051a39Sopenharmony_cistatic int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) 514e1051a39Sopenharmony_ci{ 515e1051a39Sopenharmony_ci KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; 516e1051a39Sopenharmony_ci OSSL_PARAM *p; 517e1051a39Sopenharmony_ci 518e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) 519e1051a39Sopenharmony_ci return OSSL_PARAM_set_size_t(p, sskdf_size(ctx)); 520e1051a39Sopenharmony_ci return -2; 521e1051a39Sopenharmony_ci} 522e1051a39Sopenharmony_ci 523e1051a39Sopenharmony_cistatic const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx, 524e1051a39Sopenharmony_ci ossl_unused void *provctx) 525e1051a39Sopenharmony_ci{ 526e1051a39Sopenharmony_ci static const OSSL_PARAM known_gettable_ctx_params[] = { 527e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), 528e1051a39Sopenharmony_ci OSSL_PARAM_END 529e1051a39Sopenharmony_ci }; 530e1051a39Sopenharmony_ci return known_gettable_ctx_params; 531e1051a39Sopenharmony_ci} 532e1051a39Sopenharmony_ci 533e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_sskdf_functions[] = { 534e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, 535e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, 536e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, 537e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive }, 538e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, 539e1051a39Sopenharmony_ci (void(*)(void))sskdf_settable_ctx_params }, 540e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, 541e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, 542e1051a39Sopenharmony_ci (void(*)(void))sskdf_gettable_ctx_params }, 543e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, 544e1051a39Sopenharmony_ci { 0, NULL } 545e1051a39Sopenharmony_ci}; 546e1051a39Sopenharmony_ci 547e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = { 548e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, 549e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, 550e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, 551e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, 552e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, 553e1051a39Sopenharmony_ci (void(*)(void))sskdf_settable_ctx_params }, 554e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, 555e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, 556e1051a39Sopenharmony_ci (void(*)(void))sskdf_gettable_ctx_params }, 557e1051a39Sopenharmony_ci { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, 558e1051a39Sopenharmony_ci { 0, NULL } 559e1051a39Sopenharmony_ci}; 560