1 /* 2 * Copyright 2020-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/core.h> 11 #include <openssl/core_dispatch.h> 12 #include <openssl/decoder.h> 13 #include <openssl/ui.h> 14 #include "internal/core.h" 15 #include "internal/namemap.h" 16 #include "internal/property.h" 17 #include "internal/provider.h" 18 #include "crypto/decoder.h" 19 #include "encoder_local.h" 20 #include "crypto/context.h" 21 22 /* 23 * Decoder can have multiple names, separated with colons in a name string 24 */ 25 #define NAME_SEPARATOR ':' 26 27 static void ossl_decoder_free(void *data) 28 { 29 OSSL_DECODER_free(data); 30 } 31 32 static int ossl_decoder_up_ref(void *data) 33 { 34 return OSSL_DECODER_up_ref(data); 35 } 36 37 /* Simple method structure constructor and destructor */ 38 static OSSL_DECODER *ossl_decoder_new(void) 39 { 40 OSSL_DECODER *decoder = NULL; 41 42 if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL) 43 return NULL; 44 if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) { 45 OSSL_DECODER_free(decoder); 46 return NULL; 47 } 48 49 return decoder; 50 } 51 52 int OSSL_DECODER_up_ref(OSSL_DECODER *decoder) 53 { 54 int ref = 0; 55 56 CRYPTO_UP_REF(&decoder->base.refcnt, &ref); 57 return 1; 58 } 59 60 void OSSL_DECODER_free(OSSL_DECODER *decoder) 61 { 62 int ref = 0; 63 64 if (decoder == NULL) 65 return; 66 67 CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref); 68 if (ref > 0) 69 return; 70 OPENSSL_free(decoder->base.name); 71 ossl_property_free(decoder->base.parsed_propdef); 72 ossl_provider_free(decoder->base.prov); 73 CRYPTO_FREE_REF(&decoder->base.refcnt); 74 OPENSSL_free(decoder); 75 } 76 77 /* Data to be passed through ossl_method_construct() */ 78 struct decoder_data_st { 79 OSSL_LIB_CTX *libctx; 80 int id; /* For get_decoder_from_store() */ 81 const char *names; /* For get_decoder_from_store() */ 82 const char *propquery; /* For get_decoder_from_store() */ 83 84 OSSL_METHOD_STORE *tmp_store; /* For get_tmp_decoder_store() */ 85 86 unsigned int flag_construct_error_occurred : 1; 87 }; 88 89 /* 90 * Generic routines to fetch / create DECODER methods with 91 * ossl_method_construct() 92 */ 93 94 /* Temporary decoder method store, constructor and destructor */ 95 static void *get_tmp_decoder_store(void *data) 96 { 97 struct decoder_data_st *methdata = data; 98 99 if (methdata->tmp_store == NULL) 100 methdata->tmp_store = ossl_method_store_new(methdata->libctx); 101 return methdata->tmp_store; 102 } 103 104 static void dealloc_tmp_decoder_store(void *store) 105 { 106 if (store != NULL) 107 ossl_method_store_free(store); 108 } 109 110 /* Get the permanent decoder store */ 111 static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx) 112 { 113 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX); 114 } 115 116 static int reserve_decoder_store(void *store, void *data) 117 { 118 struct decoder_data_st *methdata = data; 119 120 if (store == NULL 121 && (store = get_decoder_store(methdata->libctx)) == NULL) 122 return 0; 123 124 return ossl_method_lock_store(store); 125 } 126 127 static int unreserve_decoder_store(void *store, void *data) 128 { 129 struct decoder_data_st *methdata = data; 130 131 if (store == NULL 132 && (store = get_decoder_store(methdata->libctx)) == NULL) 133 return 0; 134 135 return ossl_method_unlock_store(store); 136 } 137 138 /* Get decoder methods from a store, or put one in */ 139 static void *get_decoder_from_store(void *store, const OSSL_PROVIDER **prov, 140 void *data) 141 { 142 struct decoder_data_st *methdata = data; 143 void *method = NULL; 144 int id; 145 146 /* 147 * get_decoder_from_store() is only called to try and get the method 148 * that OSSL_DECODER_fetch() is asking for, and the name or name id are 149 * passed via methdata. 150 */ 151 if ((id = methdata->id) == 0 && methdata->names != NULL) { 152 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); 153 const char *names = methdata->names; 154 const char *q = strchr(names, NAME_SEPARATOR); 155 size_t l = (q == NULL ? strlen(names) : (size_t)(q - names)); 156 157 if (namemap == 0) 158 return NULL; 159 id = ossl_namemap_name2num_n(namemap, names, l); 160 } 161 162 if (id == 0) 163 return NULL; 164 165 if (store == NULL 166 && (store = get_decoder_store(methdata->libctx)) == NULL) 167 return NULL; 168 169 if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method)) 170 return NULL; 171 return method; 172 } 173 174 static int put_decoder_in_store(void *store, void *method, 175 const OSSL_PROVIDER *prov, 176 const char *names, const char *propdef, 177 void *data) 178 { 179 struct decoder_data_st *methdata = data; 180 OSSL_NAMEMAP *namemap; 181 int id; 182 size_t l = 0; 183 184 /* 185 * put_decoder_in_store() is only called with an OSSL_DECODER method that 186 * was successfully created by construct_decoder() below, which means that 187 * all the names should already be stored in the namemap with the same 188 * numeric identity, so just use the first to get that identity. 189 */ 190 if (names != NULL) { 191 const char *q = strchr(names, NAME_SEPARATOR); 192 193 l = (q == NULL ? strlen(names) : (size_t)(q - names)); 194 } 195 196 if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL 197 || (id = ossl_namemap_name2num_n(namemap, names, l)) == 0) 198 return 0; 199 200 if (store == NULL && (store = get_decoder_store(methdata->libctx)) == NULL) 201 return 0; 202 203 return ossl_method_store_add(store, prov, id, propdef, method, 204 ossl_decoder_up_ref, 205 ossl_decoder_free); 206 } 207 208 /* Create and populate a decoder method */ 209 void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, 210 OSSL_PROVIDER *prov) 211 { 212 OSSL_DECODER *decoder = NULL; 213 const OSSL_DISPATCH *fns = algodef->implementation; 214 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 215 216 if ((decoder = ossl_decoder_new()) == NULL) 217 return NULL; 218 decoder->base.id = id; 219 if ((decoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) { 220 OSSL_DECODER_free(decoder); 221 return NULL; 222 } 223 decoder->base.algodef = algodef; 224 if ((decoder->base.parsed_propdef 225 = ossl_parse_property(libctx, algodef->property_definition)) 226 == NULL) { 227 OSSL_DECODER_free(decoder); 228 return NULL; 229 } 230 231 for (; fns->function_id != 0; fns++) { 232 switch (fns->function_id) { 233 case OSSL_FUNC_DECODER_NEWCTX: 234 if (decoder->newctx == NULL) 235 decoder->newctx = OSSL_FUNC_decoder_newctx(fns); 236 break; 237 case OSSL_FUNC_DECODER_FREECTX: 238 if (decoder->freectx == NULL) 239 decoder->freectx = OSSL_FUNC_decoder_freectx(fns); 240 break; 241 case OSSL_FUNC_DECODER_GET_PARAMS: 242 if (decoder->get_params == NULL) 243 decoder->get_params = OSSL_FUNC_decoder_get_params(fns); 244 break; 245 case OSSL_FUNC_DECODER_GETTABLE_PARAMS: 246 if (decoder->gettable_params == NULL) 247 decoder->gettable_params = OSSL_FUNC_decoder_gettable_params(fns); 248 break; 249 case OSSL_FUNC_DECODER_SET_CTX_PARAMS: 250 if (decoder->set_ctx_params == NULL) 251 decoder->set_ctx_params = OSSL_FUNC_decoder_set_ctx_params(fns); 252 break; 253 case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS: 254 if (decoder->settable_ctx_params == NULL) 255 decoder->settable_ctx_params = OSSL_FUNC_decoder_settable_ctx_params(fns); 256 break; 257 case OSSL_FUNC_DECODER_DOES_SELECTION: 258 if (decoder->does_selection == NULL) 259 decoder->does_selection = OSSL_FUNC_decoder_does_selection(fns); 260 break; 261 case OSSL_FUNC_DECODER_DECODE: 262 if (decoder->decode == NULL) 263 decoder->decode = OSSL_FUNC_decoder_decode(fns); 264 break; 265 case OSSL_FUNC_DECODER_EXPORT_OBJECT: 266 if (decoder->export_object == NULL) 267 decoder->export_object = OSSL_FUNC_decoder_export_object(fns); 268 break; 269 } 270 } 271 /* 272 * Try to check that the method is sensible. 273 * If you have a constructor, you must have a destructor and vice versa. 274 * You must have at least one of the encoding driver functions. 275 */ 276 if (!((decoder->newctx == NULL && decoder->freectx == NULL) 277 || (decoder->newctx != NULL && decoder->freectx != NULL)) 278 || decoder->decode == NULL) { 279 OSSL_DECODER_free(decoder); 280 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); 281 return NULL; 282 } 283 284 if (prov != NULL && !ossl_provider_up_ref(prov)) { 285 OSSL_DECODER_free(decoder); 286 return NULL; 287 } 288 289 decoder->base.prov = prov; 290 return decoder; 291 } 292 293 /* 294 * The core fetching functionality passes the names of the implementation. 295 * This function is responsible to getting an identity number for them, 296 * then call ossl_decoder_from_algorithm() with that identity number. 297 */ 298 static void *construct_decoder(const OSSL_ALGORITHM *algodef, 299 OSSL_PROVIDER *prov, void *data) 300 { 301 /* 302 * This function is only called if get_decoder_from_store() returned 303 * NULL, so it's safe to say that of all the spots to create a new 304 * namemap entry, this is it. Should the name already exist there, we 305 * know that ossl_namemap_add() will return its corresponding number. 306 */ 307 struct decoder_data_st *methdata = data; 308 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 309 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 310 const char *names = algodef->algorithm_names; 311 int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); 312 void *method = NULL; 313 314 if (id != 0) 315 method = ossl_decoder_from_algorithm(id, algodef, prov); 316 317 /* 318 * Flag to indicate that there was actual construction errors. This 319 * helps inner_evp_generic_fetch() determine what error it should 320 * record on inaccessible algorithms. 321 */ 322 if (method == NULL) 323 methdata->flag_construct_error_occurred = 1; 324 325 return method; 326 } 327 328 /* Intermediary function to avoid ugly casts, used below */ 329 static void destruct_decoder(void *method, void *data) 330 { 331 OSSL_DECODER_free(method); 332 } 333 334 static int up_ref_decoder(void *method) 335 { 336 return OSSL_DECODER_up_ref(method); 337 } 338 339 static void free_decoder(void *method) 340 { 341 OSSL_DECODER_free(method); 342 } 343 344 /* Fetching support. Can fetch by numeric identity or by name */ 345 static OSSL_DECODER * 346 inner_ossl_decoder_fetch(struct decoder_data_st *methdata, 347 const char *name, const char *properties) 348 { 349 OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx); 350 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); 351 const char *const propq = properties != NULL ? properties : ""; 352 void *method = NULL; 353 int unsupported, id; 354 355 if (store == NULL || namemap == NULL) { 356 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT); 357 return NULL; 358 } 359 360 id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0; 361 362 /* 363 * If we haven't found the name yet, chances are that the algorithm to 364 * be fetched is unsupported. 365 */ 366 unsupported = id == 0; 367 368 if (id == 0 369 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { 370 OSSL_METHOD_CONSTRUCT_METHOD mcm = { 371 get_tmp_decoder_store, 372 reserve_decoder_store, 373 unreserve_decoder_store, 374 get_decoder_from_store, 375 put_decoder_in_store, 376 construct_decoder, 377 destruct_decoder 378 }; 379 OSSL_PROVIDER *prov = NULL; 380 381 methdata->id = id; 382 methdata->names = name; 383 methdata->propquery = propq; 384 methdata->flag_construct_error_occurred = 0; 385 if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_DECODER, 386 &prov, 0 /* !force_cache */, 387 &mcm, methdata)) 388 != NULL) { 389 /* 390 * If construction did create a method for us, we know that 391 * there is a correct name_id and meth_id, since those have 392 * already been calculated in get_decoder_from_store() and 393 * put_decoder_in_store() above. 394 */ 395 if (id == 0 && name != NULL) 396 id = ossl_namemap_name2num(namemap, name); 397 if (id != 0) 398 ossl_method_store_cache_set(store, prov, id, propq, method, 399 up_ref_decoder, free_decoder); 400 } 401 402 /* 403 * If we never were in the constructor, the algorithm to be fetched 404 * is unsupported. 405 */ 406 unsupported = !methdata->flag_construct_error_occurred; 407 } 408 409 if ((id != 0 || name != NULL) && method == NULL) { 410 int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED; 411 412 if (name == NULL) 413 name = ossl_namemap_num2name(namemap, id, 0); 414 ERR_raise_data(ERR_LIB_OSSL_DECODER, code, 415 "%s, Name (%s : %d), Properties (%s)", 416 ossl_lib_ctx_get_descriptor(methdata->libctx), 417 name == NULL ? "<null>" : name, id, 418 properties == NULL ? "<null>" : properties); 419 } 420 421 return method; 422 } 423 424 OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name, 425 const char *properties) 426 { 427 struct decoder_data_st methdata; 428 void *method; 429 430 methdata.libctx = libctx; 431 methdata.tmp_store = NULL; 432 method = inner_ossl_decoder_fetch(&methdata, name, properties); 433 dealloc_tmp_decoder_store(methdata.tmp_store); 434 return method; 435 } 436 437 int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx) 438 { 439 OSSL_METHOD_STORE *store = get_decoder_store(libctx); 440 441 if (store != NULL) 442 return ossl_method_store_cache_flush_all(store); 443 return 1; 444 } 445 446 int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov) 447 { 448 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 449 OSSL_METHOD_STORE *store = get_decoder_store(libctx); 450 451 if (store != NULL) 452 return ossl_method_store_remove_all_provided(store, prov); 453 return 1; 454 } 455 456 /* 457 * Library of basic method functions 458 */ 459 460 const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *decoder) 461 { 462 if (!ossl_assert(decoder != NULL)) { 463 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 464 return 0; 465 } 466 467 return decoder->base.prov; 468 } 469 470 const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder) 471 { 472 if (!ossl_assert(decoder != NULL)) { 473 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 474 return 0; 475 } 476 477 return decoder->base.algodef->property_definition; 478 } 479 480 const OSSL_PROPERTY_LIST * 481 ossl_decoder_parsed_properties(const OSSL_DECODER *decoder) 482 { 483 if (!ossl_assert(decoder != NULL)) { 484 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 485 return 0; 486 } 487 488 return decoder->base.parsed_propdef; 489 } 490 491 int ossl_decoder_get_number(const OSSL_DECODER *decoder) 492 { 493 if (!ossl_assert(decoder != NULL)) { 494 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 495 return 0; 496 } 497 498 return decoder->base.id; 499 } 500 501 const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder) 502 { 503 return decoder->base.name; 504 } 505 506 const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder) 507 { 508 return decoder->base.algodef->algorithm_description; 509 } 510 511 int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name) 512 { 513 if (decoder->base.prov != NULL) { 514 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 515 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 516 517 return ossl_namemap_name2num(namemap, name) == decoder->base.id; 518 } 519 return 0; 520 } 521 522 static int resolve_name(OSSL_DECODER *decoder, const char *name) 523 { 524 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 525 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 526 527 return ossl_namemap_name2num(namemap, name); 528 } 529 530 int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, const char *name, int *id_cache) 531 { 532 int id = *id_cache; 533 534 if (id <= 0) 535 *id_cache = id = resolve_name(decoder, name); 536 537 return id > 0 && ossl_decoder_get_number(decoder) == id; 538 } 539 540 struct do_one_data_st { 541 void (*user_fn)(OSSL_DECODER *decoder, void *arg); 542 void *user_arg; 543 }; 544 545 static void do_one(ossl_unused int id, void *method, void *arg) 546 { 547 struct do_one_data_st *data = arg; 548 549 data->user_fn(method, data->user_arg); 550 } 551 552 void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx, 553 void (*user_fn)(OSSL_DECODER *decoder, 554 void *arg), 555 void *user_arg) 556 { 557 struct decoder_data_st methdata; 558 struct do_one_data_st data; 559 560 methdata.libctx = libctx; 561 methdata.tmp_store = NULL; 562 (void)inner_ossl_decoder_fetch(&methdata, NULL, NULL /* properties */); 563 564 data.user_fn = user_fn; 565 data.user_arg = user_arg; 566 if (methdata.tmp_store != NULL) 567 ossl_method_store_do_all(methdata.tmp_store, &do_one, &data); 568 ossl_method_store_do_all(get_decoder_store(libctx), &do_one, &data); 569 dealloc_tmp_decoder_store(methdata.tmp_store); 570 } 571 572 int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder, 573 void (*fn)(const char *name, void *data), 574 void *data) 575 { 576 if (decoder == NULL) 577 return 0; 578 579 if (decoder->base.prov != NULL) { 580 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 581 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 582 583 return ossl_namemap_doall_names(namemap, decoder->base.id, fn, data); 584 } 585 586 return 1; 587 } 588 589 const OSSL_PARAM * 590 OSSL_DECODER_gettable_params(OSSL_DECODER *decoder) 591 { 592 if (decoder != NULL && decoder->gettable_params != NULL) { 593 void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder)); 594 595 return decoder->gettable_params(provctx); 596 } 597 return NULL; 598 } 599 600 int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[]) 601 { 602 if (decoder != NULL && decoder->get_params != NULL) 603 return decoder->get_params(params); 604 return 0; 605 } 606 607 const OSSL_PARAM * 608 OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder) 609 { 610 if (decoder != NULL && decoder->settable_ctx_params != NULL) { 611 void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder)); 612 613 return decoder->settable_ctx_params(provctx); 614 } 615 return NULL; 616 } 617 618 /* 619 * Decoder context support 620 */ 621 622 /* 623 * |encoder| value NULL is valid, and signifies that there is no decoder. 624 * This is useful to provide fallback mechanisms. 625 * Functions that want to verify if there is a decoder can do so with 626 * OSSL_DECODER_CTX_get_decoder() 627 */ 628 OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void) 629 { 630 OSSL_DECODER_CTX *ctx; 631 632 ctx = OPENSSL_zalloc(sizeof(*ctx)); 633 return ctx; 634 } 635 636 int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx, 637 const OSSL_PARAM params[]) 638 { 639 int ok = 1; 640 size_t i; 641 size_t l; 642 643 if (!ossl_assert(ctx != NULL)) { 644 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 645 return 0; 646 } 647 648 if (ctx->decoder_insts == NULL) 649 return 1; 650 651 l = OSSL_DECODER_CTX_get_num_decoders(ctx); 652 for (i = 0; i < l; i++) { 653 OSSL_DECODER_INSTANCE *decoder_inst = sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); 654 OSSL_DECODER *decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst); 655 OSSL_DECODER *decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst); 656 657 if (decoderctx == NULL || decoder->set_ctx_params == NULL) 658 continue; 659 if (!decoder->set_ctx_params(decoderctx, params)) 660 ok = 0; 661 } 662 return ok; 663 } 664 665 void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx) 666 { 667 if (ctx != NULL) { 668 if (ctx->cleanup != NULL) 669 ctx->cleanup(ctx->construct_data); 670 sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts, 671 ossl_decoder_instance_free); 672 ossl_pw_clear_passphrase_data(&ctx->pwdata); 673 OPENSSL_free(ctx); 674 } 675 } 676