Changeset View
Changeset View
Standalone View
Standalone View
src/secp256k1/src/valgrind_ctime_test.c
/*********************************************************************** | /*********************************************************************** | ||||
* Copyright (c) 2020 Gregory Maxwell * | * Copyright (c) 2020 Gregory Maxwell * | ||||
* Distributed under the MIT software license, see the accompanying * | * Distributed under the MIT software license, see the accompanying * | ||||
* file COPYING or https://www.opensource.org/licenses/mit-license.php.* | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* | ||||
***********************************************************************/ | ***********************************************************************/ | ||||
#include <valgrind/memcheck.h> | #include <valgrind/memcheck.h> | ||||
#include <stdio.h> | |||||
#include "include/secp256k1.h" | #include "include/secp256k1.h" | ||||
#include "assumptions.h" | #include "assumptions.h" | ||||
#include "util.h" | #include "util.h" | ||||
#ifdef ENABLE_MODULE_ECDH | #ifdef ENABLE_MODULE_ECDH | ||||
# include "include/secp256k1_ecdh.h" | # include "include/secp256k1_ecdh.h" | ||||
#endif | #endif | ||||
#ifdef ENABLE_MODULE_RECOVERY | #ifdef ENABLE_MODULE_RECOVERY | ||||
# include "include/secp256k1_recovery.h" | # include "include/secp256k1_recovery.h" | ||||
#endif | #endif | ||||
#ifdef ENABLE_MODULE_SCHNORR | #ifdef ENABLE_MODULE_SCHNORR | ||||
# include "include/secp256k1_schnorr.h" | # include "include/secp256k1_schnorr.h" | ||||
#endif | #endif | ||||
#ifdef ENABLE_MODULE_EXTRAKEYS | #ifdef ENABLE_MODULE_EXTRAKEYS | ||||
# include "include/secp256k1_extrakeys.h" | # include "include/secp256k1_extrakeys.h" | ||||
#endif | #endif | ||||
#ifdef ENABLE_MODULE_SCHNORRSIG | #ifdef ENABLE_MODULE_SCHNORRSIG | ||||
#include "include/secp256k1_schnorrsig.h" | #include "include/secp256k1_schnorrsig.h" | ||||
#endif | #endif | ||||
void run_tests(secp256k1_context *ctx, unsigned char *key); | |||||
int main(void) { | int main(void) { | ||||
secp256k1_context* ctx; | secp256k1_context* ctx; | ||||
unsigned char key[32]; | |||||
int ret, i; | |||||
if (!RUNNING_ON_VALGRIND) { | |||||
fprintf(stderr, "This test can only usefully be run inside valgrind.\n"); | |||||
fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n"); | |||||
return 1; | |||||
} | |||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | |||||
| SECP256K1_CONTEXT_VERIFY | |||||
| SECP256K1_CONTEXT_DECLASSIFY); | |||||
/** In theory, testing with a single secret input should be sufficient: | |||||
* If control flow depended on secrets the tool would generate an error. | |||||
*/ | |||||
for (i = 0; i < 32; i++) { | |||||
key[i] = i + 65; | |||||
} | |||||
run_tests(ctx, key); | |||||
/* Test context randomisation. Do this last because it leaves the context | |||||
* tainted. */ | |||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | |||||
ret = secp256k1_context_randomize(ctx, key); | |||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | |||||
CHECK(ret); | |||||
secp256k1_context_destroy(ctx); | |||||
return 0; | |||||
} | |||||
void run_tests(secp256k1_context *ctx, unsigned char *key) { | |||||
secp256k1_ecdsa_signature signature; | secp256k1_ecdsa_signature signature; | ||||
secp256k1_pubkey pubkey; | secp256k1_pubkey pubkey; | ||||
size_t siglen = 74; | size_t siglen = 74; | ||||
size_t outputlen = 33; | size_t outputlen = 33; | ||||
int i; | int i; | ||||
int ret; | int ret; | ||||
unsigned char msg[32]; | unsigned char msg[32]; | ||||
unsigned char key[32]; | |||||
unsigned char sig[74]; | unsigned char sig[74]; | ||||
unsigned char spubkey[33]; | unsigned char spubkey[33]; | ||||
#ifdef ENABLE_MODULE_RECOVERY | #ifdef ENABLE_MODULE_RECOVERY | ||||
secp256k1_ecdsa_recoverable_signature recoverable_signature; | secp256k1_ecdsa_recoverable_signature recoverable_signature; | ||||
int recid; | int recid; | ||||
#endif | #endif | ||||
#ifdef ENABLE_MODULE_EXTRAKEYS | #ifdef ENABLE_MODULE_EXTRAKEYS | ||||
secp256k1_keypair keypair; | secp256k1_keypair keypair; | ||||
#endif | #endif | ||||
if (!RUNNING_ON_VALGRIND) { | |||||
fprintf(stderr, "This test can only usefully be run inside valgrind.\n"); | |||||
fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n"); | |||||
exit(1); | |||||
} | |||||
/** In theory, testing with a single secret input should be sufficient: | |||||
* If control flow depended on secrets the tool would generate an error. | |||||
*/ | |||||
for (i = 0; i < 32; i++) { | |||||
key[i] = i + 65; | |||||
} | |||||
for (i = 0; i < 32; i++) { | for (i = 0; i < 32; i++) { | ||||
msg[i] = i + 1; | msg[i] = i + 1; | ||||
} | } | ||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | |||||
| SECP256K1_CONTEXT_VERIFY | |||||
| SECP256K1_CONTEXT_DECLASSIFY); | |||||
/* Test keygen. */ | /* Test keygen. */ | ||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | ||||
ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key); | ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key); | ||||
VALGRIND_MAKE_MEM_DEFINED(&pubkey, sizeof(secp256k1_pubkey)); | VALGRIND_MAKE_MEM_DEFINED(&pubkey, sizeof(secp256k1_pubkey)); | ||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | ||||
CHECK(ret); | CHECK(ret); | ||||
CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); | CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | #endif | ||||
CHECK(ret == 1); | CHECK(ret == 1); | ||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | ||||
VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); | VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); | ||||
ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg); | ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg); | ||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | ||||
CHECK(ret == 1); | CHECK(ret == 1); | ||||
/* Test context randomisation. Do this last because it leaves the context tainted. */ | |||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | |||||
ret = secp256k1_context_randomize(ctx, key); | |||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | |||||
CHECK(ret); | |||||
/* Test keypair_create and keypair_xonly_tweak_add. */ | /* Test keypair_create and keypair_xonly_tweak_add. */ | ||||
#ifdef ENABLE_MODULE_EXTRAKEYS | #ifdef ENABLE_MODULE_EXTRAKEYS | ||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | ||||
ret = secp256k1_keypair_create(ctx, &keypair, key); | ret = secp256k1_keypair_create(ctx, &keypair, key); | ||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | ||||
CHECK(ret == 1); | CHECK(ret == 1); | ||||
/* The tweak is not treated as a secret in keypair_tweak_add */ | /* The tweak is not treated as a secret in keypair_tweak_add */ | ||||
Show All 13 Lines | #ifdef ENABLE_MODULE_SCHNORRSIG | ||||
VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | VALGRIND_MAKE_MEM_UNDEFINED(key, 32); | ||||
ret = secp256k1_keypair_create(ctx, &keypair, key); | ret = secp256k1_keypair_create(ctx, &keypair, key); | ||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | ||||
CHECK(ret == 1); | CHECK(ret == 1); | ||||
ret = secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL); | ret = secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL); | ||||
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); | ||||
CHECK(ret == 1); | CHECK(ret == 1); | ||||
#endif | #endif | ||||
secp256k1_context_destroy(ctx); | |||||
return 0; | |||||
} | } |