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