1 /* 2 * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * https://www.openssl.org/source/license.html 8 * or in the file LICENSE in the source distribution. 9 */ 10 11 #include <string.h> 12 #include <openssl/core_names.h> 13 #include <openssl/core_object.h> 14 #include <openssl/rand.h> 15 #include <openssl/provider.h> 16 #include <openssl/proverr.h> 17 #include <openssl/param_build.h> 18 #include "testutil.h" 19 #include "fake_cipherprov.h" 20 21 #define MAX_KEYNAME 32 22 #define FAKE_KEY_LEN 16 23 24 typedef struct prov_cipher_fake_ctx_st { 25 char key_name[MAX_KEYNAME]; 26 unsigned char key[FAKE_KEY_LEN]; 27 } PROV_CIPHER_FAKE_CTX; 28 29 static int ctx_from_key_params(PROV_CIPHER_FAKE_CTX *pctx, const OSSL_PARAM *params) 30 { 31 const OSSL_PARAM *p; 32 char key_name[MAX_KEYNAME]; 33 char *pval = key_name; 34 35 memset(key_name, 0, MAX_KEYNAME); 36 37 p = OSSL_PARAM_locate_const(params, FAKE_CIPHER_PARAM_KEY_NAME); 38 if (p != NULL) { 39 if (!OSSL_PARAM_get_utf8_string(p, &pval, sizeof(key_name))) { 40 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 41 return 0; 42 } 43 44 memcpy(pctx->key_name, key_name, sizeof(key_name)); 45 } 46 47 p = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES); 48 if (p != NULL) { 49 size_t data_size = p->data_size; 50 51 if (data_size > FAKE_KEY_LEN) 52 data_size = FAKE_KEY_LEN; 53 memcpy(pctx->key, p->data, data_size); 54 } 55 56 return 1; 57 } 58 59 static void fake_skeymgmt_free(void *keydata) 60 { 61 OPENSSL_free(keydata); 62 } 63 64 static void *fake_skeymgmt_import(void *provctx, int selection, const OSSL_PARAM *p) 65 { 66 PROV_CIPHER_FAKE_CTX *ctx = NULL; 67 68 if (!TEST_ptr(ctx = OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)))) 69 return 0; 70 71 if (ctx_from_key_params(ctx, p) != 1) { 72 OPENSSL_free(ctx); 73 return NULL; 74 } 75 76 return ctx; 77 } 78 79 static int fake_skeymgmt_export(void *keydata, int selection, 80 OSSL_CALLBACK *param_callback, void *cbarg) 81 { 82 OSSL_PARAM params[3]; 83 PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)keydata; 84 OSSL_PARAM *p = params; 85 86 if (selection & OSSL_SKEYMGMT_SELECT_PARAMETERS) { 87 *p = OSSL_PARAM_construct_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, 88 ctx->key_name, 89 strlen(ctx->key_name)); 90 p++; 91 } 92 93 if (selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) { 94 *p = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES, 95 ctx->key, 96 sizeof(ctx->key)); 97 p++; 98 } 99 *p = OSSL_PARAM_construct_end(); 100 101 return param_callback(params, cbarg); 102 } 103 104 static const OSSL_DISPATCH fake_skeymgmt_funcs[] = { 105 { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))fake_skeymgmt_free }, 106 { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))fake_skeymgmt_import }, 107 { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))fake_skeymgmt_export }, 108 OSSL_DISPATCH_END 109 }; 110 111 static const OSSL_ALGORITHM fake_skeymgmt_algs[] = { 112 { "fake_cipher", FAKE_CIPHER_FETCH_PROPS, fake_skeymgmt_funcs, "Fake Cipher Key Management" }, 113 { NULL, NULL, NULL, NULL } 114 }; 115 static OSSL_FUNC_cipher_newctx_fn fake_newctx; 116 117 static void *fake_newctx(void *provctx) 118 { 119 return OPENSSL_zalloc(sizeof(PROV_CIPHER_FAKE_CTX)); 120 } 121 122 static OSSL_FUNC_cipher_freectx_fn fake_freectx; 123 static void fake_freectx(void *vctx) 124 { 125 OPENSSL_free(vctx); 126 } 127 128 static int fake_skey_init(PROV_CIPHER_FAKE_CTX *ctx, void *pkeyparam, 129 const unsigned char *iv, size_t ivlen, 130 const OSSL_PARAM params[]) 131 { 132 if (pkeyparam != NULL) 133 memcpy(ctx, pkeyparam, sizeof(PROV_CIPHER_FAKE_CTX)); 134 135 return 1; 136 } 137 138 static OSSL_FUNC_cipher_encrypt_skey_init_fn fake_skey_einit; 139 static int fake_skey_einit(void *vctx, void *pkeyparam, 140 const unsigned char *iv, size_t ivlen, 141 const OSSL_PARAM params[]) 142 { 143 PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; 144 145 if (fake_skey_init(ctx, pkeyparam, iv, ivlen, params) != 1) 146 return 0; 147 148 return 1; 149 } 150 151 static OSSL_FUNC_cipher_decrypt_skey_init_fn fake_skey_dinit; 152 static int fake_skey_dinit(void *vctx, void *pkeyparam, 153 const unsigned char *iv, size_t ivlen, 154 const OSSL_PARAM params[]) 155 { 156 PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; 157 158 if (fake_skey_init(ctx, pkeyparam, iv, ivlen, params) != 1) 159 return 0; 160 161 return 1; 162 } 163 164 static OSSL_FUNC_cipher_cipher_fn fake_cipher; 165 static int fake_cipher(void *vctx, unsigned char *out, size_t *outl, 166 size_t outsize, const unsigned char *in, size_t inl) 167 { 168 PROV_CIPHER_FAKE_CTX *ctx = (PROV_CIPHER_FAKE_CTX *)vctx; 169 size_t i; 170 171 if (out == NULL || outsize < inl) 172 return 0; 173 if (in != out) 174 memcpy(out, in, inl); 175 for (i = 0; i < inl; i++) 176 out[i] ^= ctx->key[i % FAKE_KEY_LEN]; 177 *outl = inl; 178 return 1; 179 } 180 181 static OSSL_FUNC_cipher_final_fn fake_final; 182 static int fake_final(void *vctx, unsigned char *out, size_t *outl, 183 size_t outsize) 184 { 185 *outl = 0; 186 return 1; 187 } 188 189 static OSSL_FUNC_cipher_get_params_fn fake_get_params; 190 static int fake_get_params(OSSL_PARAM params[]) 191 { 192 /* FIXME copy of ossl_cipher_generic_get_params */ 193 OSSL_PARAM *p; 194 195 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 196 if (p != NULL && !OSSL_PARAM_set_size_t(p, 1)) { 197 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 198 return 0; 199 } 200 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); 201 if (p != NULL && !OSSL_PARAM_set_size_t(p, 1)) { 202 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 203 return 0; 204 } 205 return 1; 206 } 207 208 static const OSSL_PARAM fake_known_gettable_ctx_params[] = { 209 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 210 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL), 211 OSSL_PARAM_END 212 }; 213 214 static OSSL_FUNC_cipher_gettable_ctx_params_fn fake_gettable_ctx_params; 215 static const OSSL_PARAM *fake_gettable_ctx_params(ossl_unused void *cctx, 216 ossl_unused void *provctx) 217 { 218 return fake_known_gettable_ctx_params; 219 } 220 221 static OSSL_FUNC_cipher_get_ctx_params_fn fake_get_ctx_params; 222 static int fake_get_ctx_params(void *vctx, OSSL_PARAM params[]) 223 { 224 OSSL_PARAM *p; 225 226 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); 227 if (p != NULL && !OSSL_PARAM_set_size_t(p, 0)) { 228 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 229 return 0; 230 } 231 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 232 if (p != NULL && !OSSL_PARAM_set_size_t(p, sizeof((PROV_CIPHER_FAKE_CTX *)vctx)->key)) { 233 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 234 return 0; 235 } 236 return 1; 237 } 238 239 static const OSSL_PARAM fake_known_settable_ctx_params[] = { 240 OSSL_PARAM_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME, NULL, 0), 241 OSSL_PARAM_END 242 }; 243 244 static OSSL_FUNC_cipher_settable_ctx_params_fn fake_settable_ctx_params; 245 static const OSSL_PARAM *fake_settable_ctx_params(ossl_unused void *cctx, 246 ossl_unused void *provctx) 247 { 248 return fake_known_settable_ctx_params; 249 } 250 251 static const OSSL_DISPATCH ossl_fake_functions[] = { 252 { OSSL_FUNC_CIPHER_NEWCTX, 253 (void (*)(void)) fake_newctx }, 254 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) fake_freectx }, 255 { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) fake_newctx }, 256 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) fake_cipher }, 257 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) fake_final }, 258 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) fake_cipher }, 259 { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void)) fake_get_params }, 260 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void)) fake_get_ctx_params }, 261 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, 262 (void (*)(void)) fake_gettable_ctx_params }, 263 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, 264 (void (*)(void)) fake_settable_ctx_params }, 265 { OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT, (void (*)(void)) fake_skey_einit }, 266 { OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT, (void (*)(void)) fake_skey_dinit }, 267 OSSL_DISPATCH_END 268 }; 269 270 static const OSSL_ALGORITHM fake_cipher_algs[] = { 271 { "fake_cipher", FAKE_CIPHER_FETCH_PROPS, ossl_fake_functions}, 272 { NULL, NULL, NULL } 273 }; 274 275 static const OSSL_ALGORITHM *fake_cipher_query(void *provctx, 276 int operation_id, 277 int *no_cache) 278 { 279 *no_cache = 0; 280 switch (operation_id) { 281 case OSSL_OP_CIPHER: 282 return fake_cipher_algs; 283 case OSSL_OP_SKEYMGMT: 284 return fake_skeymgmt_algs; 285 } 286 return NULL; 287 } 288 289 /* Functions we provide to the core */ 290 static const OSSL_DISPATCH fake_cipher_method[] = { 291 { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free }, 292 { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_cipher_query }, 293 OSSL_DISPATCH_END 294 }; 295 296 static int fake_cipher_provider_init(const OSSL_CORE_HANDLE *handle, 297 const OSSL_DISPATCH *in, 298 const OSSL_DISPATCH **out, void **provctx) 299 { 300 if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) 301 return 0; 302 *out = fake_cipher_method; 303 return 1; 304 } 305 306 OSSL_PROVIDER *fake_cipher_start(OSSL_LIB_CTX *libctx) 307 { 308 OSSL_PROVIDER *p; 309 310 if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, FAKE_PROV_NAME, 311 fake_cipher_provider_init)) 312 || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, FAKE_PROV_NAME, 1))) 313 return NULL; 314 315 return p; 316 } 317 318 void fake_cipher_finish(OSSL_PROVIDER *p) 319 { 320 OSSL_PROVIDER_unload(p); 321 } 322