Add an ownership token for OSSL_FN_CTX frames

This prevents ending a frame that wasn't started by the caller.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Thu Apr 30 09:18:52 2026
(Merged from https://github.com/openssl/openssl/pull/30886)
This commit is contained in:
Igor Ustinov
2026-04-17 18:23:00 +02:00
committed by Tomas Mraz
parent 22c18b12a9
commit f811a2894a
5 changed files with 35 additions and 22 deletions
+8 -5
View File
@@ -112,16 +112,16 @@ void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx)
OPENSSL_free(ctx);
}
int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx)
const void *OSSL_FN_CTX_start(OSSL_FN_CTX *ctx)
{
if (!ossl_assert(ctx != NULL))
return 0;
return NULL;
struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame;
size_t used = (last_frame == NULL) ? 0 : last_frame->free_memory - ctx->memory;
if (ctx->msize - used < sizeof(struct ossl_fn_ctx_frame_st))
return 0;
return NULL;
if (ctx->last_frame == NULL)
ctx->last_frame = (struct ossl_fn_ctx_frame_st *)ctx->memory;
@@ -134,16 +134,19 @@ int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx)
frame->free_memory = frame->memory;
frame->msize = ctx->msize - used - sizeof(*frame);
return 1;
return ctx->last_frame;
}
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx)
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx, const void *token)
{
if (!ossl_assert(ctx != NULL) || !ossl_assert(ctx->last_frame != NULL))
return 0;
struct ossl_fn_ctx_frame_st *last_frame = ctx->last_frame;
if (last_frame != token)
return 0;
ctx->last_frame = last_frame->previous_frame;
return 1;
+4 -4
View File
@@ -16,13 +16,13 @@
int OSSL_FN_mul(OSSL_FN *r, const OSSL_FN *a, const OSSL_FN *b, OSSL_FN_CTX *ctx)
{
if (!OSSL_FN_CTX_start(ctx))
return 0;
size_t al = (size_t)a->dsize;
size_t bl = (size_t)b->dsize;
size_t rl = (size_t)r->dsize;
size_t max = (size_t)(al + bl);
const void *token = OSSL_FN_CTX_start(ctx);
if (token == NULL)
return 0;
int ret = 0;
#ifdef BN_MUL_COMBA
@@ -60,6 +60,6 @@ end:
ret = 1;
err:
OSSL_FN_CTX_end(ctx);
OSSL_FN_CTX_end(ctx, token);
return ret;
}
+3 -2
View File
@@ -16,7 +16,8 @@
int OSSL_FN_sqr(OSSL_FN *r, const OSSL_FN *a, OSSL_FN_CTX *ctx)
{
if (!OSSL_FN_CTX_start(ctx))
const void *token = OSSL_FN_CTX_start(ctx);
if (token == NULL)
return 0;
size_t al = (size_t)a->dsize;
@@ -70,6 +71,6 @@ end:
}
err:
OSSL_FN_CTX_end(ctx);
OSSL_FN_CTX_end(ctx, token);
return ret;
}
+10 -3
View File
@@ -184,9 +184,10 @@ void OSSL_FN_CTX_free(OSSL_FN_CTX *ctx);
* call this must also clean up with a OSSL_FN_CTX_end() call.
*
* @param[in] ctx The OSSL_FN_CTX to start the frame in.
* @returns 1 on success, 0 on error.
* @returns Ownership token of the started frame, NULL on error.
* This token must be passed to OSSL_FN_CTX_end().
*/
int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx);
const void *OSSL_FN_CTX_start(OSSL_FN_CTX *ctx);
/**
* End the last OSSL_FN_CTX frame, resetting back to the previous
@@ -194,9 +195,15 @@ int OSSL_FN_CTX_start(OSSL_FN_CTX *ctx);
* this function before returning.
*
* @param[in] ctx The OSSL_FN_CTX to start the frame in.
* @param[in] token Ownership token returned by OSSL_FN_CTX_start().
* @returns 1 on success, 0 on error.
*
* @note The token parameter is validated but not used for choosing a
* frame; only the most recent frame can be ended. Passing an incorrect
* token indicates a programming error and the function will fail.
* If NULL is passed, nothing will be done but the function will return 1.
*/
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx);
int OSSL_FN_CTX_end(OSSL_FN_CTX *ctx, const void *token);
/**
* Get a suitably sized OSSL_FN from an OSSL_FN_CTX.
+10 -8
View File
@@ -97,6 +97,7 @@ static int test_ctx(void)
int ret = 1;
OSSL_FN_CTX *ctx = NULL;
OSSL_FN *f = NULL;
const void *token = NULL;
/*
* Make a CTX that is likely to contain two 2048-bit or one 4096-bit OSSL_FN
@@ -111,7 +112,7 @@ static int test_ctx(void)
}
/* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
@@ -120,14 +121,14 @@ static int test_ctx(void)
|| !TEST_false(ossl_fn_is_dynamically_allocated(f))
|| !TEST_false(ossl_fn_is_securely_allocated(f)))
ret = 0;
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
}
/* Check that we can get 2 2048-bit OSSL_FN instances, but not 3 */
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
@@ -136,14 +137,14 @@ static int test_ctx(void)
|| !TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 2048))
|| !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048)))
ret = 0;
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
}
/* Check that we can get 1 4096-bit OSSL_FN instance, but not 2 */
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
@@ -151,7 +152,7 @@ static int test_ctx(void)
if (!TEST_ptr(f = OSSL_FN_CTX_get_bits(ctx, 4096))
|| !TEST_ptr_null(f = OSSL_FN_CTX_get_bits(ctx, 2048)))
ret = 0;
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
@@ -168,6 +169,7 @@ static int test_secure_ctx(void)
int ret = 1;
OSSL_FN_CTX *ctx = NULL;
OSSL_FN *f = NULL;
const void *token = NULL;
/*
* Make a CTX that is likely to contain two 2048-bit OSSL_FN and one frame
@@ -182,7 +184,7 @@ static int test_secure_ctx(void)
}
/* Check that we can get 1 2048-bit OSSL_FN instance, and check its metadata */
if (!TEST_true(OSSL_FN_CTX_start(ctx))) {
if (!TEST_ptr(token = OSSL_FN_CTX_start(ctx))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;
@@ -191,7 +193,7 @@ static int test_secure_ctx(void)
|| !TEST_false(ossl_fn_is_dynamically_allocated(f))
|| !TEST_true(ossl_fn_is_securely_allocated(f)))
ret = 0;
if (!TEST_true(OSSL_FN_CTX_end(ctx))) {
if (!TEST_true(OSSL_FN_CTX_end(ctx, token))) {
ret = 0;
/* It's pointless to try more tests after this failure */
goto end;