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 23 static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx; 24 static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx; 25 static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx; 26 static OSSL_FUNC_keyexch_init_fn kdf_init; 27 static OSSL_FUNC_keyexch_derive_fn kdf_derive; 28 static OSSL_FUNC_keyexch_freectx_fn kdf_freectx; 29 static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx; 30 static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params; 31 static OSSL_FUNC_keyexch_get_ctx_params_fn kdf_get_ctx_params; 32 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params; 33 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; 34 static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params; 35 static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params; 36 static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; 37 static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params; 38 39 typedef struct { 40 void *provctx; 41 EVP_KDF_CTX *kdfctx; 42 KDF_DATA *kdfdata; 43 } PROV_KDF_CTX; 44 45 static 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; 69 err: 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 80 KDF_NEWCTX(tls1_prf, "TLS1-PRF") 81 KDF_NEWCTX(hkdf, "HKDF") 82 KDF_NEWCTX(scrypt, "SCRYPT") 83 84 static 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 98 static 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 131 static 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 141 static 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 169 static 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 176 static 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 183 static 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 207 KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") 208 KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF") 209 KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT") 210 211 static 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 235 KDF_GETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") 236 KDF_GETTABLE_CTX_PARAMS(hkdf, "HKDF") 237 KDF_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 255 KDF_KEYEXCH_FUNCTIONS(tls1_prf) 256 KDF_KEYEXCH_FUNCTIONS(hkdf) 257 KDF_KEYEXCH_FUNCTIONS(scrypt) 258