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 */ 27static 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 43int 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 51void 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 */ 69static void encoder_store_free(void *vstore) 70{ 71 ossl_method_store_free(vstore); 72} 73 74static void *encoder_store_new(OSSL_LIB_CTX *ctx) 75{ 76 return ossl_method_store_new(ctx); 77} 78 79 80static 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() */ 88struct 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 */ 105static 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 114static 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 */ 121static 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 127static 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 138static 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 */ 150static 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 185static 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 */ 220static 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 */ 324static 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 */ 355static void destruct_encoder(void *method, void *data) 356{ 357 OSSL_ENCODER_free(method); 358} 359 360static int up_ref_encoder(void *method) 361{ 362 return OSSL_ENCODER_up_ref(method); 363} 364 365static void free_encoder(void *method) 366{ 367 OSSL_ENCODER_free(method); 368} 369 370/* Fetching support. Can fetch by numeric identity or by name */ 371static OSSL_ENCODER * 372inner_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 459OSSL_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 472OSSL_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 485int 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 494int 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 508const 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 518const 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 528const OSSL_PROPERTY_LIST * 529ossl_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 539int 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 549const char *OSSL_ENCODER_get0_name(const OSSL_ENCODER *encoder) 550{ 551 return encoder->base.name; 552} 553 554const char *OSSL_ENCODER_get0_description(const OSSL_ENCODER *encoder) 555{ 556 return encoder->base.algodef->algorithm_description; 557} 558 559int 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 570struct do_one_data_st { 571 void (*user_fn)(OSSL_ENCODER *encoder, void *arg); 572 void *user_arg; 573}; 574 575static 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 582void 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 602int 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 619const OSSL_PARAM * 620OSSL_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 630int 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 637const 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 651OSSL_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 661int 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 691void 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