Add OSSL_FN_CTX integration with BN_CTX
Add an OSSL_FN_CTX * pointer to struct bignum_ctx, allowing a BN_CTX to cache an OSSL_FN_CTX for use by BIGNUM wrapper functions. The pointer is freed automatically when BN_CTX_free() is called. Also add bn_ctx_acquire_ossl_fn_ctx() and bn_ctx_release_ossl_fn_ctx(): - acquire creates (or reuses if large enough) an OSSL_FN_CTX inside the BN_CTX, sizing it according to the caller's needs. - release checks that no frames remain in the cached OSSL_FN_CTX. The acquire function respects BN_FLG_SECURE: if the BN_CTX was created with BN_CTX_secure_new(), the OSSL_FN_CTX is also allocated in secure memory. Assisted-by: Pi:moonshotai/kimi-k2.6 Signed-off-by: Richard Levitte <levitte@openssl.foundation> Reviewed-by: Igor Ustinov <igus@openssl.foundation> Reviewed-by: Tomas Mraz <tomas@openssl.foundation> MergeDate: Sun Jun 14 08:40:44 2026 (Merged from https://github.com/openssl/openssl/pull/31431)
This commit is contained in:
parent
485e79dc66
commit
e3213b0c03
3 changed files with 143 additions and 0 deletions
|
|
@ -75,6 +75,8 @@ struct bignum_ctx {
|
|||
int flags;
|
||||
/* The library context */
|
||||
OSSL_LIB_CTX *libctx;
|
||||
/* OSSL_FN_CTX for OSSL_FN wrapper functions */
|
||||
OSSL_FN_CTX *fn_ctx;
|
||||
};
|
||||
|
||||
#ifndef FIPS_MODULE
|
||||
|
|
@ -179,6 +181,7 @@ void BN_CTX_free(BN_CTX *ctx)
|
|||
#endif
|
||||
BN_STACK_finish(&ctx->stack);
|
||||
BN_POOL_finish(&ctx->pool);
|
||||
OSSL_FN_CTX_free(ctx->fn_ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
|
|
@ -240,6 +243,49 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx)
|
|||
return ret;
|
||||
}
|
||||
|
||||
OSSL_FN_CTX *bn_ctx_acquire_ossl_fn_ctx(BN_CTX *ctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs)
|
||||
{
|
||||
size_t needed;
|
||||
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
needed = ossl_fn_ctx_calculate_arena_size(max_n_frames, max_n_numbers,
|
||||
max_n_limbs);
|
||||
|
||||
if (ctx->fn_ctx != NULL) {
|
||||
if (ctx->fn_ctx->msize >= needed) {
|
||||
/*
|
||||
* Existing context is large enough. Ensure no frames are
|
||||
* outstanding (callers are expected to have ended them).
|
||||
*/
|
||||
assert(ctx->fn_ctx->last_frame == NULL);
|
||||
return ctx->fn_ctx;
|
||||
}
|
||||
/* Too small, free and recreate */
|
||||
OSSL_FN_CTX_free(ctx->fn_ctx);
|
||||
ctx->fn_ctx = NULL;
|
||||
}
|
||||
|
||||
if (ctx->flags & BN_FLG_SECURE)
|
||||
ctx->fn_ctx = OSSL_FN_CTX_secure_new(ctx->libctx, max_n_frames,
|
||||
max_n_numbers, max_n_limbs);
|
||||
else
|
||||
ctx->fn_ctx = OSSL_FN_CTX_new(ctx->libctx, max_n_frames,
|
||||
max_n_numbers, max_n_limbs);
|
||||
|
||||
return ctx->fn_ctx;
|
||||
}
|
||||
|
||||
void bn_ctx_release_ossl_fn_ctx(BN_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL || ctx->fn_ctx == NULL)
|
||||
return;
|
||||
|
||||
assert(ctx->fn_ctx->last_frame == NULL);
|
||||
}
|
||||
|
||||
OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
|
|
|
|||
|
|
@ -126,6 +126,15 @@ int ossl_bn_rsa_fips186_5_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
|||
|
||||
OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx);
|
||||
|
||||
/*
|
||||
* bn_ctx_acquire_ossl_fn_ctx() and bn_ctx_release_ossl_fn_ctx() work
|
||||
* in tandem. They manage an OSSL_FN_CTX that is cached inside a BN_CTX
|
||||
* for use by BIGNUM wrapper functions that delegate to OSSL_FN.
|
||||
*/
|
||||
OSSL_FN_CTX *bn_ctx_acquire_ossl_fn_ctx(BN_CTX *ctx, size_t max_n_frames,
|
||||
size_t max_n_numbers, size_t max_n_limbs);
|
||||
void bn_ctx_release_ossl_fn_ctx(BN_CTX *ctx);
|
||||
|
||||
extern const BIGNUM ossl_bn_inv_sqrt_2;
|
||||
|
||||
#if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) && defined(__s390x__) \
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "testutil.h"
|
||||
#include "bn_prime.h"
|
||||
#include "crypto/bn.h"
|
||||
#include "crypto/fn.h"
|
||||
#include "crypto/fn_intern.h"
|
||||
|
||||
static BN_CTX *ctx;
|
||||
|
||||
|
|
@ -86,6 +88,91 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int test_bn_ctx_fn_ctx(void)
|
||||
{
|
||||
int ret = 1;
|
||||
BN_CTX *bnctx = NULL;
|
||||
OSSL_FN_CTX *fnctx = NULL;
|
||||
OSSL_FN *fn = NULL;
|
||||
const void *token = NULL;
|
||||
|
||||
/* Test non-secure BN_CTX */
|
||||
if (!TEST_ptr(bnctx = BN_CTX_new()))
|
||||
return 0;
|
||||
|
||||
/* Acquire should create a new OSSL_FN_CTX */
|
||||
if (!TEST_ptr(fnctx = bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 32)))
|
||||
ret = 0;
|
||||
|
||||
/* The returned pointer should be cached inside BN_CTX */
|
||||
if (ret && !TEST_ptr_eq(fnctx, bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 32)))
|
||||
ret = 0;
|
||||
|
||||
/* Re-acquire with same size should return the same cached context */
|
||||
if (ret && !TEST_ptr_eq(fnctx, bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 32)))
|
||||
ret = 0;
|
||||
|
||||
/* Use the OSSL_FN_CTX */
|
||||
if (ret) {
|
||||
if (!TEST_ptr(token = OSSL_FN_CTX_start(fnctx))
|
||||
|| !TEST_ptr(fn = OSSL_FN_CTX_get_limbs(fnctx, 4))
|
||||
|| !TEST_true(OSSL_FN_CTX_end(fnctx, token)))
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release does NOT free the cached OSSL_FN_CTX; it just asserts
|
||||
* no frames are outstanding. Re-acquire should return the same
|
||||
* cached pointer.
|
||||
*/
|
||||
bn_ctx_release_ossl_fn_ctx(bnctx);
|
||||
if (ret && !TEST_ptr_eq(fnctx, bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 32)))
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Re-acquire with a larger size should replace the cached context
|
||||
* because the old one is too small. (Free + alloc may reuse the
|
||||
* same address, so only verify the new context satisfies the larger
|
||||
* request.)
|
||||
*/
|
||||
if (ret) {
|
||||
OSSL_FN_CTX *small = bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 8);
|
||||
if (!TEST_ptr(small))
|
||||
ret = 0;
|
||||
else {
|
||||
OSSL_FN_CTX *large = bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 64);
|
||||
|
||||
if (!TEST_ptr(large)
|
||||
|| !TEST_ptr(token = OSSL_FN_CTX_start(large))
|
||||
|| !TEST_ptr(fn = OSSL_FN_CTX_get_limbs(large, 64))
|
||||
|| !TEST_true(OSSL_FN_CTX_end(large, token)))
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
/* Test secure BN_CTX */
|
||||
if (ret) {
|
||||
if (!TEST_ptr(bnctx = BN_CTX_secure_new()))
|
||||
ret = 0;
|
||||
else {
|
||||
fn = NULL;
|
||||
token = NULL;
|
||||
fnctx = bn_ctx_acquire_ossl_fn_ctx(bnctx, 1, 1, 8);
|
||||
if (!TEST_ptr(fnctx)
|
||||
|| !TEST_ptr(token = OSSL_FN_CTX_start(fnctx))
|
||||
|| !TEST_ptr(fn = OSSL_FN_CTX_get_limbs(fnctx, 1))
|
||||
|| !TEST_true(ossl_fn_is_securely_allocated(fn))
|
||||
|| !TEST_true(OSSL_FN_CTX_end(fnctx, token)))
|
||||
ret = 0;
|
||||
BN_CTX_free(bnctx);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(ctx = BN_CTX_new()))
|
||||
|
|
@ -94,6 +181,7 @@ int setup_tests(void)
|
|||
ADD_TEST(test_is_prime_enhanced);
|
||||
ADD_ALL_TESTS(test_is_composite_enhanced, (int)OSSL_NELEM(composites));
|
||||
ADD_TEST(test_bn_small_factors);
|
||||
ADD_TEST(test_bn_ctx_fn_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue