xref: /freebsd/crypto/openssl/crypto/encode_decode/encoder_lib.c (revision 44096ebd22ddd0081a357011714eff8963614b65)
1 /*
2  * Copyright 2019-2024 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_names.h>
11 #include <openssl/bio.h>
12 #include <openssl/encoder.h>
13 #include <openssl/buffer.h>
14 #include <openssl/params.h>
15 #include <openssl/provider.h>
16 #include <openssl/trace.h>
17 #include "internal/bio.h"
18 #include "internal/provider.h"
19 #include "encoder_local.h"
20 
21 struct encoder_process_data_st {
22     OSSL_ENCODER_CTX *ctx;
23 
24     /* Current BIO */
25     BIO *bio;
26 
27     /* Index of the current encoder instance to be processed */
28     int current_encoder_inst_index;
29 
30     /* Processing data passed down through recursion */
31     int level;                   /* Recursion level */
32     OSSL_ENCODER_INSTANCE *next_encoder_inst;
33     int count_output_structure;
34 
35     /* Processing data passed up through recursion */
36     OSSL_ENCODER_INSTANCE *prev_encoder_inst;
37     unsigned char *running_output;
38     size_t running_output_length;
39     /* Data type = the name of the first succeeding encoder implementation */
40     const char *data_type;
41 };
42 
43 static int encoder_process(struct encoder_process_data_st *data);
44 
45 int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out)
46 {
47     struct encoder_process_data_st data;
48 
49     memset(&data, 0, sizeof(data));
50     data.ctx = ctx;
51     data.bio = out;
52     data.current_encoder_inst_index = OSSL_ENCODER_CTX_get_num_encoders(ctx);
53 
54     if (data.current_encoder_inst_index == 0) {
55         ERR_raise_data(ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND,
56                        "No encoders were found. For standard encoders you need "
57                        "at least one of the default or base providers "
58                        "available. Did you forget to load them?");
59         return 0;
60     }
61 
62     if (ctx->cleanup == NULL || ctx->construct == NULL) {
63         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INIT_FAIL);
64         return 0;
65     }
66 
67     return encoder_process(&data) > 0;
68 }
69 
70 #ifndef OPENSSL_NO_STDIO
71 static BIO *bio_from_file(FILE *fp)
72 {
73     BIO *b;
74 
75     if ((b = BIO_new(BIO_s_file())) == NULL) {
76         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_BUF_LIB);
77         return NULL;
78     }
79     BIO_set_fp(b, fp, BIO_NOCLOSE);
80     return b;
81 }
82 
83 int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp)
84 {
85     BIO *b = bio_from_file(fp);
86     int ret = 0;
87 
88     if (b != NULL)
89         ret = OSSL_ENCODER_to_bio(ctx, b);
90 
91     BIO_free(b);
92     return ret;
93 }
94 #endif
95 
96 int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
97                          size_t *pdata_len)
98 {
99     BIO *out;
100     BUF_MEM *buf = NULL;
101     int ret = 0;
102 
103     if (pdata_len == NULL) {
104         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
105         return 0;
106     }
107 
108     out = BIO_new(BIO_s_mem());
109 
110     if (out != NULL
111         && OSSL_ENCODER_to_bio(ctx, out)
112         && BIO_get_mem_ptr(out, &buf) > 0) {
113         ret = 1; /* Hope for the best. A too small buffer will clear this */
114 
115         if (pdata != NULL && *pdata != NULL) {
116             if (*pdata_len < buf->length)
117                 /*
118                  * It's tempting to do |*pdata_len = (size_t)buf->length|
119                  * However, it's believed to be confusing more than helpful,
120                  * so we don't.
121                  */
122                 ret = 0;
123             else
124                 *pdata_len -= buf->length;
125         } else {
126             /* The buffer with the right size is already allocated for us */
127             *pdata_len = (size_t)buf->length;
128         }
129 
130         if (ret) {
131             if (pdata != NULL) {
132                 if (*pdata != NULL) {
133                     memcpy(*pdata, buf->data, buf->length);
134                     *pdata += buf->length;
135                 } else {
136                     /* In this case, we steal the data from BIO_s_mem() */
137                     *pdata = (unsigned char *)buf->data;
138                     buf->data = NULL;
139                 }
140             }
141         }
142     }
143     BIO_free(out);
144     return ret;
145 }
146 
147 int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection)
148 {
149     if (!ossl_assert(ctx != NULL)) {
150         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
151         return 0;
152     }
153 
154     if (!ossl_assert(selection != 0)) {
155         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
156         return 0;
157     }
158 
159     ctx->selection = selection;
160     return 1;
161 }
162 
163 int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
164                                      const char *output_type)
165 {
166     if (!ossl_assert(ctx != NULL) || !ossl_assert(output_type != NULL)) {
167         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
168         return 0;
169     }
170 
171     ctx->output_type = output_type;
172     return 1;
173 }
174 
175 int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx,
176                                           const char *output_structure)
177 {
178     if (!ossl_assert(ctx != NULL) || !ossl_assert(output_structure != NULL)) {
179         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
180         return 0;
181     }
182 
183     ctx->output_structure = output_structure;
184     return 1;
185 }
186 
187 static OSSL_ENCODER_INSTANCE *ossl_encoder_instance_new(OSSL_ENCODER *encoder,
188                                                         void *encoderctx)
189 {
190     OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
191     const OSSL_PROVIDER *prov;
192     OSSL_LIB_CTX *libctx;
193     const OSSL_PROPERTY_LIST *props;
194     const OSSL_PROPERTY_DEFINITION *prop;
195 
196     if (!ossl_assert(encoder != NULL)) {
197         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
198         return 0;
199     }
200 
201     if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) {
202         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
203         return 0;
204     }
205 
206     if (!OSSL_ENCODER_up_ref(encoder)) {
207         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
208         goto err;
209     }
210 
211     prov = OSSL_ENCODER_get0_provider(encoder);
212     libctx = ossl_provider_libctx(prov);
213     props = ossl_encoder_parsed_properties(encoder);
214     if (props == NULL) {
215         ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
216                        "there are no property definitions with encoder %s",
217                        OSSL_ENCODER_get0_name(encoder));
218         goto err;
219     }
220 
221     /* The "output" property is mandatory */
222     prop = ossl_property_find_property(props, libctx, "output");
223     encoder_inst->output_type = ossl_property_get_string_value(libctx, prop);
224     if (encoder_inst->output_type == NULL) {
225         ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
226                        "the mandatory 'output' property is missing "
227                        "for encoder %s (properties: %s)",
228                        OSSL_ENCODER_get0_name(encoder),
229                        OSSL_ENCODER_get0_properties(encoder));
230         goto err;
231     }
232 
233     /* The "structure" property is optional */
234     prop = ossl_property_find_property(props, libctx, "structure");
235     if (prop != NULL)
236         encoder_inst->output_structure
237             = ossl_property_get_string_value(libctx, prop);
238 
239     encoder_inst->encoder = encoder;
240     encoder_inst->encoderctx = encoderctx;
241     return encoder_inst;
242  err:
243     ossl_encoder_instance_free(encoder_inst);
244     return NULL;
245 }
246 
247 void ossl_encoder_instance_free(OSSL_ENCODER_INSTANCE *encoder_inst)
248 {
249     if (encoder_inst != NULL) {
250         if (encoder_inst->encoder != NULL)
251             encoder_inst->encoder->freectx(encoder_inst->encoderctx);
252         encoder_inst->encoderctx = NULL;
253         OSSL_ENCODER_free(encoder_inst->encoder);
254         encoder_inst->encoder = NULL;
255         OPENSSL_free(encoder_inst);
256     }
257 }
258 
259 static int ossl_encoder_ctx_add_encoder_inst(OSSL_ENCODER_CTX *ctx,
260                                              OSSL_ENCODER_INSTANCE *ei)
261 {
262     int ok;
263 
264     if (ctx->encoder_insts == NULL
265         && (ctx->encoder_insts =
266             sk_OSSL_ENCODER_INSTANCE_new_null()) == NULL) {
267         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
268         return 0;
269     }
270 
271     ok = (sk_OSSL_ENCODER_INSTANCE_push(ctx->encoder_insts, ei) > 0);
272     if (ok) {
273         OSSL_TRACE_BEGIN(ENCODER) {
274             BIO_printf(trc_out,
275                        "(ctx %p) Added encoder instance %p (encoder %p):\n"
276                        "    %s with %s\n",
277                        (void *)ctx, (void *)ei, (void *)ei->encoder,
278                        OSSL_ENCODER_get0_name(ei->encoder),
279                        OSSL_ENCODER_get0_properties(ei->encoder));
280         } OSSL_TRACE_END(ENCODER);
281     }
282     return ok;
283 }
284 
285 int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder)
286 {
287     OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
288     const OSSL_PROVIDER *prov = NULL;
289     void *encoderctx = NULL;
290     void *provctx = NULL;
291 
292     if (!ossl_assert(ctx != NULL) || !ossl_assert(encoder != NULL)) {
293         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
294         return 0;
295     }
296 
297     prov = OSSL_ENCODER_get0_provider(encoder);
298     provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
299 
300     if ((encoderctx = encoder->newctx(provctx)) == NULL
301         || (encoder_inst =
302             ossl_encoder_instance_new(encoder, encoderctx)) == NULL)
303         goto err;
304     /* Avoid double free of encoderctx on further errors */
305     encoderctx = NULL;
306 
307     if (!ossl_encoder_ctx_add_encoder_inst(ctx, encoder_inst))
308         goto err;
309 
310     return 1;
311  err:
312     ossl_encoder_instance_free(encoder_inst);
313     if (encoderctx != NULL)
314         encoder->freectx(encoderctx);
315     return 0;
316 }
317 
318 int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
319                                OSSL_LIB_CTX *libctx, const char *propq)
320 {
321     return 1;
322 }
323 
324 int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx)
325 {
326     if (ctx == NULL || ctx->encoder_insts == NULL)
327         return 0;
328     return sk_OSSL_ENCODER_INSTANCE_num(ctx->encoder_insts);
329 }
330 
331 int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
332                                    OSSL_ENCODER_CONSTRUCT *construct)
333 {
334     if (!ossl_assert(ctx != NULL)) {
335         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
336         return 0;
337     }
338     ctx->construct = construct;
339     return 1;
340 }
341 
342 int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
343                                         void *construct_data)
344 {
345     if (!ossl_assert(ctx != NULL)) {
346         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
347         return 0;
348     }
349     ctx->construct_data = construct_data;
350     return 1;
351 }
352 
353 int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
354                                  OSSL_ENCODER_CLEANUP *cleanup)
355 {
356     if (!ossl_assert(ctx != NULL)) {
357         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
358         return 0;
359     }
360     ctx->cleanup = cleanup;
361     return 1;
362 }
363 
364 OSSL_ENCODER *
365 OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst)
366 {
367     if (encoder_inst == NULL)
368         return NULL;
369     return encoder_inst->encoder;
370 }
371 
372 void *
373 OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst)
374 {
375     if (encoder_inst == NULL)
376         return NULL;
377     return encoder_inst->encoderctx;
378 }
379 
380 const char *
381 OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst)
382 {
383     if (encoder_inst == NULL)
384         return NULL;
385     return encoder_inst->output_type;
386 }
387 
388 const char *
389 OSSL_ENCODER_INSTANCE_get_output_structure(OSSL_ENCODER_INSTANCE *encoder_inst)
390 {
391     if (encoder_inst == NULL)
392         return NULL;
393     return encoder_inst->output_structure;
394 }
395 
396 static int encoder_process(struct encoder_process_data_st *data)
397 {
398     OSSL_ENCODER_INSTANCE *current_encoder_inst = NULL;
399     OSSL_ENCODER *current_encoder = NULL;
400     OSSL_ENCODER_CTX *current_encoder_ctx = NULL;
401     BIO *allocated_out = NULL;
402     const void *original_data = NULL;
403     OSSL_PARAM abstract[10];
404     const OSSL_PARAM *current_abstract = NULL;
405     int i;
406     int ok = -1;  /* -1 signifies that the lookup loop gave nothing */
407     int top = 0;
408 
409     if (data->next_encoder_inst == NULL) {
410         /* First iteration, where we prepare for what is to come */
411 
412         data->count_output_structure =
413             data->ctx->output_structure == NULL ? -1 : 0;
414         top = 1;
415     }
416 
417     for (i = data->current_encoder_inst_index; i-- > 0;) {
418         OSSL_ENCODER *next_encoder = NULL;
419         const char *current_output_type;
420         const char *current_output_structure;
421         struct encoder_process_data_st new_data;
422 
423         if (!top)
424             next_encoder =
425                 OSSL_ENCODER_INSTANCE_get_encoder(data->next_encoder_inst);
426 
427         current_encoder_inst =
428             sk_OSSL_ENCODER_INSTANCE_value(data->ctx->encoder_insts, i);
429         current_encoder =
430             OSSL_ENCODER_INSTANCE_get_encoder(current_encoder_inst);
431         current_encoder_ctx =
432             OSSL_ENCODER_INSTANCE_get_encoder_ctx(current_encoder_inst);
433         current_output_type =
434             OSSL_ENCODER_INSTANCE_get_output_type(current_encoder_inst);
435         current_output_structure =
436             OSSL_ENCODER_INSTANCE_get_output_structure(current_encoder_inst);
437         memset(&new_data, 0, sizeof(new_data));
438         new_data.ctx = data->ctx;
439         new_data.current_encoder_inst_index = i;
440         new_data.next_encoder_inst = current_encoder_inst;
441         new_data.count_output_structure = data->count_output_structure;
442         new_data.level = data->level + 1;
443 
444         OSSL_TRACE_BEGIN(ENCODER) {
445             BIO_printf(trc_out,
446                        "[%d] (ctx %p) Considering encoder instance %p (encoder %p)\n",
447                        data->level, (void *)data->ctx,
448                        (void *)current_encoder_inst, (void *)current_encoder);
449         } OSSL_TRACE_END(ENCODER);
450 
451         /*
452          * If this is the top call, we check if the output type of the current
453          * encoder matches the desired output type.
454          * If this isn't the top call, i.e. this is deeper in the recursion,
455          * we instead check if the output type of the current encoder matches
456          * the name of the next encoder (the one found by the parent call).
457          */
458         if (top) {
459             if (data->ctx->output_type != NULL
460                 && OPENSSL_strcasecmp(current_output_type,
461                                       data->ctx->output_type) != 0) {
462                 OSSL_TRACE_BEGIN(ENCODER) {
463                     BIO_printf(trc_out,
464                                "[%d]    Skipping because current encoder output type (%s) != desired output type (%s)\n",
465                                data->level,
466                                current_output_type, data->ctx->output_type);
467                 } OSSL_TRACE_END(ENCODER);
468                 continue;
469             }
470         } else {
471             if (!OSSL_ENCODER_is_a(next_encoder, current_output_type)) {
472                 OSSL_TRACE_BEGIN(ENCODER) {
473                     BIO_printf(trc_out,
474                                "[%d]    Skipping because current encoder output type (%s) != name of encoder %p\n",
475                                data->level,
476                                current_output_type, (void *)next_encoder);
477                 } OSSL_TRACE_END(ENCODER);
478                 continue;
479             }
480         }
481 
482         /*
483          * If the caller and the current encoder specify an output structure,
484          * Check if they match.  If they do, count the match, otherwise skip
485          * the current encoder.
486          */
487         if (data->ctx->output_structure != NULL
488             && current_output_structure != NULL) {
489             if (OPENSSL_strcasecmp(data->ctx->output_structure,
490                                    current_output_structure) != 0) {
491                 OSSL_TRACE_BEGIN(ENCODER) {
492                     BIO_printf(trc_out,
493                                "[%d]    Skipping because current encoder output structure (%s) != ctx output structure (%s)\n",
494                                data->level,
495                                current_output_structure,
496                                data->ctx->output_structure);
497                 } OSSL_TRACE_END(ENCODER);
498                 continue;
499             }
500 
501             data->count_output_structure++;
502         }
503 
504         /*
505          * Recurse to process the encoder implementations before the current
506          * one.
507          */
508         ok = encoder_process(&new_data);
509 
510         data->prev_encoder_inst = new_data.prev_encoder_inst;
511         data->running_output = new_data.running_output;
512         data->running_output_length = new_data.running_output_length;
513 
514         /*
515          * ok == -1     means that the recursion call above gave no further
516          *              encoders, and that the one we're currently at should
517          *              be tried.
518          * ok == 0      means that something failed in the recursion call
519          *              above, making the result unsuitable for a chain.
520          *              In this case, we simply continue to try finding a
521          *              suitable encoder at this recursion level.
522          * ok == 1      means that the recursion call was successful, and we
523          *              try to use the result at this recursion level.
524          */
525         if (ok != 0)
526             break;
527 
528         OSSL_TRACE_BEGIN(ENCODER) {
529             BIO_printf(trc_out,
530                        "[%d]    Skipping because recusion level %d failed\n",
531                        data->level, new_data.level);
532         } OSSL_TRACE_END(ENCODER);
533     }
534 
535     /*
536      * If |i < 0|, we didn't find any useful encoder in this recursion, so
537      * we do the rest of the process only if |i >= 0|.
538      */
539     if (i < 0) {
540         ok = -1;
541 
542         OSSL_TRACE_BEGIN(ENCODER) {
543             BIO_printf(trc_out,
544                        "[%d] (ctx %p) No suitable encoder found\n",
545                        data->level, (void *)data->ctx);
546         } OSSL_TRACE_END(ENCODER);
547     } else {
548         /* Preparations */
549 
550         switch (ok) {
551         case 0:
552             break;
553         case -1:
554             /*
555              * We have reached the beginning of the encoder instance sequence,
556              * so we prepare the object to be encoded.
557              */
558 
559             /*
560              * |data->count_output_structure| is one of these values:
561              *
562              * -1       There is no desired output structure
563              *  0       There is a desired output structure, and it wasn't
564              *          matched by any of the encoder instances that were
565              *          considered
566              * >0       There is a desired output structure, and at least one
567              *          of the encoder instances matched it
568              */
569             if (data->count_output_structure == 0)
570                 return 0;
571 
572             original_data =
573                 data->ctx->construct(current_encoder_inst,
574                                      data->ctx->construct_data);
575 
576             /* Also set the data type, using the encoder implementation name */
577             data->data_type = OSSL_ENCODER_get0_name(current_encoder);
578 
579             /* Assume that the constructor recorded an error */
580             if (original_data != NULL)
581                 ok = 1;
582             else
583                 ok = 0;
584             break;
585         case 1:
586             if (!ossl_assert(data->running_output != NULL)) {
587                 ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
588                 ok = 0;
589                 break;
590             }
591 
592             {
593                 /*
594                  * Create an object abstraction from the latest output, which
595                  * was stolen from the previous round.
596                  */
597 
598                 OSSL_PARAM *abstract_p = abstract;
599                 const char *prev_output_structure =
600                     OSSL_ENCODER_INSTANCE_get_output_structure(data->prev_encoder_inst);
601 
602                 *abstract_p++ =
603                     OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
604                                                      (char *)data->data_type, 0);
605                 if (prev_output_structure != NULL)
606                     *abstract_p++ =
607                         OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
608                                                          (char *)prev_output_structure,
609                                                          0);
610                 *abstract_p++ =
611                     OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
612                                                       data->running_output,
613                                                       data->running_output_length);
614                 *abstract_p = OSSL_PARAM_construct_end();
615                 current_abstract = abstract;
616             }
617             break;
618         }
619 
620         /* Calling the encoder implementation */
621 
622         if (ok) {
623             OSSL_CORE_BIO *cbio = NULL;
624             BIO *current_out = NULL;
625 
626             /*
627              * If we're at the last encoder instance to use, we're setting up
628              * final output.  Otherwise, set up an intermediary memory output.
629              */
630             if (top)
631                 current_out = data->bio;
632             else if ((current_out = allocated_out = BIO_new(BIO_s_mem()))
633                      == NULL)
634                 ok = 0;     /* Assume BIO_new() recorded an error */
635 
636             if (ok)
637                 ok = (cbio = ossl_core_bio_new_from_bio(current_out)) != NULL;
638             if (ok) {
639                 ok = current_encoder->encode(current_encoder_ctx, cbio,
640                                              original_data, current_abstract,
641                                              data->ctx->selection,
642                                              ossl_pw_passphrase_callback_enc,
643                                              &data->ctx->pwdata);
644                 OSSL_TRACE_BEGIN(ENCODER) {
645                     BIO_printf(trc_out,
646                                "[%d] (ctx %p) Running encoder instance %p => %d\n",
647                                data->level, (void *)data->ctx,
648                                (void *)current_encoder_inst, ok);
649                 } OSSL_TRACE_END(ENCODER);
650             }
651 
652             ossl_core_bio_free(cbio);
653             data->prev_encoder_inst = current_encoder_inst;
654         }
655     }
656 
657     /* Cleanup and collecting the result */
658 
659     OPENSSL_free(data->running_output);
660     data->running_output = NULL;
661 
662     /*
663      * Steal the output from the BIO_s_mem, if we did allocate one.
664      * That'll be the data for an object abstraction in the next round.
665      */
666     if (allocated_out != NULL) {
667         BUF_MEM *buf;
668 
669         BIO_get_mem_ptr(allocated_out, &buf);
670         data->running_output = (unsigned char *)buf->data;
671         data->running_output_length = buf->length;
672         memset(buf, 0, sizeof(*buf));
673     }
674 
675     BIO_free(allocated_out);
676     if (original_data != NULL)
677         data->ctx->cleanup(data->ctx->construct_data);
678     return ok;
679 }
680