From: Igor Ustinov Date: Tue, 11 Nov 2025 10:23:35 +0000 (+0100) Subject: Added finalized flag to the OSSL_ENCODER/DECODER_CTX structures X-Git-Tag: 4.0-PRE-CLANG-FORMAT-WEBKIT~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f480a73610708c10c044c17a36cdcc8b9233914d;p=thirdparty%2Fopenssl.git Added finalized flag to the OSSL_ENCODER/DECODER_CTX structures After this flag is set, the generic OSSL_ENCODER/DECODER_CTX_set_*() functions shouldn't be called anymore, so they return error in this case. Fixes #28249 Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/29120) --- diff --git a/CHANGES.md b/CHANGES.md index 73c1e9d3221..6ac08a2ca46 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -46,6 +46,12 @@ OpenSSL 4.0 *Ryan Hooper* + * Added `OSSL_[EN|DE]CODER_CTX_[set|get]_finalized()` functions. + `OSSL_[EN|DE]CODER_CTX_set_*()` and `OSSL_[EN|DE]CODER_CTX_add_*()` + functions return 0 if the context is already finalised. + + *Igor Ustinov* + OpenSSL 3.6 ----------- diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c index f0e29c1608e..54fc3519901 100644 --- a/crypto/encode_decode/decoder_lib.c +++ b/crypto/encode_decode/decoder_lib.c @@ -170,6 +170,11 @@ int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection) return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* * 0 is a valid selection, and means that the caller leaves * it to code to discover what the selection is. @@ -186,6 +191,11 @@ int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx, return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* * NULL is a valid starting input type, and means that the caller leaves * it to code to discover what the starting input type is. @@ -202,6 +212,11 @@ int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* * NULL is a valid starting input structure, and means that the caller * leaves it to code to discover what the starting input structure is. @@ -388,6 +403,11 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder) return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + prov = OSSL_DECODER_get0_provider(decoder); provctx = OSSL_PROVIDER_get0_provider_ctx(prov); @@ -582,6 +602,11 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + /* * If there is no stack of OSSL_DECODER_INSTANCE, we have nothing * more to add. That's fine. @@ -684,6 +709,12 @@ int OSSL_DECODER_CTX_set_construct(OSSL_DECODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->construct = construct; return 1; } @@ -695,6 +726,12 @@ int OSSL_DECODER_CTX_set_construct_data(OSSL_DECODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->construct_data = construct_data; return 1; } @@ -706,10 +743,35 @@ int OSSL_DECODER_CTX_set_cleanup(OSSL_DECODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->cleanup = cleanup; return 1; } +int OSSL_DECODER_CTX_set_finalized(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx->finalized = 1; + return 1; +} + +int OSSL_DECODER_CTX_get_finalized(OSSL_DECODER_CTX *ctx) +{ + if (ctx == NULL) + return 0; + + return ctx->finalized; +} + OSSL_DECODER_CONSTRUCT * OSSL_DECODER_CTX_get_construct(OSSL_DECODER_CTX *ctx) { diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c index 5f08536bff1..4e795a640e8 100644 --- a/crypto/encode_decode/decoder_pkey.c +++ b/crypto/encode_decode/decoder_pkey.c @@ -877,6 +877,7 @@ OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey, && OSSL_DECODER_CTX_set_selection(ctx, selection) && ossl_decoder_ctx_setup_for_pkey(ctx, keytype, libctx, propquery) && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery) + && OSSL_DECODER_CTX_set_finalized(ctx) && (propquery == NULL || OSSL_DECODER_CTX_set_params(ctx, decoder_params))) { OSSL_TRACE_BEGIN(DECODER) { diff --git a/crypto/encode_decode/encoder_lib.c b/crypto/encode_decode/encoder_lib.c index 59d0c885a3e..d22b1184d2a 100644 --- a/crypto/encode_decode/encoder_lib.c +++ b/crypto/encode_decode/encoder_lib.c @@ -174,6 +174,11 @@ int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection) return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (!ossl_assert(selection != 0)) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT); return 0; @@ -191,6 +196,11 @@ int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx, return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->output_type = output_type; return 1; } @@ -203,6 +213,11 @@ int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx, return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->output_structure = output_structure; return 1; } @@ -315,6 +330,11 @@ int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder) return 0; } + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + prov = OSSL_ENCODER_get0_provider(encoder); provctx = OSSL_PROVIDER_get0_provider_ctx(prov); @@ -339,6 +359,16 @@ int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder) int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx, OSSL_LIB_CTX *libctx, const char *propq) { + if (ctx == NULL) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return 1; } @@ -356,6 +386,12 @@ int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->construct = construct; return 1; } @@ -367,6 +403,12 @@ int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->construct_data = construct_data; return 1; } @@ -378,10 +420,35 @@ int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx, ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (ctx->finalized != 0) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + ctx->cleanup = cleanup; return 1; } +int OSSL_ENCODER_CTX_set_finalized(OSSL_ENCODER_CTX *ctx) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx->finalized = 1; + return 1; +} + +int OSSL_ENCODER_CTX_get_finalized(OSSL_ENCODER_CTX *ctx) +{ + if (ctx == NULL) + return 0; + + return ctx->finalized; +} + OSSL_ENCODER * OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst) { diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h index 11e52cfeec7..e43259e8649 100644 --- a/crypto/encode_decode/encoder_local.h +++ b/crypto/encode_decode/encoder_local.h @@ -101,6 +101,9 @@ struct ossl_encoder_ctx_st { /* For any function that needs a passphrase reader */ struct ossl_passphrase_data_st pwdata; + + /* Flag that the structure is ready for use */ + int finalized; }; struct ossl_decoder_instance_st { @@ -162,6 +165,9 @@ struct ossl_decoder_ctx_st { /* Signal that further processing should not continue. */ int harderr; + + /* Flag that the structure is ready for use */ + int finalized; }; const OSSL_PROPERTY_LIST * diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c index 414859d1e46..7fe7318a3e4 100644 --- a/crypto/encode_decode/encoder_pkey.c +++ b/crypto/encode_decode/encoder_pkey.c @@ -388,7 +388,8 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey, || OSSL_ENCODER_CTX_set_output_structure(ctx, output_struct)) && OSSL_ENCODER_CTX_set_selection(ctx, selection) && ossl_encoder_ctx_setup_for_pkey(ctx, pkey, selection, propquery) - && OSSL_ENCODER_CTX_add_extra(ctx, libctx, propquery)) { + && OSSL_ENCODER_CTX_add_extra(ctx, libctx, propquery) + && OSSL_ENCODER_CTX_set_finalized(ctx)) { OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; int save_parameters = pkey->save_parameters; diff --git a/doc/man3/OSSL_DECODER_CTX.pod b/doc/man3/OSSL_DECODER_CTX.pod index 33b09c836db..0ccbd62c11b 100644 --- a/doc/man3/OSSL_DECODER_CTX.pod +++ b/doc/man3/OSSL_DECODER_CTX.pod @@ -19,9 +19,11 @@ OSSL_DECODER_CLEANUP, OSSL_DECODER_CTX_set_construct, OSSL_DECODER_CTX_set_construct_data, OSSL_DECODER_CTX_set_cleanup, +OSSL_DECODER_CTX_set_finalized, OSSL_DECODER_CTX_get_construct, OSSL_DECODER_CTX_get_construct_data, OSSL_DECODER_CTX_get_cleanup, +OSSL_DECODER_CTX_get_finalized, OSSL_DECODER_export, OSSL_DECODER_INSTANCE_get_decoder, OSSL_DECODER_INSTANCE_get_decoder_ctx, @@ -77,6 +79,9 @@ OSSL_DECODER_INSTANCE_get_input_structure void *OSSL_DECODER_CTX_get_construct_data(OSSL_DECODER_CTX *ctx); OSSL_DECODER_CLEANUP *OSSL_DECODER_CTX_get_cleanup(OSSL_DECODER_CTX *ctx); + int OSSL_DECODER_CTX_set_finalized(OSSL_DECODER_CTX *ctx); + int OSSL_DECODER_CTX_get_finalized(OSSL_DECODER_CTX *ctx); + int OSSL_DECODER_export(OSSL_DECODER_INSTANCE *decoder_inst, void *reference, size_t reference_sz, OSSL_CALLBACK *export_cb, void *export_cbarg); @@ -135,6 +140,8 @@ OSSL_DECODER_CTX_add_extra() finds decoders that generate input for already added decoders, and adds them as well. This is used to build decoder chains. +OSSL_DECODER_CTX_set_selection() sets what the input is expected to contain. + OSSL_DECODER_CTX_set_input_type() sets the starting input type. This limits the decoder chains to be considered, as explained in the general description above. @@ -160,6 +167,15 @@ OSSL_DECODER_CTX_get_cleanup() return the values that have been set by OSSL_DECODER_CTX_set_construct(), OSSL_DECODER_CTX_set_construct_data() and OSSL_DECODER_CTX_set_cleanup() respectively. +OSSL_DECODER_CTX_set_finalized() finalises the context. Functions +OSSL_DECODER_CTX_set_selection(), OSSL_DECODER_CTX_set_output_type(), +OSSL_DECODER_CTX_set_output_structure(), OSSL_DECODER_CTX_add_encoder(), +OSSL_DECODER_CTX_add_extra(), OSSL_DECODER_CTX_set_construct(), +OSSL_DECODER_CTX_set_construct_data() and OSSL_DECODER_CTX_set_cleanup() +can't be used after the context is finalised. + +OSSL_DECODER_CTX_get_finalized() indicates if the context was finalised. + OSSL_DECODER_export() is a fallback function for constructors that cannot use the data they get directly for diverse reasons. It takes the same decode instance I that the constructor got and an object @@ -221,14 +237,20 @@ OSSL_DECODER_CTX_set_params() returns 1 if all recognised parameters were valid, or 0 if one of them was invalid or caused some other failure in the implementation. +OSSL_DECODER_CTX_set_selection(), OSSL_DECODER_CTX_set_input_type(), +OSSL_DECODER_CTX_set_input_structure(), OSSL_DECODER_CTX_add_decoder(), OSSL_DECODER_CTX_add_extra(), -OSSL_DECODER_CTX_set_construct(), OSSL_DECODER_CTX_set_construct_data() and -OSSL_DECODER_CTX_set_cleanup() return 1 on success, or 0 on failure. +OSSL_DECODER_CTX_set_construct(), OSSL_DECODER_CTX_set_construct_data(), +OSSL_DECODER_CTX_set_cleanup() and OSSL_DECODER_CTX_set_finalized() +return 1 on success, or 0 on failure. OSSL_DECODER_CTX_get_construct(), OSSL_DECODER_CTX_get_construct_data() and OSSL_DECODER_CTX_get_cleanup() return the current pointers to the constructor, the constructor data and the cleanup functions, respectively. +OSSL_DECODER_CTX_get_finalized() returns 1 if I was finalised, +0 otherwise. It also returns 0 if I is NULL. + OSSL_DECODER_CTX_num_decoders() returns the current number of decoders. It returns 0 if I is NULL. @@ -248,6 +270,9 @@ L, L, L The functions described here were added in OpenSSL 3.0. +OSSL_DECODER_CTX_set_finalized() and OSSL_DECODER_CTX_get_finalized() +were added in OpenSSL 4.0. + =head1 COPYRIGHT Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod b/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod index e55212ad554..2836d0e18a7 100644 --- a/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod +++ b/doc/man3/OSSL_DECODER_CTX_new_for_pkey.pod @@ -71,6 +71,10 @@ zero). This helps the caller to distinguish between an error when creating the B and missing encoder implementation, and allows it to act accordingly. +Note that OSSL_DECODER_CTX_new_for_pkey() finalises the OSSL_DECODER_CTX; +after that the B and B +functions described in L shouldn't be called. + OSSL_DECODER_CTX_set_passphrase() gives the implementation a pass phrase to use when decrypting the encoded private key. Alternatively, a pass phrase callback may be specified with the following functions. diff --git a/doc/man3/OSSL_ENCODER_CTX.pod b/doc/man3/OSSL_ENCODER_CTX.pod index e9248c356a0..6266f6ac3a0 100644 --- a/doc/man3/OSSL_ENCODER_CTX.pod +++ b/doc/man3/OSSL_ENCODER_CTX.pod @@ -22,7 +22,9 @@ OSSL_ENCODER_CONSTRUCT, OSSL_ENCODER_CLEANUP, OSSL_ENCODER_CTX_set_construct, OSSL_ENCODER_CTX_set_construct_data, -OSSL_ENCODER_CTX_set_cleanup +OSSL_ENCODER_CTX_set_cleanup, +OSSL_ENCODER_CTX_set_finalized, +OSSL_ENCODER_CTX_get_finalized - Encoder context routines =head1 SYNOPSIS @@ -69,6 +71,9 @@ OSSL_ENCODER_CTX_set_cleanup int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER_CLEANUP *cleanup); + int OSSL_ENCODER_CTX_set_finalized(OSSL_ENCODER_CTX *ctx); + int OSSL_ENCODER_CTX_get_finalized(OSSL_ENCODER_CTX *ctx); + =head1 DESCRIPTION Encoding an input object to the desired encoding may be done with a chain of @@ -111,6 +116,8 @@ OSSL_ENCODER_CTX_add_extra() finds encoders that further encodes output from already added encoders, and adds them as well. This is used to build encoder chains. +OSSL_ENCODER_CTX_set_selection() sets what should be included in the output. + OSSL_ENCODER_CTX_set_output_type() sets the ending output type. This must be specified, and determines if a complete encoder chain is available. @@ -130,6 +137,15 @@ passed to the constructor every time it's called. OSSL_ENCODER_CTX_set_cleanup() sets the constructor data I function. This is called by L. +OSSL_ENCODER_CTX_set_finalized() finalises the context. Functions +OSSL_ENCODER_CTX_set_selection(), +OSSL_ENCODER_CTX_set_output_type(), OSSL_ENCODER_CTX_set_output_structure(), +OSSL_ENCODER_CTX_add_encoder(), OSSL_ENCODER_CTX_add_extra(), +OSSL_ENCODER_CTX_set_construct(), OSSL_ENCODER_CTX_set_construct_data() and +OSSL_ENCODER_CTX_set_cleanup() can't be used after the context is finalised. + +OSSL_ENCODER_CTX_get_finalized() indicates if the context was finalised. + =head2 Constructor A B gets the following arguments: @@ -180,9 +196,15 @@ OSSL_ENCODER_CTX_set_params() returns 1 if all recognised parameters were valid, or 0 if one of them was invalid or caused some other failure in the implementation. +OSSL_ENCODER_CTX_set_selection(), +OSSL_ENCODER_CTX_set_output_type(), OSSL_ENCODER_CTX_set_output_structure(), OSSL_ENCODER_CTX_add_encoder(), OSSL_ENCODER_CTX_add_extra(), -OSSL_ENCODER_CTX_set_construct(), OSSL_ENCODER_CTX_set_construct_data() and -OSSL_ENCODER_CTX_set_cleanup() return 1 on success, or 0 on failure. +OSSL_ENCODER_CTX_set_construct(), OSSL_ENCODER_CTX_set_construct_data(), +OSSL_ENCODER_CTX_set_cleanup() and OSSL_ENCODER_CTX_set_finalized() +return 1 on success, or 0 on failure. + +OSSL_ENCODER_CTX_get_finalized() returns 1 if I was finalised, +0 otherwise. It also returns 0 if I is NULL. OSSL_ENCODER_CTX_get_num_encoders() returns the current number of encoders. It returns 0 if I is NULL. @@ -202,6 +224,12 @@ output type. OSSL_ENCODER_INSTANCE_get_output_structure() returns a string with the name of the output structure. +=head1 NOTES AND BUGS + +The chain mechanism in ENCODE is not yet completely implemented. +It affects functions such as OSSL_ENCODER_CTX_add_extra and the +inner processing loop. + =head1 SEE ALSO L, L @@ -210,6 +238,9 @@ L, L The functions described here were added in OpenSSL 3.0. +OSSL_ENCODER_CTX_set_finalized() and OSSL_ENCODER_CTX_get_finalized() +were added in OpenSSL 4.0. + =head1 COPYRIGHT Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod index 3bf9c10e374..5fb7a036813 100644 --- a/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod +++ b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod @@ -60,6 +60,10 @@ zero). This helps the caller to distinguish between an error when creating the B and missing encoder implementation, and allows it to act accordingly. +Note that OSSL_ENCODER_CTX_new_for_pkey() finalises the OSSL_ENCODER_CTX; +after that the B and B +functions described in L shouldn't be called. + OSSL_ENCODER_CTX_set_cipher() tells the implementation what cipher should be used to encrypt encoded keys. The cipher is given by name I. The interpretation of that I is diff --git a/include/openssl/decoder.h b/include/openssl/decoder.h index d4ee2cf4134..632a399d97b 100644 --- a/include/openssl/decoder.h +++ b/include/openssl/decoder.h @@ -63,6 +63,8 @@ int OSSL_DECODER_CTX_set_passphrase_cb(OSSL_DECODER_CTX *ctx, int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx, const UI_METHOD *ui_method, void *ui_data); +int OSSL_DECODER_CTX_set_finalized(OSSL_DECODER_CTX *ctx); +int OSSL_DECODER_CTX_get_finalized(OSSL_DECODER_CTX *ctx); /* * Utilities to read the object to decode, with the result sent to cb. diff --git a/include/openssl/encoder.h b/include/openssl/encoder.h index c37a6f16f23..5ffed5ceb2d 100644 --- a/include/openssl/encoder.h +++ b/include/openssl/encoder.h @@ -71,6 +71,8 @@ int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx, const char *output_type); int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx, const char *output_structure); +int OSSL_ENCODER_CTX_set_finalized(OSSL_ENCODER_CTX *ctx); +int OSSL_ENCODER_CTX_get_finalized(OSSL_ENCODER_CTX *ctx); /* Utilities to add encoders */ int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder); diff --git a/test/endecode_test.c b/test/endecode_test.c index 76b9348ec1a..37fc950e463 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -1370,6 +1370,56 @@ static int ec_encode_to_data_multi(void) } #endif /* OPENSSL_NO_EC */ +/* + * Test that OSSL_ENCODER_CTX setters return 0 after finalising the context + */ +static int encoder_ctx_setters(void) +{ + int ret; + OSSL_ENCODER_CTX *ectx = NULL; + + ret = TEST_ptr(ectx = OSSL_ENCODER_CTX_new()) + && TEST_int_eq(OSSL_ENCODER_CTX_get_finalized(ectx), 0) + && TEST_int_eq(OSSL_ENCODER_CTX_set_selection(ectx, + EVP_PKEY_KEYPAIR), 1) + && TEST_int_eq(OSSL_ENCODER_CTX_set_output_type(ectx, "DER"), 1) + && TEST_int_eq(OSSL_ENCODER_CTX_set_output_structure(ectx, "PKCS8"), 1) + && TEST_int_eq(OSSL_ENCODER_CTX_set_finalized(ectx), 1) + && TEST_int_eq(OSSL_ENCODER_CTX_set_selection(ectx, + EVP_PKEY_PUBLIC_KEY), 0) + && TEST_int_eq(OSSL_ENCODER_CTX_set_output_type(ectx, "PEM"), 0) + && TEST_int_eq(OSSL_ENCODER_CTX_set_output_structure(ectx, "PKCS8"), 0) + && TEST_int_eq(OSSL_ENCODER_CTX_add_extra(ectx, NULL, NULL), 0) + && TEST_int_eq(OSSL_ENCODER_CTX_get_finalized(ectx), 1); + OSSL_ENCODER_CTX_free(ectx); + return ret; +} + +/* + * Test that OSSL_DECODER_CTX setters return 0 after finalising the context + */ +static int decoder_ctx_setters(void) +{ + int ret; + OSSL_DECODER_CTX *dctx = NULL; + + ret = TEST_ptr(dctx = OSSL_DECODER_CTX_new()) + && TEST_int_eq(OSSL_DECODER_CTX_get_finalized(dctx), 0) + && TEST_int_eq(OSSL_DECODER_CTX_set_selection(dctx, + EVP_PKEY_KEYPAIR), 1) + && TEST_int_eq(OSSL_DECODER_CTX_set_input_type(dctx, "DER"), 1) + && TEST_int_eq(OSSL_DECODER_CTX_set_input_structure(dctx, "PKCS8"), 1) + && TEST_int_eq(OSSL_DECODER_CTX_set_finalized(dctx), 1) + && TEST_int_eq(OSSL_DECODER_CTX_set_selection(dctx, + EVP_PKEY_PUBLIC_KEY), 0) + && TEST_int_eq(OSSL_DECODER_CTX_set_input_type(dctx, "PEM"), 0) + && TEST_int_eq(OSSL_DECODER_CTX_set_input_structure(dctx, "PKCS8"), 0) + && TEST_int_eq(OSSL_DECODER_CTX_add_extra(dctx, NULL, NULL), 0) + && TEST_int_eq(OSSL_DECODER_CTX_get_finalized(dctx), 1); + OSSL_DECODER_CTX_free(dctx); + return ret; +} + typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, @@ -1668,6 +1718,9 @@ int setup_tests(void) ADD_TEST_SUITE(SLH_DSA_SHAKE_256f); } #endif /* OPENSSL_NO_SLH_DSA */ + + ADD_TEST(encoder_ctx_setters); + ADD_TEST(decoder_ctx_setters); } return 1; diff --git a/util/libcrypto.num b/util/libcrypto.num index 1cf60c7e848..9f351914e1d 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5946,3 +5946,7 @@ OSSL_PARAM_clear_free ? 4_0_0 EXIST::FUNCTION: CMS_dataFinal_ex ? 4_0_0 EXIST::FUNCTION:CMS CMS_SignerInfo_verify_ex ? 4_0_0 EXIST::FUNCTION:CMS EVP_SIGNATURE_has_message_update ? 4_0_0 EXIST::FUNCTION: +OSSL_DECODER_CTX_set_finalized ? 4_0_0 EXIST::FUNCTION: +OSSL_DECODER_CTX_get_finalized ? 4_0_0 EXIST::FUNCTION: +OSSL_ENCODER_CTX_set_finalized ? 4_0_0 EXIST::FUNCTION: +OSSL_ENCODER_CTX_get_finalized ? 4_0_0 EXIST::FUNCTION: