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)) == NULL) { 226 OSSL_DECODER_free(decoder); 227 return NULL; 228 } 229 230 for (; fns->function_id != 0; fns++) { 231 switch (fns->function_id) { 232 case OSSL_FUNC_DECODER_NEWCTX: 233 if (decoder->newctx == NULL) 234 decoder->newctx = OSSL_FUNC_decoder_newctx(fns); 235 break; 236 case OSSL_FUNC_DECODER_FREECTX: 237 if (decoder->freectx == NULL) 238 decoder->freectx = OSSL_FUNC_decoder_freectx(fns); 239 break; 240 case OSSL_FUNC_DECODER_GET_PARAMS: 241 if (decoder->get_params == NULL) 242 decoder->get_params = 243 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 = 248 OSSL_FUNC_decoder_gettable_params(fns); 249 break; 250 case OSSL_FUNC_DECODER_SET_CTX_PARAMS: 251 if (decoder->set_ctx_params == NULL) 252 decoder->set_ctx_params = 253 OSSL_FUNC_decoder_set_ctx_params(fns); 254 break; 255 case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS: 256 if (decoder->settable_ctx_params == NULL) 257 decoder->settable_ctx_params = 258 OSSL_FUNC_decoder_settable_ctx_params(fns); 259 break; 260 case OSSL_FUNC_DECODER_DOES_SELECTION: 261 if (decoder->does_selection == NULL) 262 decoder->does_selection = 263 OSSL_FUNC_decoder_does_selection(fns); 264 break; 265 case OSSL_FUNC_DECODER_DECODE: 266 if (decoder->decode == NULL) 267 decoder->decode = OSSL_FUNC_decoder_decode(fns); 268 break; 269 case OSSL_FUNC_DECODER_EXPORT_OBJECT: 270 if (decoder->export_object == NULL) 271 decoder->export_object = OSSL_FUNC_decoder_export_object(fns); 272 break; 273 } 274 } 275 /* 276 * Try to check that the method is sensible. 277 * If you have a constructor, you must have a destructor and vice versa. 278 * You must have at least one of the encoding driver functions. 279 */ 280 if (!((decoder->newctx == NULL && decoder->freectx == NULL) 281 || (decoder->newctx != NULL && decoder->freectx != NULL)) 282 || decoder->decode == NULL) { 283 OSSL_DECODER_free(decoder); 284 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); 285 return NULL; 286 } 287 288 if (prov != NULL && !ossl_provider_up_ref(prov)) { 289 OSSL_DECODER_free(decoder); 290 return NULL; 291 } 292 293 decoder->base.prov = prov; 294 return decoder; 295 } 296 297 298 /* 299 * The core fetching functionality passes the names of the implementation. 300 * This function is responsible to getting an identity number for them, 301 * then call ossl_decoder_from_algorithm() with that identity number. 302 */ 303 static void *construct_decoder(const OSSL_ALGORITHM *algodef, 304 OSSL_PROVIDER *prov, void *data) 305 { 306 /* 307 * This function is only called if get_decoder_from_store() returned 308 * NULL, so it's safe to say that of all the spots to create a new 309 * namemap entry, this is it. Should the name already exist there, we 310 * know that ossl_namemap_add() will return its corresponding number. 311 */ 312 struct decoder_data_st *methdata = data; 313 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 314 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 315 const char *names = algodef->algorithm_names; 316 int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); 317 void *method = NULL; 318 319 if (id != 0) 320 method = ossl_decoder_from_algorithm(id, algodef, prov); 321 322 /* 323 * Flag to indicate that there was actual construction errors. This 324 * helps inner_evp_generic_fetch() determine what error it should 325 * record on inaccessible algorithms. 326 */ 327 if (method == NULL) 328 methdata->flag_construct_error_occurred = 1; 329 330 return method; 331 } 332 333 /* Intermediary function to avoid ugly casts, used below */ 334 static void destruct_decoder(void *method, void *data) 335 { 336 OSSL_DECODER_free(method); 337 } 338 339 static int up_ref_decoder(void *method) 340 { 341 return OSSL_DECODER_up_ref(method); 342 } 343 344 static void free_decoder(void *method) 345 { 346 OSSL_DECODER_free(method); 347 } 348 349 /* Fetching support. Can fetch by numeric identity or by name */ 350 static OSSL_DECODER * 351 inner_ossl_decoder_fetch(struct decoder_data_st *methdata, 352 const char *name, const char *properties) 353 { 354 OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx); 355 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); 356 const char *const propq = properties != NULL ? properties : ""; 357 void *method = NULL; 358 int unsupported, id; 359 360 if (store == NULL || namemap == NULL) { 361 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT); 362 return NULL; 363 } 364 365 id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0; 366 367 /* 368 * If we haven't found the name yet, chances are that the algorithm to 369 * be fetched is unsupported. 370 */ 371 unsupported = id == 0; 372 373 if (id == 0 374 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { 375 OSSL_METHOD_CONSTRUCT_METHOD mcm = { 376 get_tmp_decoder_store, 377 reserve_decoder_store, 378 unreserve_decoder_store, 379 get_decoder_from_store, 380 put_decoder_in_store, 381 construct_decoder, 382 destruct_decoder 383 }; 384 OSSL_PROVIDER *prov = NULL; 385 386 methdata->id = id; 387 methdata->names = name; 388 methdata->propquery = propq; 389 methdata->flag_construct_error_occurred = 0; 390 if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_DECODER, 391 &prov, 0 /* !force_cache */, 392 &mcm, methdata)) != NULL) { 393 /* 394 * If construction did create a method for us, we know that 395 * there is a correct name_id and meth_id, since those have 396 * already been calculated in get_decoder_from_store() and 397 * put_decoder_in_store() above. 398 */ 399 if (id == 0 && name != NULL) 400 id = ossl_namemap_name2num(namemap, name); 401 if (id != 0) 402 ossl_method_store_cache_set(store, prov, id, propq, method, 403 up_ref_decoder, free_decoder); 404 } 405 406 /* 407 * If we never were in the constructor, the algorithm to be fetched 408 * is unsupported. 409 */ 410 unsupported = !methdata->flag_construct_error_occurred; 411 } 412 413 if ((id != 0 || name != NULL) && method == NULL) { 414 int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED; 415 416 if (name == NULL) 417 name = ossl_namemap_num2name(namemap, id, 0); 418 ERR_raise_data(ERR_LIB_OSSL_DECODER, code, 419 "%s, Name (%s : %d), Properties (%s)", 420 ossl_lib_ctx_get_descriptor(methdata->libctx), 421 name == NULL ? "<null>" : name, id, 422 properties == NULL ? "<null>" : properties); 423 } 424 425 return method; 426 } 427 428 OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name, 429 const char *properties) 430 { 431 struct decoder_data_st methdata; 432 void *method; 433 434 methdata.libctx = libctx; 435 methdata.tmp_store = NULL; 436 method = inner_ossl_decoder_fetch(&methdata, name, properties); 437 dealloc_tmp_decoder_store(methdata.tmp_store); 438 return method; 439 } 440 441 int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx) 442 { 443 OSSL_METHOD_STORE *store = get_decoder_store(libctx); 444 445 if (store != NULL) 446 return ossl_method_store_cache_flush_all(store); 447 return 1; 448 } 449 450 int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov) 451 { 452 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 453 OSSL_METHOD_STORE *store = get_decoder_store(libctx); 454 455 if (store != NULL) 456 return ossl_method_store_remove_all_provided(store, prov); 457 return 1; 458 } 459 460 /* 461 * Library of basic method functions 462 */ 463 464 const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *decoder) 465 { 466 if (!ossl_assert(decoder != NULL)) { 467 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 468 return 0; 469 } 470 471 return decoder->base.prov; 472 } 473 474 const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder) 475 { 476 if (!ossl_assert(decoder != NULL)) { 477 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 478 return 0; 479 } 480 481 return decoder->base.algodef->property_definition; 482 } 483 484 const OSSL_PROPERTY_LIST * 485 ossl_decoder_parsed_properties(const OSSL_DECODER *decoder) 486 { 487 if (!ossl_assert(decoder != NULL)) { 488 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 489 return 0; 490 } 491 492 return decoder->base.parsed_propdef; 493 } 494 495 int ossl_decoder_get_number(const OSSL_DECODER *decoder) 496 { 497 if (!ossl_assert(decoder != NULL)) { 498 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 499 return 0; 500 } 501 502 return decoder->base.id; 503 } 504 505 const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder) 506 { 507 return decoder->base.name; 508 } 509 510 const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder) 511 { 512 return decoder->base.algodef->algorithm_description; 513 } 514 515 int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name) 516 { 517 if (decoder->base.prov != NULL) { 518 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 519 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 520 521 return ossl_namemap_name2num(namemap, name) == decoder->base.id; 522 } 523 return 0; 524 } 525 526 static int resolve_name(OSSL_DECODER *decoder, const char *name) 527 { 528 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 529 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 530 531 return ossl_namemap_name2num(namemap, name); 532 } 533 534 int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, const char *name, int *id_cache) 535 { 536 int id = *id_cache; 537 538 if (id <= 0) 539 *id_cache = id = resolve_name(decoder, name); 540 541 return id > 0 && ossl_decoder_get_number(decoder) == id; 542 } 543 544 struct do_one_data_st { 545 void (*user_fn)(OSSL_DECODER *decoder, void *arg); 546 void *user_arg; 547 }; 548 549 static void do_one(ossl_unused int id, void *method, void *arg) 550 { 551 struct do_one_data_st *data = arg; 552 553 data->user_fn(method, data->user_arg); 554 } 555 556 void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx, 557 void (*user_fn)(OSSL_DECODER *decoder, 558 void *arg), 559 void *user_arg) 560 { 561 struct decoder_data_st methdata; 562 struct do_one_data_st data; 563 564 methdata.libctx = libctx; 565 methdata.tmp_store = NULL; 566 (void)inner_ossl_decoder_fetch(&methdata, NULL, NULL /* properties */); 567 568 data.user_fn = user_fn; 569 data.user_arg = user_arg; 570 if (methdata.tmp_store != NULL) 571 ossl_method_store_do_all(methdata.tmp_store, &do_one, &data); 572 ossl_method_store_do_all(get_decoder_store(libctx), &do_one, &data); 573 dealloc_tmp_decoder_store(methdata.tmp_store); 574 } 575 576 int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder, 577 void (*fn)(const char *name, void *data), 578 void *data) 579 { 580 if (decoder == NULL) 581 return 0; 582 583 if (decoder->base.prov != NULL) { 584 OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); 585 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 586 587 return ossl_namemap_doall_names(namemap, decoder->base.id, fn, data); 588 } 589 590 return 1; 591 } 592 593 const OSSL_PARAM * 594 OSSL_DECODER_gettable_params(OSSL_DECODER *decoder) 595 { 596 if (decoder != NULL && decoder->gettable_params != NULL) { 597 void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder)); 598 599 return decoder->gettable_params(provctx); 600 } 601 return NULL; 602 } 603 604 int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[]) 605 { 606 if (decoder != NULL && decoder->get_params != NULL) 607 return decoder->get_params(params); 608 return 0; 609 } 610 611 const OSSL_PARAM * 612 OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder) 613 { 614 if (decoder != NULL && decoder->settable_ctx_params != NULL) { 615 void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder)); 616 617 return decoder->settable_ctx_params(provctx); 618 } 619 return NULL; 620 } 621 622 /* 623 * Decoder context support 624 */ 625 626 /* 627 * |encoder| value NULL is valid, and signifies that there is no decoder. 628 * This is useful to provide fallback mechanisms. 629 * Functions that want to verify if there is a decoder can do so with 630 * OSSL_DECODER_CTX_get_decoder() 631 */ 632 OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void) 633 { 634 OSSL_DECODER_CTX *ctx; 635 636 ctx = OPENSSL_zalloc(sizeof(*ctx)); 637 return ctx; 638 } 639 640 int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx, 641 const OSSL_PARAM params[]) 642 { 643 int ok = 1; 644 size_t i; 645 size_t l; 646 647 if (!ossl_assert(ctx != NULL)) { 648 ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); 649 return 0; 650 } 651 652 if (ctx->decoder_insts == NULL) 653 return 1; 654 655 l = OSSL_DECODER_CTX_get_num_decoders(ctx); 656 for (i = 0; i < l; i++) { 657 OSSL_DECODER_INSTANCE *decoder_inst = 658 sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); 659 OSSL_DECODER *decoder = 660 OSSL_DECODER_INSTANCE_get_decoder(decoder_inst); 661 OSSL_DECODER *decoderctx = 662 OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst); 663 664 if (decoderctx == NULL || decoder->set_ctx_params == NULL) 665 continue; 666 if (!decoder->set_ctx_params(decoderctx, params)) 667 ok = 0; 668 } 669 return ok; 670 } 671 672 void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx) 673 { 674 if (ctx != NULL) { 675 if (ctx->cleanup != NULL) 676 ctx->cleanup(ctx->construct_data); 677 sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts, 678 ossl_decoder_instance_free); 679 ossl_pw_clear_passphrase_data(&ctx->pwdata); 680 OPENSSL_free(ctx); 681 } 682 } 683