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