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