1 /* 2 * Copyright 2019-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/encoder.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/encoder.h" 19 #include "encoder_local.h" 20 21 /* 22 * Encoder 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_ENCODER *ossl_encoder_new(void) 28 { 29 OSSL_ENCODER *encoder = NULL; 30 31 if ((encoder = OPENSSL_zalloc(sizeof(*encoder))) == NULL 32 || (encoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { 33 OSSL_ENCODER_free(encoder); 34 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); 35 return NULL; 36 } 37 38 encoder->base.refcnt = 1; 39 40 return encoder; 41 } 42 43 int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder) 44 { 45 int ref = 0; 46 47 CRYPTO_UP_REF(&encoder->base.refcnt, &ref, encoder->base.lock); 48 return 1; 49 } 50 51 void OSSL_ENCODER_free(OSSL_ENCODER *encoder) 52 { 53 int ref = 0; 54 55 if (encoder == NULL) 56 return; 57 58 CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref, encoder->base.lock); 59 if (ref > 0) 60 return; 61 OPENSSL_free(encoder->base.name); 62 ossl_property_free(encoder->base.parsed_propdef); 63 ossl_provider_free(encoder->base.prov); 64 CRYPTO_THREAD_lock_free(encoder->base.lock); 65 OPENSSL_free(encoder); 66 } 67 68 /* Permanent encoder method store, constructor and destructor */ 69 static void encoder_store_free(void *vstore) 70 { 71 ossl_method_store_free(vstore); 72 } 73 74 static void *encoder_store_new(OSSL_LIB_CTX *ctx) 75 { 76 return ossl_method_store_new(ctx); 77 } 78 79 80 static const OSSL_LIB_CTX_METHOD encoder_store_method = { 81 /* We want encoder_store to be cleaned up before the provider store */ 82 OSSL_LIB_CTX_METHOD_PRIORITY_2, 83 encoder_store_new, 84 encoder_store_free, 85 }; 86 87 /* Data to be passed through ossl_method_construct() */ 88 struct encoder_data_st { 89 OSSL_LIB_CTX *libctx; 90 int id; /* For get_encoder_from_store() */ 91 const char *names; /* For get_encoder_from_store() */ 92 const char *propquery; /* For get_encoder_from_store() */ 93 94 OSSL_METHOD_STORE *tmp_store; /* For get_tmp_encoder_store() */ 95 96 unsigned int flag_construct_error_occurred : 1; 97 }; 98 99 /* 100 * Generic routines to fetch / create ENCODER methods with 101 * ossl_method_construct() 102 */ 103 104 /* Temporary encoder method store, constructor and destructor */ 105 static void *get_tmp_encoder_store(void *data) 106 { 107 struct encoder_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_encoder_store(void *store) 115 { 116 if (store != NULL) 117 ossl_method_store_free(store); 118 } 119 120 /* Get the permanent encoder store */ 121 static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx) 122 { 123 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX, 124 &encoder_store_method); 125 } 126 127 static int reserve_encoder_store(void *store, void *data) 128 { 129 struct encoder_data_st *methdata = data; 130 131 if (store == NULL 132 && (store = get_encoder_store(methdata->libctx)) == NULL) 133 return 0; 134 135 return ossl_method_lock_store(store); 136 } 137 138 static int unreserve_encoder_store(void *store, void *data) 139 { 140 struct encoder_data_st *methdata = data; 141 142 if (store == NULL 143 && (store = get_encoder_store(methdata->libctx)) == NULL) 144 return 0; 145 146 return ossl_method_unlock_store(store); 147 } 148 149 /* Get encoder methods from a store, or put one in */ 150 static void *get_encoder_from_store(void *store, const OSSL_PROVIDER **prov, 151 void *data) 152 { 153 struct encoder_data_st *methdata = data; 154 void *method = NULL; 155 int id; 156 157 /* 158 * get_encoder_from_store() is only called to try and get the method 159 * that OSSL_ENCODER_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, methdata->names, l); 171 } 172 173 if (id == 0) 174 return NULL; 175 176 if (store == NULL 177 && (store = get_encoder_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_encoder_in_store(void *store, void *method, 186 const OSSL_PROVIDER *prov, 187 const char *names, const char *propdef, 188 void *data) 189 { 190 struct encoder_data_st *methdata = data; 191 OSSL_NAMEMAP *namemap; 192 int id; 193 size_t l = 0; 194 195 /* 196 * put_encoder_in_store() is only called with an OSSL_ENCODER method that 197 * was successfully created by construct_encoder() 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_encoder_store(methdata->libctx)) == NULL) 212 return 0; 213 214 return ossl_method_store_add(store, prov, id, propdef, method, 215 (int (*)(void *))OSSL_ENCODER_up_ref, 216 (void (*)(void *))OSSL_ENCODER_free); 217 } 218 219 /* Create and populate a encoder method */ 220 static void *encoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef, 221 OSSL_PROVIDER *prov) 222 { 223 OSSL_ENCODER *encoder = NULL; 224 const OSSL_DISPATCH *fns = algodef->implementation; 225 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 226 227 if ((encoder = ossl_encoder_new()) == NULL) 228 return NULL; 229 encoder->base.id = id; 230 if ((encoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) { 231 OSSL_ENCODER_free(encoder); 232 return NULL; 233 } 234 encoder->base.algodef = algodef; 235 if ((encoder->base.parsed_propdef 236 = ossl_parse_property(libctx, algodef->property_definition)) == NULL) { 237 OSSL_ENCODER_free(encoder); 238 return NULL; 239 } 240 241 for (; fns->function_id != 0; fns++) { 242 switch (fns->function_id) { 243 case OSSL_FUNC_ENCODER_NEWCTX: 244 if (encoder->newctx == NULL) 245 encoder->newctx = 246 OSSL_FUNC_encoder_newctx(fns); 247 break; 248 case OSSL_FUNC_ENCODER_FREECTX: 249 if (encoder->freectx == NULL) 250 encoder->freectx = 251 OSSL_FUNC_encoder_freectx(fns); 252 break; 253 case OSSL_FUNC_ENCODER_GET_PARAMS: 254 if (encoder->get_params == NULL) 255 encoder->get_params = 256 OSSL_FUNC_encoder_get_params(fns); 257 break; 258 case OSSL_FUNC_ENCODER_GETTABLE_PARAMS: 259 if (encoder->gettable_params == NULL) 260 encoder->gettable_params = 261 OSSL_FUNC_encoder_gettable_params(fns); 262 break; 263 case OSSL_FUNC_ENCODER_SET_CTX_PARAMS: 264 if (encoder->set_ctx_params == NULL) 265 encoder->set_ctx_params = 266 OSSL_FUNC_encoder_set_ctx_params(fns); 267 break; 268 case OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS: 269 if (encoder->settable_ctx_params == NULL) 270 encoder->settable_ctx_params = 271 OSSL_FUNC_encoder_settable_ctx_params(fns); 272 break; 273 case OSSL_FUNC_ENCODER_DOES_SELECTION: 274 if (encoder->does_selection == NULL) 275 encoder->does_selection = 276 OSSL_FUNC_encoder_does_selection(fns); 277 break; 278 case OSSL_FUNC_ENCODER_ENCODE: 279 if (encoder->encode == NULL) 280 encoder->encode = OSSL_FUNC_encoder_encode(fns); 281 break; 282 case OSSL_FUNC_ENCODER_IMPORT_OBJECT: 283 if (encoder->import_object == NULL) 284 encoder->import_object = 285 OSSL_FUNC_encoder_import_object(fns); 286 break; 287 case OSSL_FUNC_ENCODER_FREE_OBJECT: 288 if (encoder->free_object == NULL) 289 encoder->free_object = 290 OSSL_FUNC_encoder_free_object(fns); 291 break; 292 } 293 } 294 /* 295 * Try to check that the method is sensible. 296 * If you have a constructor, you must have a destructor and vice versa. 297 * You must have the encoding driver functions. 298 */ 299 if (!((encoder->newctx == NULL && encoder->freectx == NULL) 300 || (encoder->newctx != NULL && encoder->freectx != NULL) 301 || (encoder->import_object != NULL && encoder->free_object != NULL) 302 || (encoder->import_object == NULL && encoder->free_object == NULL)) 303 || encoder->encode == NULL) { 304 OSSL_ENCODER_free(encoder); 305 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INVALID_PROVIDER_FUNCTIONS); 306 return NULL; 307 } 308 309 if (prov != NULL && !ossl_provider_up_ref(prov)) { 310 OSSL_ENCODER_free(encoder); 311 return NULL; 312 } 313 314 encoder->base.prov = prov; 315 return encoder; 316 } 317 318 319 /* 320 * The core fetching functionality passes the names of the implementation. 321 * This function is responsible to getting an identity number for them, 322 * then call encoder_from_algorithm() with that identity number. 323 */ 324 static void *construct_encoder(const OSSL_ALGORITHM *algodef, 325 OSSL_PROVIDER *prov, void *data) 326 { 327 /* 328 * This function is only called if get_encoder_from_store() returned 329 * NULL, so it's safe to say that of all the spots to create a new 330 * namemap entry, this is it. Should the name already exist there, we 331 * know that ossl_namemap_add() will return its corresponding number. 332 */ 333 struct encoder_data_st *methdata = data; 334 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 335 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 336 const char *names = algodef->algorithm_names; 337 int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); 338 void *method = NULL; 339 340 if (id != 0) 341 method = encoder_from_algorithm(id, algodef, prov); 342 343 /* 344 * Flag to indicate that there was actual construction errors. This 345 * helps inner_evp_generic_fetch() determine what error it should 346 * record on inaccessible algorithms. 347 */ 348 if (method == NULL) 349 methdata->flag_construct_error_occurred = 1; 350 351 return method; 352 } 353 354 /* Intermediary function to avoid ugly casts, used below */ 355 static void destruct_encoder(void *method, void *data) 356 { 357 OSSL_ENCODER_free(method); 358 } 359 360 static int up_ref_encoder(void *method) 361 { 362 return OSSL_ENCODER_up_ref(method); 363 } 364 365 static void free_encoder(void *method) 366 { 367 OSSL_ENCODER_free(method); 368 } 369 370 /* Fetching support. Can fetch by numeric identity or by name */ 371 static OSSL_ENCODER * 372 inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, 373 const char *name, const char *properties) 374 { 375 OSSL_METHOD_STORE *store = get_encoder_store(methdata->libctx); 376 OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); 377 const char *const propq = properties != NULL ? properties : ""; 378 void *method = NULL; 379 int unsupported = 0; 380 381 if (store == NULL || namemap == NULL) { 382 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT); 383 return NULL; 384 } 385 386 /* 387 * If we have been passed both an id and a name, we have an 388 * internal programming error. 389 */ 390 if (!ossl_assert(id == 0 || name == NULL)) { 391 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR); 392 return NULL; 393 } 394 395 if (id == 0) 396 id = ossl_namemap_name2num(namemap, name); 397 398 /* 399 * If we haven't found the name yet, chances are that the algorithm to 400 * be fetched is unsupported. 401 */ 402 if (id == 0) 403 unsupported = 1; 404 405 if (id == 0 406 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { 407 OSSL_METHOD_CONSTRUCT_METHOD mcm = { 408 get_tmp_encoder_store, 409 reserve_encoder_store, 410 unreserve_encoder_store, 411 get_encoder_from_store, 412 put_encoder_in_store, 413 construct_encoder, 414 destruct_encoder 415 }; 416 OSSL_PROVIDER *prov = NULL; 417 418 methdata->id = id; 419 methdata->names = name; 420 methdata->propquery = propq; 421 methdata->flag_construct_error_occurred = 0; 422 if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_ENCODER, 423 &prov, 0 /* !force_cache */, 424 &mcm, methdata)) != NULL) { 425 /* 426 * If construction did create a method for us, we know that 427 * there is a correct name_id and meth_id, since those have 428 * already been calculated in get_encoder_from_store() and 429 * put_encoder_in_store() above. 430 */ 431 if (id == 0) 432 id = ossl_namemap_name2num(namemap, name); 433 ossl_method_store_cache_set(store, prov, id, propq, method, 434 up_ref_encoder, free_encoder); 435 } 436 437 /* 438 * If we never were in the constructor, the algorithm to be fetched 439 * is unsupported. 440 */ 441 unsupported = !methdata->flag_construct_error_occurred; 442 } 443 444 if ((id != 0 || name != NULL) && method == NULL) { 445 int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED; 446 447 if (name == NULL) 448 name = ossl_namemap_num2name(namemap, id, 0); 449 ERR_raise_data(ERR_LIB_OSSL_ENCODER, code, 450 "%s, Name (%s : %d), Properties (%s)", 451 ossl_lib_ctx_get_descriptor(methdata->libctx), 452 name == NULL ? "<null>" : name, id, 453 properties == NULL ? "<null>" : properties); 454 } 455 456 return method; 457 } 458 459 OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *libctx, const char *name, 460 const char *properties) 461 { 462 struct encoder_data_st methdata; 463 void *method; 464 465 methdata.libctx = libctx; 466 methdata.tmp_store = NULL; 467 method = inner_ossl_encoder_fetch(&methdata, 0, name, properties); 468 dealloc_tmp_encoder_store(methdata.tmp_store); 469 return method; 470 } 471 472 OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id, 473 const char *properties) 474 { 475 struct encoder_data_st methdata; 476 void *method; 477 478 methdata.libctx = libctx; 479 methdata.tmp_store = NULL; 480 method = inner_ossl_encoder_fetch(&methdata, id, NULL, properties); 481 dealloc_tmp_encoder_store(methdata.tmp_store); 482 return method; 483 } 484 485 int ossl_encoder_store_cache_flush(OSSL_LIB_CTX *libctx) 486 { 487 OSSL_METHOD_STORE *store = get_encoder_store(libctx); 488 489 if (store != NULL) 490 return ossl_method_store_cache_flush_all(store); 491 return 1; 492 } 493 494 int ossl_encoder_store_remove_all_provided(const OSSL_PROVIDER *prov) 495 { 496 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); 497 OSSL_METHOD_STORE *store = get_encoder_store(libctx); 498 499 if (store != NULL) 500 return ossl_method_store_remove_all_provided(store, prov); 501 return 1; 502 } 503 504 /* 505 * Library of basic method functions 506 */ 507 508 const OSSL_PROVIDER *OSSL_ENCODER_get0_provider(const OSSL_ENCODER *encoder) 509 { 510 if (!ossl_assert(encoder != NULL)) { 511 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); 512 return 0; 513 } 514 515 return encoder->base.prov; 516 } 517 518 const char *OSSL_ENCODER_get0_properties(const OSSL_ENCODER *encoder) 519 { 520 if (!ossl_assert(encoder != NULL)) { 521 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); 522 return 0; 523 } 524 525 return encoder->base.algodef->property_definition; 526 } 527 528 const OSSL_PROPERTY_LIST * 529 ossl_encoder_parsed_properties(const OSSL_ENCODER *encoder) 530 { 531 if (!ossl_assert(encoder != NULL)) { 532 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); 533 return 0; 534 } 535 536 return encoder->base.parsed_propdef; 537 } 538 539 int ossl_encoder_get_number(const OSSL_ENCODER *encoder) 540 { 541 if (!ossl_assert(encoder != NULL)) { 542 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); 543 return 0; 544 } 545 546 return encoder->base.id; 547 } 548 549 const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *encoder) 550 { 551 return encoder->base.name; 552 } 553 554 const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *encoder) 555 { 556 return encoder->base.algodef->algorithm_description; 557 } 558 559 int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name) 560 { 561 if (encoder->base.prov != NULL) { 562 OSSL_LIB_CTX *libctx = ossl_provider_libctx(encoder->base.prov); 563 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 564 565 return ossl_namemap_name2num(namemap, name) == encoder->base.id; 566 } 567 return 0; 568 } 569 570 struct do_one_data_st { 571 void (*user_fn)(OSSL_ENCODER *encoder, void *arg); 572 void *user_arg; 573 }; 574 575 static void do_one(ossl_unused int id, void *method, void *arg) 576 { 577 struct do_one_data_st *data = arg; 578 579 data->user_fn(method, data->user_arg); 580 } 581 582 void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx, 583 void (*user_fn)(OSSL_ENCODER *encoder, 584 void *arg), 585 void *user_arg) 586 { 587 struct encoder_data_st methdata; 588 struct do_one_data_st data; 589 590 methdata.libctx = libctx; 591 methdata.tmp_store = NULL; 592 (void)inner_ossl_encoder_fetch(&methdata, 0, NULL, NULL /* properties */); 593 594 data.user_fn = user_fn; 595 data.user_arg = user_arg; 596 if (methdata.tmp_store != NULL) 597 ossl_method_store_do_all(methdata.tmp_store, &do_one, &data); 598 ossl_method_store_do_all(get_encoder_store(libctx), &do_one, &data); 599 dealloc_tmp_encoder_store(methdata.tmp_store); 600 } 601 602 int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder, 603 void (*fn)(const char *name, void *data), 604 void *data) 605 { 606 if (encoder == NULL) 607 return 0; 608 609 if (encoder->base.prov != NULL) { 610 OSSL_LIB_CTX *libctx = ossl_provider_libctx(encoder->base.prov); 611 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); 612 613 return ossl_namemap_doall_names(namemap, encoder->base.id, fn, data); 614 } 615 616 return 1; 617 } 618 619 const OSSL_PARAM * 620 OSSL_ENCODER_gettable_params(OSSL_ENCODER *encoder) 621 { 622 if (encoder != NULL && encoder->gettable_params != NULL) { 623 void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder)); 624 625 return encoder->gettable_params(provctx); 626 } 627 return NULL; 628 } 629 630 int OSSL_ENCODER_get_params(OSSL_ENCODER *encoder, OSSL_PARAM params[]) 631 { 632 if (encoder != NULL && encoder->get_params != NULL) 633 return encoder->get_params(params); 634 return 0; 635 } 636 637 const OSSL_PARAM *OSSL_ENCODER_settable_ctx_params(OSSL_ENCODER *encoder) 638 { 639 if (encoder != NULL && encoder->settable_ctx_params != NULL) { 640 void *provctx = ossl_provider_ctx(OSSL_ENCODER_get0_provider(encoder)); 641 642 return encoder->settable_ctx_params(provctx); 643 } 644 return NULL; 645 } 646 647 /* 648 * Encoder context support 649 */ 650 651 OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(void) 652 { 653 OSSL_ENCODER_CTX *ctx; 654 655 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) 656 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); 657 658 return ctx; 659 } 660 661 int OSSL_ENCODER_CTX_set_params(OSSL_ENCODER_CTX *ctx, 662 const OSSL_PARAM params[]) 663 { 664 int ok = 1; 665 size_t i; 666 size_t l; 667 668 if (!ossl_assert(ctx != NULL)) { 669 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); 670 return 0; 671 } 672 673 if (ctx->encoder_insts == NULL) 674 return 1; 675 676 l = OSSL_ENCODER_CTX_get_num_encoders(ctx); 677 for (i = 0; i < l; i++) { 678 OSSL_ENCODER_INSTANCE *encoder_inst = 679 sk_OSSL_ENCODER_INSTANCE_value(ctx->encoder_insts, i); 680 OSSL_ENCODER *encoder = OSSL_ENCODER_INSTANCE_get_encoder(encoder_inst); 681 void *encoderctx = OSSL_ENCODER_INSTANCE_get_encoder_ctx(encoder_inst); 682 683 if (encoderctx == NULL || encoder->set_ctx_params == NULL) 684 continue; 685 if (!encoder->set_ctx_params(encoderctx, params)) 686 ok = 0; 687 } 688 return ok; 689 } 690 691 void OSSL_ENCODER_CTX_free(OSSL_ENCODER_CTX *ctx) 692 { 693 if (ctx != NULL) { 694 sk_OSSL_ENCODER_INSTANCE_pop_free(ctx->encoder_insts, 695 ossl_encoder_instance_free); 696 OPENSSL_free(ctx->construct_data); 697 ossl_pw_clear_passphrase_data(&ctx->pwdata); 698 OPENSSL_free(ctx); 699 } 700 } 701