1 /* 2 * Copyright 2025 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/core_dispatch.h> 12 #include <openssl/evp.h> 13 #include <openssl/err.h> 14 #include "internal/core.h" 15 #include "internal/provider.h" 16 #include "internal/refcount.h" 17 #include "crypto/evp.h" 18 #include "evp_local.h" 19 20 void *evp_skeymgmt_generate(const EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[]) 21 { 22 void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); 23 24 return (skeymgmt->generate != NULL) ? skeymgmt->generate(provctx, params) : NULL; 25 } 26 27 void *evp_skeymgmt_import(const EVP_SKEYMGMT *skeymgmt, int selection, const OSSL_PARAM params[]) 28 { 29 void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); 30 31 /* This is mandatory, no need to check for its presence */ 32 return skeymgmt->import(provctx, selection, params); 33 } 34 35 int evp_skeymgmt_export(const EVP_SKEYMGMT *skeymgmt, void *keydata, 36 int selection, OSSL_CALLBACK *param_cb, void *cbarg) 37 { 38 /* This is mandatory, no need to check for its presence */ 39 return skeymgmt->export(keydata, selection, param_cb, cbarg); 40 } 41 42 void evp_skeymgmt_freedata(const EVP_SKEYMGMT *skeymgmt, void *keydata) 43 { 44 /* This is mandatory, no need to check for its presence */ 45 skeymgmt->free(keydata); 46 } 47 48 static void *skeymgmt_new(void) 49 { 50 EVP_SKEYMGMT *skeymgmt = NULL; 51 52 if ((skeymgmt = OPENSSL_zalloc(sizeof(*skeymgmt))) == NULL) 53 return NULL; 54 if (!CRYPTO_NEW_REF(&skeymgmt->refcnt, 1)) { 55 EVP_SKEYMGMT_free(skeymgmt); 56 return NULL; 57 } 58 return skeymgmt; 59 } 60 61 static void *skeymgmt_from_algorithm(int name_id, 62 const OSSL_ALGORITHM *algodef, 63 OSSL_PROVIDER *prov) 64 { 65 const OSSL_DISPATCH *fns = algodef->implementation; 66 EVP_SKEYMGMT *skeymgmt = NULL; 67 68 if ((skeymgmt = skeymgmt_new()) == NULL) 69 return NULL; 70 71 skeymgmt->name_id = name_id; 72 if ((skeymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { 73 EVP_SKEYMGMT_free(skeymgmt); 74 return NULL; 75 } 76 skeymgmt->description = algodef->algorithm_description; 77 78 for (; fns->function_id != 0; fns++) { 79 switch (fns->function_id) { 80 case OSSL_FUNC_SKEYMGMT_FREE: 81 if (skeymgmt->free == NULL) 82 skeymgmt->free = OSSL_FUNC_skeymgmt_free(fns); 83 break; 84 case OSSL_FUNC_SKEYMGMT_IMPORT: 85 if (skeymgmt->import == NULL) 86 skeymgmt->import = OSSL_FUNC_skeymgmt_import(fns); 87 break; 88 case OSSL_FUNC_SKEYMGMT_EXPORT: 89 if (skeymgmt->export == NULL) 90 skeymgmt->export = OSSL_FUNC_skeymgmt_export(fns); 91 break; 92 case OSSL_FUNC_SKEYMGMT_GENERATE: 93 if (skeymgmt->generate == NULL) 94 skeymgmt->generate = OSSL_FUNC_skeymgmt_generate(fns); 95 break; 96 case OSSL_FUNC_SKEYMGMT_GET_KEY_ID: 97 if (skeymgmt->get_key_id == NULL) 98 skeymgmt->get_key_id = OSSL_FUNC_skeymgmt_get_key_id(fns); 99 break; 100 case OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS: 101 if (skeymgmt->imp_params == NULL) 102 skeymgmt->imp_params = OSSL_FUNC_skeymgmt_imp_settable_params(fns); 103 break; 104 case OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS: 105 if (skeymgmt->gen_params == NULL) 106 skeymgmt->gen_params = OSSL_FUNC_skeymgmt_gen_settable_params(fns); 107 break; 108 } 109 } 110 111 /* Check that the provider is sensible */ 112 if (skeymgmt->free == NULL 113 || skeymgmt->import == NULL 114 || skeymgmt->export == NULL) { 115 EVP_SKEYMGMT_free(skeymgmt); 116 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); 117 return NULL; 118 } 119 120 if (!ossl_provider_up_ref(prov)) { 121 EVP_SKEYMGMT_free(skeymgmt); 122 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 123 return NULL; 124 } 125 skeymgmt->prov = prov; 126 127 return skeymgmt; 128 } 129 130 EVP_SKEYMGMT *evp_skeymgmt_fetch_from_prov(OSSL_PROVIDER *prov, 131 const char *name, 132 const char *properties) 133 { 134 return evp_generic_fetch_from_prov(prov, 135 OSSL_OP_SKEYMGMT, 136 name, properties, 137 skeymgmt_from_algorithm, 138 (int (*)(void *))EVP_SKEYMGMT_up_ref, 139 (void (*)(void *))EVP_SKEYMGMT_free); 140 } 141 142 EVP_SKEYMGMT *EVP_SKEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, 143 const char *properties) 144 { 145 return evp_generic_fetch(ctx, OSSL_OP_SKEYMGMT, algorithm, properties, 146 skeymgmt_from_algorithm, 147 (int (*)(void *))EVP_SKEYMGMT_up_ref, 148 (void (*)(void *))EVP_SKEYMGMT_free); 149 } 150 151 int EVP_SKEYMGMT_up_ref(EVP_SKEYMGMT *skeymgmt) 152 { 153 int ref = 0; 154 155 CRYPTO_UP_REF(&skeymgmt->refcnt, &ref); 156 return 1; 157 } 158 159 void EVP_SKEYMGMT_free(EVP_SKEYMGMT *skeymgmt) 160 { 161 int ref = 0; 162 163 if (skeymgmt == NULL) 164 return; 165 166 CRYPTO_DOWN_REF(&skeymgmt->refcnt, &ref); 167 if (ref > 0) 168 return; 169 OPENSSL_free(skeymgmt->type_name); 170 ossl_provider_free(skeymgmt->prov); 171 CRYPTO_FREE_REF(&skeymgmt->refcnt); 172 OPENSSL_free(skeymgmt); 173 } 174 175 const OSSL_PROVIDER *EVP_SKEYMGMT_get0_provider(const EVP_SKEYMGMT *skeymgmt) 176 { 177 return (skeymgmt != NULL) ? skeymgmt->prov : NULL; 178 } 179 180 const char *EVP_SKEYMGMT_get0_description(const EVP_SKEYMGMT *skeymgmt) 181 { 182 return (skeymgmt != NULL) ? skeymgmt->description : NULL; 183 } 184 185 const char *EVP_SKEYMGMT_get0_name(const EVP_SKEYMGMT *skeymgmt) 186 { 187 return (skeymgmt != NULL) ? skeymgmt->type_name : NULL; 188 } 189 190 int EVP_SKEYMGMT_is_a(const EVP_SKEYMGMT *skeymgmt, const char *name) 191 { 192 return skeymgmt != NULL 193 && evp_is_a(skeymgmt->prov, skeymgmt->name_id, NULL, name); 194 } 195 196 void EVP_SKEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx, 197 void (*fn)(EVP_SKEYMGMT *skeymgmt, void *arg), 198 void *arg) 199 { 200 evp_generic_do_all(libctx, OSSL_OP_SKEYMGMT, 201 (void (*)(void *, void *))fn, arg, 202 skeymgmt_from_algorithm, 203 (int (*)(void *))EVP_SKEYMGMT_up_ref, 204 (void (*)(void *))EVP_SKEYMGMT_free); 205 } 206 207 int EVP_SKEYMGMT_names_do_all(const EVP_SKEYMGMT *skeymgmt, 208 void (*fn)(const char *name, void *data), 209 void *data) 210 { 211 if (skeymgmt == NULL) 212 return 0; 213 214 if (skeymgmt->prov != NULL) 215 return evp_names_do_all(skeymgmt->prov, skeymgmt->name_id, fn, data); 216 217 return 1; 218 } 219 220 const OSSL_PARAM *EVP_SKEYMGMT_get0_gen_settable_params(const EVP_SKEYMGMT *skeymgmt) 221 { 222 void *provctx = NULL; 223 224 if (skeymgmt == NULL) 225 return 0; 226 227 provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); 228 229 return (skeymgmt->gen_params != NULL) ? skeymgmt->gen_params(provctx) : NULL; 230 } 231 232 const OSSL_PARAM *EVP_SKEYMGMT_get0_imp_settable_params(const EVP_SKEYMGMT *skeymgmt) 233 { 234 void *provctx = NULL; 235 236 if (skeymgmt == NULL) 237 return 0; 238 239 provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); 240 241 return (skeymgmt->imp_params != NULL) ? skeymgmt->imp_params(provctx) : NULL; 242 } 243