contexts: Forbid cloning/destroying secp256k1_context_static
This commit is contained in:
parent
b1579cf5fb
commit
4b6df5e33e
@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
- Forbade cloning or destroying `secp256k1_context_static`. Create a new context instead of cloning the static context. (If this change breaks your code, your code is probably wrong.)
|
||||||
|
|
||||||
## [0.2.0] - 2022-12-12
|
## [0.2.0] - 2022-12-12
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
@ -291,8 +291,11 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
|
|||||||
* called at most once for every call of this function. If you need to avoid dynamic
|
* called at most once for every call of this function. If you need to avoid dynamic
|
||||||
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
|
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
|
||||||
*
|
*
|
||||||
|
* Cloning secp256k1_context_static is not possible, and should not be emulated by
|
||||||
|
* the caller (e.g., using memcpy). Create a new context instead.
|
||||||
|
*
|
||||||
* Returns: a newly created context object.
|
* Returns: a newly created context object.
|
||||||
* Args: ctx: an existing context to copy
|
* Args: ctx: an existing context to copy (not secp256k1_context_static)
|
||||||
*/
|
*/
|
||||||
SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
||||||
const secp256k1_context* ctx
|
const secp256k1_context* ctx
|
||||||
@ -310,6 +313,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
|||||||
*
|
*
|
||||||
* Args: ctx: an existing context to destroy, constructed using
|
* Args: ctx: an existing context to destroy, constructed using
|
||||||
* secp256k1_context_create or secp256k1_context_clone
|
* secp256k1_context_create or secp256k1_context_clone
|
||||||
|
* (i.e., not secp256k1_context_static).
|
||||||
*/
|
*/
|
||||||
SECP256K1_API void secp256k1_context_destroy(
|
SECP256K1_API void secp256k1_context_destroy(
|
||||||
secp256k1_context* ctx
|
secp256k1_context* ctx
|
||||||
|
@ -88,8 +88,11 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
|
|||||||
* the lifetime of this context object, see the description of
|
* the lifetime of this context object, see the description of
|
||||||
* secp256k1_context_preallocated_create for details.
|
* secp256k1_context_preallocated_create for details.
|
||||||
*
|
*
|
||||||
|
* Cloning secp256k1_context_static is not possible, and should not be emulated by
|
||||||
|
* the caller (e.g., using memcpy). Create a new context instead.
|
||||||
|
*
|
||||||
* Returns: a newly created context object.
|
* Returns: a newly created context object.
|
||||||
* Args: ctx: an existing context to copy.
|
* Args: ctx: an existing context to copy (not secp256k1_context_static).
|
||||||
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
||||||
* size at least secp256k1_context_preallocated_size(flags)
|
* size at least secp256k1_context_preallocated_size(flags)
|
||||||
* bytes, as detailed above.
|
* bytes, as detailed above.
|
||||||
@ -117,7 +120,8 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
|
|||||||
*
|
*
|
||||||
* Args: ctx: an existing context to destroy, constructed using
|
* Args: ctx: an existing context to destroy, constructed using
|
||||||
* secp256k1_context_preallocated_create or
|
* secp256k1_context_preallocated_create or
|
||||||
* secp256k1_context_preallocated_clone.
|
* secp256k1_context_preallocated_clone
|
||||||
|
* (i.e., not secp256k1_context_static).
|
||||||
*/
|
*/
|
||||||
SECP256K1_API void secp256k1_context_preallocated_destroy(
|
SECP256K1_API void secp256k1_context_preallocated_destroy(
|
||||||
secp256k1_context* ctx
|
secp256k1_context* ctx
|
||||||
|
@ -109,9 +109,9 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
||||||
size_t ret = sizeof(secp256k1_context);
|
|
||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
return ret;
|
ARG_CHECK(secp256k1_context_is_proper(ctx));
|
||||||
|
return sizeof(secp256k1_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
||||||
@ -152,6 +152,7 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context*
|
|||||||
secp256k1_context* ret;
|
secp256k1_context* ret;
|
||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
ARG_CHECK(prealloc != NULL);
|
ARG_CHECK(prealloc != NULL);
|
||||||
|
ARG_CHECK(secp256k1_context_is_proper(ctx));
|
||||||
|
|
||||||
ret = (secp256k1_context*)prealloc;
|
ret = (secp256k1_context*)prealloc;
|
||||||
*ret = *ctx;
|
*ret = *ctx;
|
||||||
@ -163,6 +164,8 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
|||||||
size_t prealloc_size;
|
size_t prealloc_size;
|
||||||
|
|
||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(secp256k1_context_is_proper(ctx));
|
||||||
|
|
||||||
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
||||||
ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
|
ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
|
||||||
ret = secp256k1_context_preallocated_clone(ctx, ret);
|
ret = secp256k1_context_preallocated_clone(ctx, ret);
|
||||||
@ -170,18 +173,27 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
|
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
|
||||||
ARG_CHECK_VOID(ctx != secp256k1_context_static);
|
ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
|
||||||
if (ctx != NULL) {
|
|
||||||
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
/* Defined as noop */
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_context_destroy(secp256k1_context* ctx) {
|
void secp256k1_context_destroy(secp256k1_context* ctx) {
|
||||||
if (ctx != NULL) {
|
ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
|
||||||
|
|
||||||
|
/* Defined as noop */
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
secp256k1_context_preallocated_destroy(ctx);
|
secp256k1_context_preallocated_destroy(ctx);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
||||||
/* We compare pointers instead of checking secp256k1_context_is_proper() here
|
/* We compare pointers instead of checking secp256k1_context_is_proper() here
|
||||||
|
57
src/tests.c
57
src/tests.c
@ -32,6 +32,18 @@ static int COUNT = 64;
|
|||||||
static secp256k1_context *CTX = NULL;
|
static secp256k1_context *CTX = NULL;
|
||||||
static secp256k1_context *STATIC_CTX = NULL;
|
static secp256k1_context *STATIC_CTX = NULL;
|
||||||
|
|
||||||
|
static int all_bytes_equal(const void* s, unsigned char value, size_t n) {
|
||||||
|
const unsigned char *p = s;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (p[i] != value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void counting_illegal_callback_fn(const char* str, void* data) {
|
static void counting_illegal_callback_fn(const char* str, void* data) {
|
||||||
/* Dummy callback function that just counts. */
|
/* Dummy callback function that just counts. */
|
||||||
int32_t *p;
|
int32_t *p;
|
||||||
@ -229,20 +241,47 @@ static void run_ec_illegal_argument_tests(void) {
|
|||||||
secp256k1_context_set_illegal_callback(CTX, NULL, NULL);
|
secp256k1_context_set_illegal_callback(CTX, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_static_context_tests(void) {
|
static void run_static_context_tests(int use_prealloc) {
|
||||||
int32_t dummy = 0;
|
|
||||||
|
|
||||||
/* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
|
/* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
|
||||||
CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
|
CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
|
||||||
|
|
||||||
/* check if sizes for cloning are consistent */
|
{
|
||||||
CHECK(secp256k1_context_preallocated_clone_size(STATIC_CTX) >= sizeof(secp256k1_context));
|
int ecount = 0;
|
||||||
|
secp256k1_context_set_illegal_callback(STATIC_CTX, counting_illegal_callback_fn, &ecount);
|
||||||
|
/* Destroying or cloning secp256k1_context_static is not supported. */
|
||||||
|
if (use_prealloc) {
|
||||||
|
CHECK(secp256k1_context_preallocated_clone_size(STATIC_CTX) == 0);
|
||||||
|
CHECK(ecount == 1);
|
||||||
|
{
|
||||||
|
secp256k1_context *my_static_ctx = malloc(sizeof(*STATIC_CTX));
|
||||||
|
CHECK(my_static_ctx != NULL);
|
||||||
|
memset(my_static_ctx, 0x2a, sizeof(*my_static_ctx));
|
||||||
|
CHECK(secp256k1_context_preallocated_clone(STATIC_CTX, my_static_ctx) == NULL);
|
||||||
|
CHECK(all_bytes_equal(my_static_ctx, 0x2a, sizeof(*my_static_ctx)));
|
||||||
|
CHECK(ecount == 2);
|
||||||
|
free(my_static_ctx);
|
||||||
|
}
|
||||||
|
secp256k1_context_preallocated_destroy(STATIC_CTX);
|
||||||
|
CHECK(ecount == 3);
|
||||||
|
} else {
|
||||||
|
CHECK(secp256k1_context_clone(STATIC_CTX) == NULL);
|
||||||
|
CHECK(ecount == 1);
|
||||||
|
secp256k1_context_destroy(STATIC_CTX);
|
||||||
|
CHECK(ecount == 2);
|
||||||
|
}
|
||||||
|
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
/* Verify that setting and resetting illegal callback works */
|
/* Verify that setting and resetting illegal callback works */
|
||||||
|
int32_t dummy = 0;
|
||||||
secp256k1_context_set_illegal_callback(STATIC_CTX, counting_illegal_callback_fn, &dummy);
|
secp256k1_context_set_illegal_callback(STATIC_CTX, counting_illegal_callback_fn, &dummy);
|
||||||
CHECK(STATIC_CTX->illegal_callback.fn == counting_illegal_callback_fn);
|
CHECK(STATIC_CTX->illegal_callback.fn == counting_illegal_callback_fn);
|
||||||
|
CHECK(STATIC_CTX->illegal_callback.data == &dummy);
|
||||||
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
|
secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
|
||||||
CHECK(STATIC_CTX->illegal_callback.fn == secp256k1_default_illegal_callback_fn);
|
CHECK(STATIC_CTX->illegal_callback.fn == secp256k1_default_illegal_callback_fn);
|
||||||
|
CHECK(STATIC_CTX->illegal_callback.data == NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_proper_context_tests(int use_prealloc) {
|
static void run_proper_context_tests(int use_prealloc) {
|
||||||
@ -300,8 +339,10 @@ static void run_proper_context_tests(int use_prealloc) {
|
|||||||
/* Verify that setting and resetting illegal callback works */
|
/* Verify that setting and resetting illegal callback works */
|
||||||
secp256k1_context_set_illegal_callback(my_ctx, counting_illegal_callback_fn, &dummy);
|
secp256k1_context_set_illegal_callback(my_ctx, counting_illegal_callback_fn, &dummy);
|
||||||
CHECK(my_ctx->illegal_callback.fn == counting_illegal_callback_fn);
|
CHECK(my_ctx->illegal_callback.fn == counting_illegal_callback_fn);
|
||||||
|
CHECK(my_ctx->illegal_callback.data == &dummy);
|
||||||
secp256k1_context_set_illegal_callback(my_ctx, NULL, NULL);
|
secp256k1_context_set_illegal_callback(my_ctx, NULL, NULL);
|
||||||
CHECK(my_ctx->illegal_callback.fn == secp256k1_default_illegal_callback_fn);
|
CHECK(my_ctx->illegal_callback.fn == secp256k1_default_illegal_callback_fn);
|
||||||
|
CHECK(my_ctx->illegal_callback.data == NULL);
|
||||||
|
|
||||||
/*** attempt to use them ***/
|
/*** attempt to use them ***/
|
||||||
random_scalar_order_test(&msg);
|
random_scalar_order_test(&msg);
|
||||||
@ -327,6 +368,7 @@ static void run_proper_context_tests(int use_prealloc) {
|
|||||||
} else {
|
} else {
|
||||||
secp256k1_context_destroy(my_ctx);
|
secp256k1_context_destroy(my_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Defined as no-op. */
|
/* Defined as no-op. */
|
||||||
secp256k1_context_destroy(NULL);
|
secp256k1_context_destroy(NULL);
|
||||||
secp256k1_context_preallocated_destroy(NULL);
|
secp256k1_context_preallocated_destroy(NULL);
|
||||||
@ -7389,9 +7431,8 @@ int main(int argc, char **argv) {
|
|||||||
run_selftest_tests();
|
run_selftest_tests();
|
||||||
|
|
||||||
/* context tests */
|
/* context tests */
|
||||||
run_proper_context_tests(0);
|
run_proper_context_tests(0); run_proper_context_tests(1);
|
||||||
run_proper_context_tests(1);
|
run_static_context_tests(0); run_static_context_tests(1);
|
||||||
run_static_context_tests();
|
|
||||||
run_deprecated_context_flags_test();
|
run_deprecated_context_flags_test();
|
||||||
|
|
||||||
/* scratch tests */
|
/* scratch tests */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user