1b077aed3SPierre Pronchery /* 2*44096ebdSEnji Cooper * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. 3b077aed3SPierre Pronchery * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at 7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html 8b077aed3SPierre Pronchery */ 9b077aed3SPierre Pronchery 10b077aed3SPierre Pronchery #include <openssl/crypto.h> 11b077aed3SPierre Pronchery #include <openssl/kdf.h> 12b077aed3SPierre Pronchery #include <openssl/core_dispatch.h> 13b077aed3SPierre Pronchery #include <openssl/core_names.h> 14b077aed3SPierre Pronchery #include <openssl/err.h> 15b077aed3SPierre Pronchery #include <openssl/proverr.h> 16b077aed3SPierre Pronchery #include <openssl/params.h> 17b077aed3SPierre Pronchery #include "internal/numbers.h" 18b077aed3SPierre Pronchery #include "prov/implementations.h" 19b077aed3SPierre Pronchery #include "prov/provider_ctx.h" 20b077aed3SPierre Pronchery #include "prov/kdfexchange.h" 21b077aed3SPierre Pronchery #include "prov/providercommon.h" 22b077aed3SPierre Pronchery 23b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx; 24b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx; 25b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx; 26b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_init_fn kdf_init; 27b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_derive_fn kdf_derive; 28b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_freectx_fn kdf_freectx; 29b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx; 30b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params; 31*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_get_ctx_params_fn kdf_get_ctx_params; 32b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params; 33b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; 34b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params; 35*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params; 36*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; 37*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params; 38b077aed3SPierre Pronchery 39b077aed3SPierre Pronchery typedef struct { 40b077aed3SPierre Pronchery void *provctx; 41b077aed3SPierre Pronchery EVP_KDF_CTX *kdfctx; 42b077aed3SPierre Pronchery KDF_DATA *kdfdata; 43b077aed3SPierre Pronchery } PROV_KDF_CTX; 44b077aed3SPierre Pronchery 45b077aed3SPierre Pronchery static void *kdf_newctx(const char *kdfname, void *provctx) 46b077aed3SPierre Pronchery { 47b077aed3SPierre Pronchery PROV_KDF_CTX *kdfctx; 48b077aed3SPierre Pronchery EVP_KDF *kdf = NULL; 49b077aed3SPierre Pronchery 50b077aed3SPierre Pronchery if (!ossl_prov_is_running()) 51b077aed3SPierre Pronchery return NULL; 52b077aed3SPierre Pronchery 53b077aed3SPierre Pronchery kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX)); 54b077aed3SPierre Pronchery if (kdfctx == NULL) 55b077aed3SPierre Pronchery return NULL; 56b077aed3SPierre Pronchery 57b077aed3SPierre Pronchery kdfctx->provctx = provctx; 58b077aed3SPierre Pronchery 59b077aed3SPierre Pronchery kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, NULL); 60b077aed3SPierre Pronchery if (kdf == NULL) 61b077aed3SPierre Pronchery goto err; 62b077aed3SPierre Pronchery kdfctx->kdfctx = EVP_KDF_CTX_new(kdf); 63b077aed3SPierre Pronchery EVP_KDF_free(kdf); 64b077aed3SPierre Pronchery 65b077aed3SPierre Pronchery if (kdfctx->kdfctx == NULL) 66b077aed3SPierre Pronchery goto err; 67b077aed3SPierre Pronchery 68b077aed3SPierre Pronchery return kdfctx; 69b077aed3SPierre Pronchery err: 70b077aed3SPierre Pronchery OPENSSL_free(kdfctx); 71b077aed3SPierre Pronchery return NULL; 72b077aed3SPierre Pronchery } 73b077aed3SPierre Pronchery 74b077aed3SPierre Pronchery #define KDF_NEWCTX(funcname, kdfname) \ 75b077aed3SPierre Pronchery static void *kdf_##funcname##_newctx(void *provctx) \ 76b077aed3SPierre Pronchery { \ 77b077aed3SPierre Pronchery return kdf_newctx(kdfname, provctx); \ 78b077aed3SPierre Pronchery } 79b077aed3SPierre Pronchery 80b077aed3SPierre Pronchery KDF_NEWCTX(tls1_prf, "TLS1-PRF") 81b077aed3SPierre Pronchery KDF_NEWCTX(hkdf, "HKDF") 82b077aed3SPierre Pronchery KDF_NEWCTX(scrypt, "SCRYPT") 83b077aed3SPierre Pronchery 84b077aed3SPierre Pronchery static int kdf_init(void *vpkdfctx, void *vkdf, const OSSL_PARAM params[]) 85b077aed3SPierre Pronchery { 86b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; 87b077aed3SPierre Pronchery 88b077aed3SPierre Pronchery if (!ossl_prov_is_running() 89b077aed3SPierre Pronchery || pkdfctx == NULL 90b077aed3SPierre Pronchery || vkdf == NULL 91b077aed3SPierre Pronchery || !ossl_kdf_data_up_ref(vkdf)) 92b077aed3SPierre Pronchery return 0; 93b077aed3SPierre Pronchery pkdfctx->kdfdata = vkdf; 94b077aed3SPierre Pronchery 95b077aed3SPierre Pronchery return kdf_set_ctx_params(pkdfctx, params); 96b077aed3SPierre Pronchery } 97b077aed3SPierre Pronchery 98b077aed3SPierre Pronchery static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen, 99b077aed3SPierre Pronchery size_t outlen) 100b077aed3SPierre Pronchery { 101b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; 102b077aed3SPierre Pronchery size_t kdfsize; 103b077aed3SPierre Pronchery int ret; 104b077aed3SPierre Pronchery 105b077aed3SPierre Pronchery if (!ossl_prov_is_running()) 106b077aed3SPierre Pronchery return 0; 107b077aed3SPierre Pronchery 108b077aed3SPierre Pronchery kdfsize = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx); 109b077aed3SPierre Pronchery 110b077aed3SPierre Pronchery if (secret == NULL) { 111b077aed3SPierre Pronchery *secretlen = kdfsize; 112b077aed3SPierre Pronchery return 1; 113b077aed3SPierre Pronchery } 114b077aed3SPierre Pronchery 115b077aed3SPierre Pronchery if (kdfsize != SIZE_MAX) { 116b077aed3SPierre Pronchery if (outlen < kdfsize) { 117b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 118b077aed3SPierre Pronchery return 0; 119b077aed3SPierre Pronchery } 120b077aed3SPierre Pronchery outlen = kdfsize; 121b077aed3SPierre Pronchery } 122b077aed3SPierre Pronchery 123b077aed3SPierre Pronchery ret = EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL); 124b077aed3SPierre Pronchery if (ret <= 0) 125b077aed3SPierre Pronchery return 0; 126b077aed3SPierre Pronchery 127b077aed3SPierre Pronchery *secretlen = outlen; 128b077aed3SPierre Pronchery return 1; 129b077aed3SPierre Pronchery } 130b077aed3SPierre Pronchery 131b077aed3SPierre Pronchery static void kdf_freectx(void *vpkdfctx) 132b077aed3SPierre Pronchery { 133b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; 134b077aed3SPierre Pronchery 135b077aed3SPierre Pronchery EVP_KDF_CTX_free(pkdfctx->kdfctx); 136b077aed3SPierre Pronchery ossl_kdf_data_free(pkdfctx->kdfdata); 137b077aed3SPierre Pronchery 138b077aed3SPierre Pronchery OPENSSL_free(pkdfctx); 139b077aed3SPierre Pronchery } 140b077aed3SPierre Pronchery 141b077aed3SPierre Pronchery static void *kdf_dupctx(void *vpkdfctx) 142b077aed3SPierre Pronchery { 143b077aed3SPierre Pronchery PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx; 144b077aed3SPierre Pronchery PROV_KDF_CTX *dstctx; 145b077aed3SPierre Pronchery 146b077aed3SPierre Pronchery if (!ossl_prov_is_running()) 147b077aed3SPierre Pronchery return NULL; 148b077aed3SPierre Pronchery 149b077aed3SPierre Pronchery dstctx = OPENSSL_zalloc(sizeof(*srcctx)); 150b077aed3SPierre Pronchery if (dstctx == NULL) 151b077aed3SPierre Pronchery return NULL; 152b077aed3SPierre Pronchery 153b077aed3SPierre Pronchery *dstctx = *srcctx; 154b077aed3SPierre Pronchery 155b077aed3SPierre Pronchery dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx); 156b077aed3SPierre Pronchery if (dstctx->kdfctx == NULL) { 157b077aed3SPierre Pronchery OPENSSL_free(dstctx); 158b077aed3SPierre Pronchery return NULL; 159b077aed3SPierre Pronchery } 160b077aed3SPierre Pronchery if (!ossl_kdf_data_up_ref(dstctx->kdfdata)) { 161b077aed3SPierre Pronchery EVP_KDF_CTX_free(dstctx->kdfctx); 162b077aed3SPierre Pronchery OPENSSL_free(dstctx); 163b077aed3SPierre Pronchery return NULL; 164b077aed3SPierre Pronchery } 165b077aed3SPierre Pronchery 166b077aed3SPierre Pronchery return dstctx; 167b077aed3SPierre Pronchery } 168b077aed3SPierre Pronchery 169b077aed3SPierre Pronchery static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[]) 170b077aed3SPierre Pronchery { 171b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; 172b077aed3SPierre Pronchery 173b077aed3SPierre Pronchery return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params); 174b077aed3SPierre Pronchery } 175b077aed3SPierre Pronchery 176*44096ebdSEnji Cooper static int kdf_get_ctx_params(void *vpkdfctx, OSSL_PARAM params[]) 177*44096ebdSEnji Cooper { 178*44096ebdSEnji Cooper PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx; 179*44096ebdSEnji Cooper 180*44096ebdSEnji Cooper return EVP_KDF_CTX_get_params(pkdfctx->kdfctx, params); 181*44096ebdSEnji Cooper } 182*44096ebdSEnji Cooper 183b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_settable_ctx_params(ossl_unused void *vpkdfctx, 184b077aed3SPierre Pronchery void *provctx, 185b077aed3SPierre Pronchery const char *kdfname) 186b077aed3SPierre Pronchery { 187b077aed3SPierre Pronchery EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, 188b077aed3SPierre Pronchery NULL); 189b077aed3SPierre Pronchery const OSSL_PARAM *params; 190b077aed3SPierre Pronchery 191b077aed3SPierre Pronchery if (kdf == NULL) 192b077aed3SPierre Pronchery return NULL; 193b077aed3SPierre Pronchery 194b077aed3SPierre Pronchery params = EVP_KDF_settable_ctx_params(kdf); 195b077aed3SPierre Pronchery EVP_KDF_free(kdf); 196b077aed3SPierre Pronchery 197b077aed3SPierre Pronchery return params; 198b077aed3SPierre Pronchery } 199b077aed3SPierre Pronchery 200b077aed3SPierre Pronchery #define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \ 201b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void *vpkdfctx, \ 202b077aed3SPierre Pronchery void *provctx) \ 203b077aed3SPierre Pronchery { \ 204b077aed3SPierre Pronchery return kdf_settable_ctx_params(vpkdfctx, provctx, kdfname); \ 205b077aed3SPierre Pronchery } 206b077aed3SPierre Pronchery 207b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") 208b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF") 209b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT") 210b077aed3SPierre Pronchery 211*44096ebdSEnji Cooper static const OSSL_PARAM *kdf_gettable_ctx_params(ossl_unused void *vpkdfctx, 212*44096ebdSEnji Cooper void *provctx, 213*44096ebdSEnji Cooper const char *kdfname) 214*44096ebdSEnji Cooper { 215*44096ebdSEnji Cooper EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, 216*44096ebdSEnji Cooper NULL); 217*44096ebdSEnji Cooper const OSSL_PARAM *params; 218*44096ebdSEnji Cooper 219*44096ebdSEnji Cooper if (kdf == NULL) 220*44096ebdSEnji Cooper return NULL; 221*44096ebdSEnji Cooper 222*44096ebdSEnji Cooper params = EVP_KDF_gettable_ctx_params(kdf); 223*44096ebdSEnji Cooper EVP_KDF_free(kdf); 224*44096ebdSEnji Cooper 225*44096ebdSEnji Cooper return params; 226*44096ebdSEnji Cooper } 227*44096ebdSEnji Cooper 228*44096ebdSEnji Cooper #define KDF_GETTABLE_CTX_PARAMS(funcname, kdfname) \ 229*44096ebdSEnji Cooper static const OSSL_PARAM *kdf_##funcname##_gettable_ctx_params(void *vpkdfctx, \ 230*44096ebdSEnji Cooper void *provctx) \ 231*44096ebdSEnji Cooper { \ 232*44096ebdSEnji Cooper return kdf_gettable_ctx_params(vpkdfctx, provctx, kdfname); \ 233*44096ebdSEnji Cooper } 234*44096ebdSEnji Cooper 235*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") 236*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(hkdf, "HKDF") 237*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(scrypt, "SCRYPT") 238*44096ebdSEnji Cooper 239b077aed3SPierre Pronchery #define KDF_KEYEXCH_FUNCTIONS(funcname) \ 240b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_kdf_##funcname##_keyexch_functions[] = { \ 241b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \ 242b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \ 243b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \ 244b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \ 245b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \ 246b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \ 247*44096ebdSEnji Cooper { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))kdf_get_ctx_params }, \ 248b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \ 249b077aed3SPierre Pronchery (void (*)(void))kdf_##funcname##_settable_ctx_params }, \ 250*44096ebdSEnji Cooper { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, \ 251*44096ebdSEnji Cooper (void (*)(void))kdf_##funcname##_gettable_ctx_params }, \ 252b077aed3SPierre Pronchery { 0, NULL } \ 253b077aed3SPierre Pronchery }; 254b077aed3SPierre Pronchery 255b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(tls1_prf) 256b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(hkdf) 257b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(scrypt) 258