Add API to override SHA256 compression at runtime
This introduces `secp256k1_context_set_sha256_compression()`, which allows users to provide their own SHA256 block-compression function at runtime. This is useful in setups where the fastest implementation can only be determined dynamically based on the available CPU features, and rebuilding the library is not possible. The callback is installed on the `secp256k1_context` and is then used by all operations that compute SHA256 hashes. As part of the setup, the library performs sanity checks to ensure that the supplied function is equivalent to the default transform. Passing NULL to the callback setter restores the built-in implementation.
This commit is contained in:
@@ -562,8 +562,14 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output,
|
||||
secp256k1_fe_normalize(&px);
|
||||
secp256k1_fe_get_b32(sx, &px);
|
||||
|
||||
/* Invoke hasher */
|
||||
ret = hashfp(output, sx, ell_a64, ell_b64, data);
|
||||
/* Invoke hasher. Use ctx-aware function by default */
|
||||
if (hashfp == secp256k1_ellswift_xdh_hash_function_bip324) {
|
||||
ret = ellswift_xdh_hash_function_bip324_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data);
|
||||
} else if (hashfp == secp256k1_ellswift_xdh_hash_function_prefix) {
|
||||
ret = ellswift_xdh_hash_function_prefix_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data);
|
||||
} else {
|
||||
ret = hashfp(output, sx, ell_a64, ell_b64, data);
|
||||
}
|
||||
|
||||
secp256k1_memclear_explicit(sx, sizeof(sx));
|
||||
secp256k1_fe_clear(&px);
|
||||
|
||||
@@ -431,6 +431,40 @@ void ellswift_xdh_correctness_tests(void) {
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_SHA256_TRANSFORM_PROBE(sha256_ellswift_xdh)
|
||||
void ellswift_xdh_ctx_sha256_tests(void) {
|
||||
/* Check ctx-provided SHA256 compression override takes effect */
|
||||
secp256k1_context *ctx = secp256k1_context_clone(CTX);
|
||||
unsigned char out_default[65], out_custom[65];
|
||||
const unsigned char skA[32] = {1}, skB[32] = {2};
|
||||
unsigned char keyA[64], keyB[64], data[64] = {0};
|
||||
const secp256k1_ellswift_xdh_hash_function hash_funcs[2] = {secp256k1_ellswift_xdh_hash_function_bip324, secp256k1_ellswift_xdh_hash_function_prefix};
|
||||
int i;
|
||||
|
||||
CHECK(secp256k1_ellswift_create(ctx, keyA, skA, NULL));
|
||||
CHECK(secp256k1_ellswift_create(ctx, keyB, skB, NULL));
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
const secp256k1_ellswift_xdh_hash_function hash_fn = hash_funcs[i];
|
||||
/* Default behavior. No ctx-provided SHA256 compression */
|
||||
CHECK(secp256k1_ellswift_xdh(ctx, out_default, keyA, keyB, skA, 0, hash_fn, data));
|
||||
CHECK(!sha256_ellswift_xdh_called);
|
||||
|
||||
/* Override SHA256 compression directly, bypassing the ctx setter sanity checks */
|
||||
ctx->hash_ctx.fn_sha256_compression = sha256_ellswift_xdh;
|
||||
CHECK(secp256k1_ellswift_xdh(ctx, out_custom, keyA, keyB, skA, 0, hash_fn, data));
|
||||
CHECK(sha256_ellswift_xdh_called);
|
||||
/* Outputs must differ if custom compression was used */
|
||||
CHECK(secp256k1_memcmp_var(out_default, out_custom, 32) != 0);
|
||||
|
||||
/* Restore defaults */
|
||||
sha256_ellswift_xdh_called = 0;
|
||||
secp256k1_context_set_sha256_compression(ctx, NULL);
|
||||
}
|
||||
|
||||
secp256k1_context_destroy(ctx);
|
||||
}
|
||||
|
||||
/* Test hash initializers */
|
||||
void ellswift_hash_init_tests(void) {
|
||||
secp256k1_sha256 sha_optimized;
|
||||
@@ -499,6 +533,7 @@ static const struct tf_test_entry tests_ellswift[] = {
|
||||
CASE1(ellswift_xdh_correctness_tests),
|
||||
CASE1(ellswift_hash_init_tests),
|
||||
CASE1(ellswift_xdh_bad_scalar_tests),
|
||||
CASE1(ellswift_xdh_ctx_sha256_tests),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user