Repository: bitcoin-core/secp256k1
Pull request #1199 (2023-01-27 21:48:53)

ci: Minor improvements inspired by Bitcoin Core
This steals two recent CI improvements from bitcoin/bitcoin.  See individual commit messages.


Patch:
diff --git a/.cirrus.yml b/.cirrus.yml
index a4182e1..bed135c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,4 +1,6 @@
 env:
+  ### cirrus config
+  CIRRUS_CLONE_DEPTH: 1
   ### compiler options
   HOST:
   WRAPPER_CMD:
@@ -53,11 +55,11 @@ cat_logs_snippet: &CAT_LOGS
 
 merge_base_script_snippet: &MERGE_BASE
   merge_base_script:
-    - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
-    - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH
     - git config --global user.email "ci@ci.ci"
     - git config --global user.name "ci"
-    - git merge FETCH_HEAD  # Merge base to detect silent merge conflicts
+    - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
+    - git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
+    - git checkout FETCH_HEAD  # Use merged changes to detect silent merge conflicts
 
 linux_container_snippet: &LINUX_CONTAINER
   container:
@@ -81,7 +83,6 @@ task:
     - env: {WIDEMUL: int128,                 ECDH: yes, SCHNORRSIG: yes}
     - env: {WIDEMUL: int128,  ASM: x86_64}
     - env: {                  RECOVERY: yes,            SCHNORRSIG: yes}
-    - env: {CTIMETESTS: no,    RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, CPPFLAGS: -DVERIFY}
     - env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no}
     - env: {CPPFLAGS: -DDETERMINISTIC}
     - env: {CFLAGS: -O0, CTIMETESTS: no}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 62a89f8..3a13a39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [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.)
- - Forbade randomizing (copies of) `secp256k1_context_static`. Randomizing a copy of `secp256k1_context_static` did not have any effect and did not provide defense-in-depth protection against side-channel attacks. Create a new context if you want to benefit from randomization.
-
 ## [0.2.0] - 2022-12-12
 
 #### Added
diff --git a/Makefile.am b/Makefile.am
index 122e044..f02ddaf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -76,7 +76,7 @@ noinst_LTLIBRARIES = $(PRECOMPUTED_LIB)
 libsecp256k1_precomputed_la_SOURCES =  src/precomputed_ecmult.c src/precomputed_ecmult_gen.c
 # We need `-I$(top_srcdir)/src` in VPATH builds if libsecp256k1_precomputed_la_SOURCES have been recreated in the build tree.
 # This helps users and packagers who insist on recreating the precomputed files (e.g., Gentoo).
-libsecp256k1_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_CONFIG_DEFINES)
+libsecp256k1_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
 
 if USE_EXTERNAL_ASM
 COMMON_LIB = libsecp256k1_common.la
@@ -95,22 +95,22 @@ endif
 endif
 
 libsecp256k1_la_SOURCES = src/secp256k1.c
-libsecp256k1_la_CPPFLAGS = $(SECP_CONFIG_DEFINES)
-libsecp256k1_la_LIBADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
+libsecp256k1_la_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
+libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE)
 
 noinst_PROGRAMS =
 if USE_BENCHMARK
 noinst_PROGRAMS += bench bench_internal bench_ecmult
 bench_SOURCES = src/bench.c
-bench_LDADD = libsecp256k1.la $(COMMON_LIB)
+bench_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
 bench_CPPFLAGS = $(SECP_CONFIG_DEFINES)
 bench_internal_SOURCES = src/bench_internal.c
-bench_internal_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
-bench_internal_CPPFLAGS = $(SECP_CONFIG_DEFINES)
+bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
+bench_internal_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
 bench_ecmult_SOURCES = src/bench_ecmult.c
-bench_ecmult_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
-bench_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES)
+bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
+bench_ecmult_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
 endif
 
 TESTS =
@@ -118,8 +118,8 @@ if USE_TESTS
 TESTS += noverify_tests
 noinst_PROGRAMS += noverify_tests
 noverify_tests_SOURCES = src/tests.c
-noverify_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
-noverify_tests_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB)
+noverify_tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) $(SECP_CONFIG_DEFINES)
+noverify_tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 noverify_tests_LDFLAGS = -static
 if !ENABLE_COVERAGE
 TESTS += tests
@@ -134,19 +134,19 @@ endif
 if USE_CTIME_TESTS
 noinst_PROGRAMS += ctime_tests
 ctime_tests_SOURCES = src/ctime_tests.c
-ctime_tests_LDADD = libsecp256k1.la $(COMMON_LIB)
+ctime_tests_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
 ctime_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
 endif
 
 if USE_EXHAUSTIVE_TESTS
 noinst_PROGRAMS += exhaustive_tests
 exhaustive_tests_SOURCES = src/tests_exhaustive.c
-exhaustive_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES)
+exhaustive_tests_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
 if !ENABLE_COVERAGE
 exhaustive_tests_CPPFLAGS += -DVERIFY
 endif
 # Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables).
-exhaustive_tests_LDADD = $(COMMON_LIB)
+exhaustive_tests_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 exhaustive_tests_LDFLAGS = -static
 TESTS += exhaustive_tests
 endif
@@ -190,12 +190,12 @@ EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen
 CLEANFILES = $(EXTRA_PROGRAMS)
 
 precompute_ecmult_SOURCES = src/precompute_ecmult.c
-precompute_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES)
-precompute_ecmult_LDADD = $(COMMON_LIB)
+precompute_ecmult_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
+precompute_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 
 precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c
-precompute_ecmult_gen_CPPFLAGS = $(SECP_CONFIG_DEFINES)
-precompute_ecmult_gen_LDADD = $(COMMON_LIB)
+precompute_ecmult_gen_CPPFLAGS = $(SECP_INCLUDES) $(SECP_CONFIG_DEFINES)
+precompute_ecmult_gen_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 
 # See Automake manual, Section "Errors with distclean".
 # We don't list any dependencies for the prebuilt files here because
diff --git a/configure.ac b/configure.ac
index 9249ae0..cb5d039 100644
--- a/configure.ac
+++ b/configure.ac
@@ -406,6 +406,10 @@ fi
 ###
 
 AC_CONFIG_FILES([Makefile libsecp256k1.pc])
+AC_SUBST(SECP_INCLUDES)
+AC_SUBST(SECP_LIBS)
+AC_SUBST(SECP_TEST_LIBS)
+AC_SUBST(SECP_TEST_INCLUDES)
 AC_SUBST(SECP_CFLAGS)
 AC_SUBST(SECP_CONFIG_DEFINES)
 AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"])
diff --git a/include/secp256k1.h b/include/secp256k1.h
index 3a75b05..3d169ec 100644
--- a/include/secp256k1.h
+++ b/include/secp256k1.h
@@ -291,11 +291,8 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
  *  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.
  *
- *  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.
- *  Args:    ctx: an existing context to copy (not secp256k1_context_static)
+ *  Args:    ctx: an existing context to copy
  */
 SECP256K1_API secp256k1_context* secp256k1_context_clone(
     const secp256k1_context* ctx
@@ -313,7 +310,6 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
  *
  *  Args:   ctx: an existing context to destroy, constructed using
  *               secp256k1_context_create or secp256k1_context_clone
- *               (i.e., not secp256k1_context_static).
  */
 SECP256K1_API void secp256k1_context_destroy(
     secp256k1_context* ctx
@@ -824,10 +820,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
 
 /** Randomizes the context to provide enhanced protection against side-channel leakage.
  *
- *  Returns: 1: randomization successful
+ *  Returns: 1: randomization successful (or called on copy of secp256k1_context_static)
  *           0: error
- *  Args:    ctx:       pointer to a context object (not secp256k1_context_static).
- *  In:      seed32:    pointer to a 32-byte random seed (NULL resets to initial state).
+ *  Args:    ctx:       pointer to a context object.
+ *  In:      seed32:    pointer to a 32-byte random seed (NULL resets to initial state)
  *
  * While secp256k1 code is written and tested to be constant-time no matter what
  * secret values are, it is possible that a compiler may output code which is not,
@@ -842,17 +838,21 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
  * functions that perform computations involving secret keys, e.g., signing and
  * public key generation. It is possible to call this function more than once on
  * the same context, and doing so before every few computations involving secret
- * keys is recommended as a defense-in-depth measure. Randomization of the static
- * context secp256k1_context_static is not supported.
+ * keys is recommended as a defense-in-depth measure.
  *
  * Currently, the random seed is mainly used for blinding multiplications of a
  * secret scalar with the elliptic curve base point. Multiplications of this
  * kind are performed by exactly those API functions which are documented to
- * require a context that is not secp256k1_context_static. As a rule of thumb,
+ * require a context that is not the secp256k1_context_static. As a rule of thumb,
  * these are all functions which take a secret key (or a keypair) as an input.
  * A notable exception to that rule is the ECDH module, which relies on a different
  * kind of elliptic curve point multiplication and thus does not benefit from
  * enhanced protection against side-channel leakage currently.
+ *
+ * It is safe to call this function on a copy of secp256k1_context_static in writable
+ * memory (e.g., obtained via secp256k1_context_clone). In that case, this
+ * function is guaranteed to return 1, but the call will have no effect because
+ * the static context (or a copy thereof) is not meant to be randomized.
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
     secp256k1_context* ctx,
diff --git a/include/secp256k1_preallocated.h b/include/secp256k1_preallocated.h
index ffa96dd..ed846f7 100644
--- a/include/secp256k1_preallocated.h
+++ b/include/secp256k1_preallocated.h
@@ -88,11 +88,8 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
  *  the lifetime of this context object, see the description of
  *  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.
- *  Args:    ctx:      an existing context to copy (not secp256k1_context_static).
+ *  Args:    ctx:      an existing context to copy.
  *  In:      prealloc: a pointer to a rewritable contiguous block of memory of
  *                     size at least secp256k1_context_preallocated_size(flags)
  *                     bytes, as detailed above.
@@ -120,8 +117,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
  *
  *  Args:   ctx: an existing context to destroy, constructed using
  *               secp256k1_context_preallocated_create or
- *               secp256k1_context_preallocated_clone
- *               (i.e., not secp256k1_context_static).
+ *               secp256k1_context_preallocated_clone.
  */
 SECP256K1_API void secp256k1_context_preallocated_destroy(
     secp256k1_context* ctx
diff --git a/libsecp256k1.pc.in b/libsecp256k1.pc.in
index 0fb6f48..694e98e 100644
--- a/libsecp256k1.pc.in
+++ b/libsecp256k1.pc.in
@@ -9,4 +9,5 @@ URL: https://github.com/bitcoin-core/secp256k1
 Version: @PACKAGE_VERSION@
 Cflags: -I${includedir}
 Libs: -L${libdir} -lsecp256k1
+Libs.private: @SECP_LIBS@
 
diff --git a/src/bench_internal.c b/src/bench_internal.c
index e1ef14f..fd794a1 100644
--- a/src/bench_internal.c
+++ b/src/bench_internal.c
@@ -110,11 +110,10 @@ static void bench_scalar_mul(void* arg, int iters) {
 static void bench_scalar_split(void* arg, int iters) {
     int i, j = 0;
     bench_inv *data = (bench_inv*)arg;
-    secp256k1_scalar tmp;
 
     for (i = 0; i < iters; i++) {
-        secp256k1_scalar_split_lambda(&tmp, &data->scalar[1], &data->scalar[0]);
-        j += secp256k1_scalar_add(&data->scalar[0], &tmp, &data->scalar[1]);
+        secp256k1_scalar_split_lambda(&data->scalar[0], &data->scalar[1], &data->scalar[0]);
+        j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
     }
     CHECK(j <= iters);
 }
diff --git a/src/scalar.h b/src/scalar.h
index 63c0d64..b9cb6b0 100644
--- a/src/scalar.h
+++ b/src/scalar.h
@@ -88,10 +88,9 @@ static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar
 
 /** Find r1 and r2 such that r1+r2*2^128 = k. */
 static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
-/** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their
- *  negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). It is
- *  required that r1, r2, and k all point to different objects. */
-static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k);
+/** Find r1 and r2 such that r1+r2*lambda = k,
+ * where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */
+static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k);
 
 /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
 static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
diff --git a/src/scalar_impl.h b/src/scalar_impl.h
index bed7f95..9e72df2 100644
--- a/src/scalar_impl.h
+++ b/src/scalar_impl.h
@@ -52,10 +52,7 @@ static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned c
  * nontrivial to get full test coverage for the exhaustive tests. We therefore
  * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n).
  */
-static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) {
-    VERIFY_CHECK(r1 != k);
-    VERIFY_CHECK(r2 != k);
-    VERIFY_CHECK(r1 != r2);
+static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
     *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER;
     *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER;
 }
@@ -122,7 +119,7 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con
  *
  * See proof below.
  */
-static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) {
+static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) {
     secp256k1_scalar c1, c2;
     static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST(
         0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
@@ -142,7 +139,6 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT
     );
     VERIFY_CHECK(r1 != k);
     VERIFY_CHECK(r2 != k);
-    VERIFY_CHECK(r1 != r2);
     /* these _var calls are constant time since the shift amount is constant */
     secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384);
     secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384);
diff --git a/src/secp256k1.c b/src/secp256k1.c
index 7af333c..6c91a76 100644
--- a/src/secp256k1.c
+++ b/src/secp256k1.c
@@ -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 ret = sizeof(secp256k1_context);
     VERIFY_CHECK(ctx != NULL);
-    ARG_CHECK(secp256k1_context_is_proper(ctx));
-    return sizeof(secp256k1_context);
+    return ret;
 }
 
 secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
@@ -152,7 +152,6 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context*
     secp256k1_context* ret;
     VERIFY_CHECK(ctx != NULL);
     ARG_CHECK(prealloc != NULL);
-    ARG_CHECK(secp256k1_context_is_proper(ctx));
 
     ret = (secp256k1_context*)prealloc;
     *ret = *ctx;
@@ -164,8 +163,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
     size_t prealloc_size;
 
     VERIFY_CHECK(ctx != NULL);
-    ARG_CHECK(secp256k1_context_is_proper(ctx));
-
     prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
     ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
     ret = secp256k1_context_preallocated_clone(ctx, ret);
@@ -173,26 +170,17 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
 }
 
 void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
-    ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
-
-    /* Defined as noop */
-    if (ctx == NULL) {
-        return;
+    ARG_CHECK_VOID(ctx != secp256k1_context_static);
+    if (ctx != NULL) {
+        secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
     }
-
-    secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
 }
 
 void secp256k1_context_destroy(secp256k1_context* ctx) {
-    ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx));
-
-    /* Defined as noop */
-    if (ctx == NULL) {
-        return;
+    if (ctx != NULL) {
+        secp256k1_context_preallocated_destroy(ctx);
+        free(ctx);
     }
-
-    secp256k1_context_preallocated_destroy(ctx);
-    free(ctx);
 }
 
 void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
@@ -749,8 +737,6 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
 
 int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
     VERIFY_CHECK(ctx != NULL);
-    ARG_CHECK(secp256k1_context_is_proper(ctx));
-
     if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
         secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
     }


Test patch:
diff --git a/src/ctime_tests.c b/src/ctime_tests.c
index 713eb42..aaa6f7f 100644
--- a/src/ctime_tests.c
+++ b/src/ctime_tests.c
@@ -38,7 +38,7 @@ int main(void) {
     int ret, i;
 
     if (!SECP256K1_CHECKMEM_RUNNING()) {
-        fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n");
+        fprintf(stderr, "Unless compiled under msan, this test can only usefully be run inside valgrind.\n");
         fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n");
         return 1;
     }
diff --git a/src/tests.c b/src/tests.c
index bc5b7cb..9cc4d17 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -32,43 +32,11 @@ static int COUNT = 64;
 static secp256k1_context *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;
-}
-
-/* TODO Use CHECK_ILLEGAL(_VOID) everywhere and get rid of the uncounting callback */
-/* CHECK that expr_or_stmt calls the illegal callback of ctx exactly once
- *
- * For checking functions that use ARG_CHECK_VOID */
-#define CHECK_ILLEGAL_VOID(ctx, expr_or_stmt) do { \
-    int32_t _calls_to_illegal_callback = 0; \
-    secp256k1_callback _saved_illegal_cb = ctx->illegal_callback; \
-    secp256k1_context_set_illegal_callback(ctx, \
-        counting_illegal_callback_fn, &_calls_to_illegal_callback); \
-    { expr_or_stmt; } \
-    ctx->illegal_callback = _saved_illegal_cb; \
-    CHECK(_calls_to_illegal_callback == 1); \
-} while(0);
-
-/* CHECK that expr calls the illegal callback of ctx exactly once and that expr == 0
- *
- * For checking functions that use ARG_CHECK */
-#define CHECK_ILLEGAL(ctx, expr) CHECK_ILLEGAL_VOID(ctx, CHECK((expr) == 0))
-
 static void counting_illegal_callback_fn(const char* str, void* data) {
     /* Dummy callback function that just counts. */
     int32_t *p;
     (void)str;
     p = data;
-    CHECK(*p != INT32_MAX);
     (*p)++;
 }
 
@@ -77,7 +45,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
     int32_t *p;
     (void)str;
     p = data;
-    CHECK(*p != INT32_MIN);
     (*p)--;
 }
 
@@ -262,61 +229,31 @@ static void run_ec_illegal_argument_tests(void) {
     secp256k1_context_set_illegal_callback(CTX, NULL, NULL);
 }
 
-static void run_static_context_tests(int use_prealloc) {
+static void run_static_context_tests(void) {
+    int32_t dummy = 0;
+
     /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */
     CHECK(secp256k1_context_no_precomp == secp256k1_context_static);
 
-    {
-        unsigned char seed[32] = {0x17};
-
-        /* Randomizing secp256k1_context_static is not supported. */
-        CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_randomize(STATIC_CTX, seed));
-        CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_randomize(STATIC_CTX, NULL));
-
-        /* Destroying or cloning secp256k1_context_static is not supported. */
-        if (use_prealloc) {
-            CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_preallocated_clone_size(STATIC_CTX));
-            {
-                secp256k1_context *my_static_ctx = malloc(sizeof(*STATIC_CTX));
-                CHECK(my_static_ctx != NULL);
-                memset(my_static_ctx, 0x2a, sizeof(*my_static_ctx));
-                CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_preallocated_clone(STATIC_CTX, my_static_ctx));
-                CHECK(all_bytes_equal(my_static_ctx, 0x2a, sizeof(*my_static_ctx)));
-                free(my_static_ctx);
-            }
-            CHECK_ILLEGAL_VOID(STATIC_CTX, secp256k1_context_preallocated_destroy(STATIC_CTX));
-        } else {
-            CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_clone(STATIC_CTX));
-            CHECK_ILLEGAL_VOID(STATIC_CTX, secp256k1_context_destroy(STATIC_CTX));
-        }
-    }
+    /* check if sizes for cloning are consistent */
+    CHECK(secp256k1_context_preallocated_clone_size(STATIC_CTX) >= sizeof(secp256k1_context));
 
-    {
-        /* Verify that setting and resetting illegal callback works */
-        int32_t dummy = 0;
-        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.data == &dummy);
-        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.data == NULL);
-    }
+    /* Verify that setting and resetting illegal callback works */
+    secp256k1_context_set_illegal_callback(STATIC_CTX, counting_illegal_callback_fn, &dummy);
+    CHECK(STATIC_CTX->illegal_callback.fn == counting_illegal_callback_fn);
+    secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL);
+    CHECK(STATIC_CTX->illegal_callback.fn == secp256k1_default_illegal_callback_fn);
 }
 
 static void run_proper_context_tests(int use_prealloc) {
     int32_t dummy = 0;
-    secp256k1_context *my_ctx, *my_ctx_fresh;
+    secp256k1_context *my_ctx;
     void *my_ctx_prealloc = NULL;
-    unsigned char seed[32] = {0x17};
 
     secp256k1_gej pubj;
     secp256k1_ge pub;
     secp256k1_scalar msg, key, nonce;
     secp256k1_scalar sigr, sigs;
-
-    /* Fresh reference context for comparison */
-    my_ctx_fresh = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
-
     if (use_prealloc) {
         my_ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
         CHECK(my_ctx_prealloc != NULL);
@@ -325,13 +262,6 @@ static void run_proper_context_tests(int use_prealloc) {
         my_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
     }
 
-    /* Randomize and reset randomization */
-    CHECK(context_eq(my_ctx, my_ctx_fresh));
-    CHECK(secp256k1_context_randomize(my_ctx, seed) == 1);
-    CHECK(!context_eq(my_ctx, my_ctx_fresh));
-    CHECK(secp256k1_context_randomize(my_ctx, NULL) == 1);
-    CHECK(context_eq(my_ctx, my_ctx_fresh));
-
     /* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
     secp256k1_context_set_error_callback(my_ctx, secp256k1_default_illegal_callback_fn, NULL);
     CHECK(my_ctx->error_callback.fn != secp256k1_default_error_callback_fn);
@@ -346,33 +276,16 @@ static void run_proper_context_tests(int use_prealloc) {
 
         if (use_prealloc) {
             /* clone into a non-preallocated context and then again into a new preallocated one. */
-            ctx_tmp = my_ctx;
-            my_ctx = secp256k1_context_clone(my_ctx);
-            CHECK(context_eq(ctx_tmp, my_ctx));
-            secp256k1_context_preallocated_destroy(ctx_tmp);
-
-            free(my_ctx_prealloc);
-            my_ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
-            CHECK(my_ctx_prealloc != NULL);
-            ctx_tmp = my_ctx;
-            my_ctx = secp256k1_context_preallocated_clone(my_ctx, my_ctx_prealloc);
-            CHECK(context_eq(ctx_tmp, my_ctx));
-            secp256k1_context_destroy(ctx_tmp);
+            ctx_tmp = my_ctx; my_ctx = secp256k1_context_clone(my_ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
+            free(my_ctx_prealloc); my_ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(my_ctx_prealloc != NULL);
+            ctx_tmp = my_ctx; my_ctx = secp256k1_context_preallocated_clone(my_ctx, my_ctx_prealloc); secp256k1_context_destroy(ctx_tmp);
         } else {
             /* clone into a preallocated context and then again into a new non-preallocated one. */
             void *prealloc_tmp;
 
-            prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
-            CHECK(prealloc_tmp != NULL);
-            ctx_tmp = my_ctx;
-            my_ctx = secp256k1_context_preallocated_clone(my_ctx, prealloc_tmp);
-            CHECK(context_eq(ctx_tmp, my_ctx));
-            secp256k1_context_destroy(ctx_tmp);
-
-            ctx_tmp = my_ctx;
-            my_ctx = secp256k1_context_clone(my_ctx);
-            CHECK(context_eq(ctx_tmp, my_ctx));
-            secp256k1_context_preallocated_destroy(ctx_tmp);
+            prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL);
+            ctx_tmp = my_ctx; my_ctx = secp256k1_context_preallocated_clone(my_ctx, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
+            ctx_tmp = my_ctx; my_ctx = secp256k1_context_clone(my_ctx); secp256k1_context_preallocated_destroy(ctx_tmp);
             free(prealloc_tmp);
         }
     }
@@ -383,16 +296,12 @@ static void run_proper_context_tests(int use_prealloc) {
     /* And that it resets back to default. */
     secp256k1_context_set_error_callback(my_ctx, NULL, NULL);
     CHECK(my_ctx->error_callback.fn == secp256k1_default_error_callback_fn);
-    CHECK(context_eq(my_ctx, my_ctx_fresh));
 
     /* Verify that setting and resetting illegal callback works */
     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.data == &dummy);
     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.data == NULL);
-    CHECK(context_eq(my_ctx, my_ctx_fresh));
 
     /*** attempt to use them ***/
     random_scalar_order_test(&msg);
@@ -418,8 +327,6 @@ static void run_proper_context_tests(int use_prealloc) {
     } else {
         secp256k1_context_destroy(my_ctx);
     }
-    secp256k1_context_destroy(my_ctx_fresh);
-
     /* Defined as no-op. */
     secp256k1_context_destroy(NULL);
     secp256k1_context_preallocated_destroy(NULL);
@@ -7482,8 +7389,9 @@ int main(int argc, char **argv) {
     run_selftest_tests();
 
     /* context tests */
-    run_proper_context_tests(0); run_proper_context_tests(1);
-    run_static_context_tests(0); run_static_context_tests(1);
+    run_proper_context_tests(0);
+    run_proper_context_tests(1);
+    run_static_context_tests();
     run_deprecated_context_flags_test();
 
     /* scratch tests */