1/* 2 * Copyright 2019-2021 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/evp.h> 11#include <openssl/err.h> 12#include <openssl/core.h> 13#include <openssl/core_dispatch.h> 14#include <openssl/kdf.h> 15#include "internal/provider.h" 16#include "internal/core.h" 17#include "crypto/evp.h" 18#include "evp_local.h" 19 20static int evp_kdf_up_ref(void *vkdf) 21{ 22 EVP_KDF *kdf = (EVP_KDF *)vkdf; 23 int ref = 0; 24 25 CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock); 26 return 1; 27} 28 29static void evp_kdf_free(void *vkdf) 30{ 31 EVP_KDF *kdf = (EVP_KDF *)vkdf; 32 int ref = 0; 33 34 if (kdf == NULL) 35 return; 36 37 CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock); 38 if (ref > 0) 39 return; 40 OPENSSL_free(kdf->type_name); 41 ossl_provider_free(kdf->prov); 42 CRYPTO_THREAD_lock_free(kdf->lock); 43 OPENSSL_free(kdf); 44} 45 46static void *evp_kdf_new(void) 47{ 48 EVP_KDF *kdf = NULL; 49 50 if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL 51 || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) { 52 OPENSSL_free(kdf); 53 return NULL; 54 } 55 kdf->refcnt = 1; 56 return kdf; 57} 58 59static void *evp_kdf_from_algorithm(int name_id, 60 const OSSL_ALGORITHM *algodef, 61 OSSL_PROVIDER *prov) 62{ 63 const OSSL_DISPATCH *fns = algodef->implementation; 64 EVP_KDF *kdf = NULL; 65 int fnkdfcnt = 0, fnctxcnt = 0; 66 67 if ((kdf = evp_kdf_new()) == NULL) { 68 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 69 return NULL; 70 } 71 kdf->name_id = name_id; 72 if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { 73 evp_kdf_free(kdf); 74 return NULL; 75 } 76 kdf->description = algodef->algorithm_description; 77 78 for (; fns->function_id != 0; fns++) { 79 switch (fns->function_id) { 80 case OSSL_FUNC_KDF_NEWCTX: 81 if (kdf->newctx != NULL) 82 break; 83 kdf->newctx = OSSL_FUNC_kdf_newctx(fns); 84 fnctxcnt++; 85 break; 86 case OSSL_FUNC_KDF_DUPCTX: 87 if (kdf->dupctx != NULL) 88 break; 89 kdf->dupctx = OSSL_FUNC_kdf_dupctx(fns); 90 break; 91 case OSSL_FUNC_KDF_FREECTX: 92 if (kdf->freectx != NULL) 93 break; 94 kdf->freectx = OSSL_FUNC_kdf_freectx(fns); 95 fnctxcnt++; 96 break; 97 case OSSL_FUNC_KDF_RESET: 98 if (kdf->reset != NULL) 99 break; 100 kdf->reset = OSSL_FUNC_kdf_reset(fns); 101 break; 102 case OSSL_FUNC_KDF_DERIVE: 103 if (kdf->derive != NULL) 104 break; 105 kdf->derive = OSSL_FUNC_kdf_derive(fns); 106 fnkdfcnt++; 107 break; 108 case OSSL_FUNC_KDF_GETTABLE_PARAMS: 109 if (kdf->gettable_params != NULL) 110 break; 111 kdf->gettable_params = 112 OSSL_FUNC_kdf_gettable_params(fns); 113 break; 114 case OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS: 115 if (kdf->gettable_ctx_params != NULL) 116 break; 117 kdf->gettable_ctx_params = 118 OSSL_FUNC_kdf_gettable_ctx_params(fns); 119 break; 120 case OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS: 121 if (kdf->settable_ctx_params != NULL) 122 break; 123 kdf->settable_ctx_params = 124 OSSL_FUNC_kdf_settable_ctx_params(fns); 125 break; 126 case OSSL_FUNC_KDF_GET_PARAMS: 127 if (kdf->get_params != NULL) 128 break; 129 kdf->get_params = OSSL_FUNC_kdf_get_params(fns); 130 break; 131 case OSSL_FUNC_KDF_GET_CTX_PARAMS: 132 if (kdf->get_ctx_params != NULL) 133 break; 134 kdf->get_ctx_params = OSSL_FUNC_kdf_get_ctx_params(fns); 135 break; 136 case OSSL_FUNC_KDF_SET_CTX_PARAMS: 137 if (kdf->set_ctx_params != NULL) 138 break; 139 kdf->set_ctx_params = OSSL_FUNC_kdf_set_ctx_params(fns); 140 break; 141 } 142 } 143 if (fnkdfcnt != 1 || fnctxcnt != 2) { 144 /* 145 * In order to be a consistent set of functions we must have at least 146 * a derive function, and a complete set of context management 147 * functions. 148 */ 149 evp_kdf_free(kdf); 150 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); 151 return NULL; 152 } 153 kdf->prov = prov; 154 if (prov != NULL) 155 ossl_provider_up_ref(prov); 156 157 return kdf; 158} 159 160EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, 161 const char *properties) 162{ 163 return evp_generic_fetch(libctx, OSSL_OP_KDF, algorithm, properties, 164 evp_kdf_from_algorithm, evp_kdf_up_ref, 165 evp_kdf_free); 166} 167 168int EVP_KDF_up_ref(EVP_KDF *kdf) 169{ 170 return evp_kdf_up_ref(kdf); 171} 172 173void EVP_KDF_free(EVP_KDF *kdf) 174{ 175 evp_kdf_free(kdf); 176} 177 178const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf) 179{ 180 if (kdf->gettable_params == NULL) 181 return NULL; 182 return kdf->gettable_params(ossl_provider_ctx(EVP_KDF_get0_provider(kdf))); 183} 184 185const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf) 186{ 187 void *alg; 188 189 if (kdf->gettable_ctx_params == NULL) 190 return NULL; 191 alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf)); 192 return kdf->gettable_ctx_params(NULL, alg); 193} 194 195const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf) 196{ 197 void *alg; 198 199 if (kdf->settable_ctx_params == NULL) 200 return NULL; 201 alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf)); 202 return kdf->settable_ctx_params(NULL, alg); 203} 204 205const OSSL_PARAM *EVP_KDF_CTX_gettable_params(EVP_KDF_CTX *ctx) 206{ 207 void *alg; 208 209 if (ctx->meth->gettable_ctx_params == NULL) 210 return NULL; 211 alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth)); 212 return ctx->meth->gettable_ctx_params(ctx->algctx, alg); 213} 214 215const OSSL_PARAM *EVP_KDF_CTX_settable_params(EVP_KDF_CTX *ctx) 216{ 217 void *alg; 218 219 if (ctx->meth->settable_ctx_params == NULL) 220 return NULL; 221 alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth)); 222 return ctx->meth->settable_ctx_params(ctx->algctx, alg); 223} 224 225void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx, 226 void (*fn)(EVP_KDF *kdf, void *arg), 227 void *arg) 228{ 229 evp_generic_do_all(libctx, OSSL_OP_KDF, 230 (void (*)(void *, void *))fn, arg, 231 evp_kdf_from_algorithm, evp_kdf_up_ref, evp_kdf_free); 232} 233