Abstract interactions with valgrind behind new checkmem.h

This commit is contained in:
Pieter Wuille 2022-12-06 16:35:35 -05:00
parent 4f1a54e41d
commit 0db05a770e
11 changed files with 203 additions and 152 deletions

View File

@ -47,6 +47,7 @@ noinst_HEADERS += src/modinv64_impl.h
noinst_HEADERS += src/precomputed_ecmult.h
noinst_HEADERS += src/precomputed_ecmult_gen.h
noinst_HEADERS += src/assumptions.h
noinst_HEADERS += src/checkmem.h
noinst_HEADERS += src/util.h
noinst_HEADERS += src/int128.h
noinst_HEADERS += src/int128_impl.h

74
src/checkmem.h Normal file
View File

@ -0,0 +1,74 @@
/***********************************************************************
* Copyright (c) 2022 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
/* The code here is inspired by Kris Kwiatkowski's approach in
* https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h
* to provide a general interface for memory-checking mechanisms, primarily
* for constant-time checking.
*/
/* These macros are defined by this header file:
*
* - SECP256K1_CHECKMEM_ENABLED:
* - 1 if memory-checking integration is available, 0 otherwise.
* This is just a compile-time macro. Use the next macro to check it is actually
* available at runtime.
* - SECP256K1_CHECKMEM_RUNNING():
* - Acts like a function call, returning 1 if memory checking is available
* at runtime.
* - SECP256K1_CHECKMEM_CHECK(p, len):
* - Assert or otherwise fail in case the len-byte memory block pointed to by p is
* not considered entirely defined.
* - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len):
* - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode.
* - SECP256K1_CHECKMEM_UNDEFINE(p, len):
* - marks the len-byte memory block pointed to by p as undefined data (secret data,
* in the context of constant-time checking).
* - SECP256K1_CHECKMEM_DEFINE(p, len):
* - marks the len-byte memory pointed to by p as defined data (public data, in the
* context of constant-time checking).
*
*/
#ifndef SECP256K1_CHECKMEM_H
#define SECP256K1_CHECKMEM_H
/* Define a statement-like macro that ignores the arguments. */
#define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0)
/* If valgrind integration is desired (through the VALGRIND define), implement the
* SECP256K1_CHECKMEM_* macros using valgrind. */
#if !defined SECP256K1_CHECKMEM_ENABLED
# if defined VALGRIND
# include <stddef.h>
# include <valgrind/memcheck.h>
# define SECP256K1_CHECKMEM_ENABLED 1
# define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len))
# define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len))
# define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len))
/* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck.
* This is more precise than the RUNNING_ON_VALGRIND macro, which
* checks for valgrind in general instead of memcheck specifically. */
# define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0)
# endif
#endif
/* As a fall-back, map these macros to dummy statements. */
#if !defined SECP256K1_CHECKMEM_ENABLED
# define SECP256K1_CHECKMEM_ENABLED 0
# define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
# define SECP256K1_CHECKMEM_RUNNING() (0)
#endif
#if defined VERIFY
#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len))
#else
#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len))
#endif
#endif /* SECP256K1_CHECKMEM_H */

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H
#include "checkmem.h"
#include "util.h"
#include "field.h"
#include "modinv32_impl.h"
@ -1132,7 +1133,7 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint32_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = flag + ~((uint32_t)0);
mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -1231,7 +1232,7 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint32_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = flag + ~((uint32_t)0);
mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_FIELD_REPR_IMPL_H
#define SECP256K1_FIELD_REPR_IMPL_H
#include "checkmem.h"
#include "util.h"
#include "field.h"
#include "modinv64_impl.h"
@ -472,7 +473,7 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint64_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = flag + ~((uint64_t)0);
mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);
@ -555,7 +556,7 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint64_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
mask0 = flag + ~((uint64_t)0);
mask1 = ~mask0;
r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1);

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
#include "checkmem.h"
#include "int128.h"
#include "modinv64_impl.h"
@ -810,7 +811,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint64_t mask0, mask1;
VG_CHECK_VERIFY(r->d, sizeof(r->d));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
mask0 = flag + ~((uint64_t)0);
mask1 = ~mask0;
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
#include "checkmem.h"
#include "modinv32_impl.h"
/* Limbs of the secp256k1 order. */
@ -631,7 +632,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint32_t mask0, mask1;
VG_CHECK_VERIFY(r->d, sizeof(r->d));
SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d));
mask0 = flag + ~((uint32_t)0);
mask1 = ~mask0;
r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1);

View File

@ -7,6 +7,7 @@
#ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define SECP256K1_SCALAR_REPR_IMPL_H
#include "checkmem.h"
#include "scalar.h"
#include <string.h>
@ -115,7 +116,7 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) {
uint32_t mask0, mask1;
VG_CHECK_VERIFY(r, sizeof(*r));
SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r));
mask0 = flag + ~((uint32_t)0);
mask1 = ~mask0;
*r = (*r & mask0) | (*a & mask1);

View File

@ -21,6 +21,7 @@
#include "../include/secp256k1_preallocated.h"
#include "assumptions.h"
#include "checkmem.h"
#include "util.h"
#include "field_impl.h"
@ -40,10 +41,6 @@
# error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c"
#endif
#if defined(VALGRIND)
# include <valgrind/memcheck.h>
#endif
#define ARG_CHECK(cond) do { \
if (EXPECT(!(cond), 0)) { \
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
@ -215,17 +212,10 @@ void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scr
}
/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour
* of the software. This is setup for use with valgrind but could be substituted with
* the appropriate instrumentation for other analysis tools.
* of the software.
*/
static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) {
#if defined(VALGRIND)
if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len);
#else
(void)ctx;
(void)p;
(void)len;
#endif
if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len);
}
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {

View File

@ -14,6 +14,7 @@
#include "../include/secp256k1.h"
#include "../include/secp256k1_preallocated.h"
#include "testrand_impl.h"
#include "checkmem.h"
#include "util.h"
#include "../contrib/lax_der_parsing.c"
@ -193,14 +194,14 @@ void run_ec_illegal_argument_tests(void) {
/* Verify context-type checking illegal-argument errors. */
CHECK(secp256k1_ec_pubkey_create(STATIC_CTX, &pubkey, ctmp) == 0);
CHECK(ecount == 1);
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ecdsa_sign(STATIC_CTX, &sig, ctmp, ctmp, NULL, NULL) == 0);
CHECK(ecount == 2);
VG_UNDEF(&sig, sizeof(sig));
SECP256K1_CHECKMEM_UNDEFINE(&sig, sizeof(sig));
CHECK(secp256k1_ecdsa_sign(CTX, &sig, ctmp, ctmp, NULL, NULL) == 1);
VG_CHECK(&sig, sizeof(sig));
SECP256K1_CHECKMEM_CHECK(&sig, sizeof(sig));
CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(CTX, &sig, ctmp, &pubkey) == 1);
CHECK(ecount2 == 10);
@ -5444,7 +5445,7 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
/* Smaller sizes are tested exhaustively elsewhere. */
int32_t i;
memcpy(&pubkeyc[1], input, 64);
VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen);
SECP256K1_CHECKMEM_UNDEFINE(&pubkeyc[pubkeyclen], 65 - pubkeyclen);
for (i = 0; i < 256; i++) {
/* Try all type bytes. */
int xpass;
@ -5463,14 +5464,14 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
unsigned char pubkeyo[65];
size_t outl;
memset(&pubkey, 0, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
ecount = 0;
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
outl = 65;
VG_UNDEF(pubkeyo, 65);
SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65);
CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
VG_CHECK(pubkeyo, outl);
SECP256K1_CHECKMEM_CHECK(pubkeyo, outl);
CHECK(outl == 33);
CHECK(secp256k1_memcmp_var(&pubkeyo[1], &pubkeyc[1], 32) == 0);
CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0]));
@ -5479,13 +5480,13 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
CHECK(pubkeyo[0] == ysign);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 1);
memset(&pubkey, 0, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
secp256k1_pubkey_save(&pubkey, &ge);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
outl = 65;
VG_UNDEF(pubkeyo, 65);
SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65);
CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1);
VG_CHECK(pubkeyo, outl);
SECP256K1_CHECKMEM_CHECK(pubkeyo, outl);
CHECK(outl == 65);
CHECK(pubkeyo[0] == 4);
CHECK(secp256k1_memcmp_var(&pubkeyo[1], input, 64) == 0);
@ -5495,9 +5496,9 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali
/* These cases must fail to parse. */
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
@ -5696,15 +5697,15 @@ void run_ec_pubkey_parse_test(void) {
int32_t ecount2;
ecount = 0;
/* Nothing should be reading this far into pubkeyc. */
VG_UNDEF(&pubkeyc[65], 1);
SECP256K1_CHECKMEM_UNDEFINE(&pubkeyc[65], 1);
secp256k1_context_set_illegal_callback(CTX, counting_illegal_callback_fn, &ecount);
/* Zero length claimed, fail, zeroize, no illegal arg error. */
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(shortkey, 2);
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(shortkey, 2);
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 0) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
@ -5713,10 +5714,10 @@ void run_ec_pubkey_parse_test(void) {
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
shortkey[0] = i;
VG_UNDEF(&shortkey[1], 1);
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&shortkey[1], 1);
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 1) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
@ -5727,19 +5728,19 @@ void run_ec_pubkey_parse_test(void) {
ecount = 0;
shortkey[0] = i & 255;
shortkey[1] = i >> 8;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 2) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
}
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
/* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 33) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
@ -5749,43 +5750,43 @@ void run_ec_pubkey_parse_test(void) {
/* NULL input string. Illegal arg and zeroize output. */
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, NULL, 65) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 1);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 2);
/* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 64) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
/* 66 bytes claimed, fail, zeroize output, no illegal arg error. */
memset(&pubkey, 0xfe, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 66) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 0);
CHECK(ecount == 1);
/* Valid parse. */
memset(&pubkey, 0, sizeof(pubkey));
ecount = 0;
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 65) == 1);
CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(ecount == 0);
VG_UNDEF(&ge, sizeof(ge));
SECP256K1_CHECKMEM_UNDEFINE(&ge, sizeof(ge));
CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 1);
VG_CHECK(&ge.x, sizeof(ge.x));
VG_CHECK(&ge.y, sizeof(ge.y));
VG_CHECK(&ge.infinity, sizeof(ge.infinity));
SECP256K1_CHECKMEM_CHECK(&ge.x, sizeof(ge.x));
SECP256K1_CHECKMEM_CHECK(&ge.y, sizeof(ge.y));
SECP256K1_CHECKMEM_CHECK(&ge.infinity, sizeof(ge.infinity));
ge_equals_ge(&secp256k1_ge_const_g, &ge);
CHECK(ecount == 0);
/* secp256k1_ec_pubkey_serialize illegal args. */
@ -5797,9 +5798,9 @@ void run_ec_pubkey_parse_test(void) {
CHECK(secp256k1_ec_pubkey_serialize(CTX, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0);
CHECK(ecount == 2);
len = 65;
VG_UNDEF(sout, 65);
SECP256K1_CHECKMEM_UNDEFINE(sout, 65);
CHECK(secp256k1_ec_pubkey_serialize(CTX, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0);
VG_CHECK(sout, 65);
SECP256K1_CHECKMEM_CHECK(sout, 65);
CHECK(ecount == 3);
CHECK(len == 0);
len = 65;
@ -5807,9 +5808,9 @@ void run_ec_pubkey_parse_test(void) {
CHECK(ecount == 4);
CHECK(len == 0);
len = 65;
VG_UNDEF(sout, 65);
SECP256K1_CHECKMEM_UNDEFINE(sout, 65);
CHECK(secp256k1_ec_pubkey_serialize(CTX, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1);
VG_CHECK(sout, 65);
SECP256K1_CHECKMEM_CHECK(sout, 65);
CHECK(ecount == 4);
CHECK(len == 65);
/* Multiple illegal args. Should still set arg error only once. */
@ -5854,33 +5855,33 @@ void run_eckey_edge_case_test(void) {
int32_t ecount;
/* Group order is too large, reject. */
CHECK(secp256k1_ec_seckey_verify(CTX, orderc) == 0);
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, orderc) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* Maximum value is too large, reject. */
memset(ctmp, 255, 32);
CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0);
memset(&pubkey, 1, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* Zero is too small, reject. */
memset(ctmp, 0, 32);
CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0);
memset(&pubkey, 1, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* One must be accepted. */
ctmp[31] = 0x01;
CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 1);
memset(&pubkey, 0, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_one = pubkey;
/* Group order + 1 is too large, reject. */
@ -5888,17 +5889,17 @@ void run_eckey_edge_case_test(void) {
ctmp[31] = 0x42;
CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0);
memset(&pubkey, 1, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
/* -1 must be accepted. */
ctmp[31] = 0x40;
CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 1);
memset(&pubkey, 0, sizeof(pubkey));
VG_UNDEF(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1);
VG_CHECK(&pubkey, sizeof(pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_negone = pubkey;
/* Tweak of zero leaves the value unchanged. */
@ -6030,29 +6031,29 @@ void run_eckey_edge_case_test(void) {
/* secp256k1_ec_pubkey_combine tests. */
ecount = 0;
pubkeys[0] = &pubkey_one;
VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *));
VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *));
VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *));
SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[0], sizeof(secp256k1_pubkey *));
SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[1], sizeof(secp256k1_pubkey *));
SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[2], sizeof(secp256k1_pubkey *));
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 0) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_ec_pubkey_combine(CTX, NULL, pubkeys, 1) == 0);
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 2);
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, NULL, 1) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3);
pubkeys[0] = &pubkey_negone;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 1) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
len = 33;
@ -6063,17 +6064,17 @@ void run_eckey_edge_case_test(void) {
pubkeys[0] = &pubkey_one;
pubkeys[1] = &pubkey_negone;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 0);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0);
CHECK(ecount == 3);
/* Passes through infinity but comes out one. */
pubkeys[2] = &pubkey_one;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 3) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
len = 33;
@ -6083,9 +6084,9 @@ void run_eckey_edge_case_test(void) {
/* Adds to two. */
pubkeys[1] = &pubkey_one;
memset(&pubkey, 255, sizeof(secp256k1_pubkey));
VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 1);
VG_CHECK(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey));
CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
CHECK(ecount == 3);
secp256k1_context_set_illegal_callback(CTX, NULL, NULL);
@ -7096,18 +7097,18 @@ void test_ecdsa_edge_cases(void) {
unsigned char nonce2[32];
unsigned char nonce3[32];
unsigned char nonce4[32];
VG_UNDEF(nonce,32);
VG_UNDEF(nonce2,32);
VG_UNDEF(nonce3,32);
VG_UNDEF(nonce4,32);
SECP256K1_CHECKMEM_UNDEFINE(nonce,32);
SECP256K1_CHECKMEM_UNDEFINE(nonce2,32);
SECP256K1_CHECKMEM_UNDEFINE(nonce3,32);
SECP256K1_CHECKMEM_UNDEFINE(nonce4,32);
CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1);
VG_CHECK(nonce,32);
SECP256K1_CHECKMEM_CHECK(nonce,32);
CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1);
VG_CHECK(nonce2,32);
SECP256K1_CHECKMEM_CHECK(nonce2,32);
CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1);
VG_CHECK(nonce3,32);
SECP256K1_CHECKMEM_CHECK(nonce3,32);
CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1);
VG_CHECK(nonce4,32);
SECP256K1_CHECKMEM_CHECK(nonce4,32);
CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0);
CHECK(secp256k1_memcmp_var(nonce, nonce3, 32) != 0);
CHECK(secp256k1_memcmp_var(nonce, nonce4, 32) != 0);

View File

@ -97,25 +97,6 @@ static const secp256k1_callback default_error_callback = {
#define VERIFY_SETUP(stmt)
#endif
/* Define `VG_UNDEF` and `VG_CHECK` when VALGRIND is defined */
#if !defined(VG_CHECK)
# if defined(VALGRIND)
# include <valgrind/memcheck.h>
# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y))
# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y))
# else
# define VG_UNDEF(x,y)
# define VG_CHECK(x,y)
# endif
#endif
/* Like `VG_CHECK` but on VERIFY only */
#if defined(VERIFY)
#define VG_CHECK_VERIFY(x,y) VG_CHECK((x), (y))
#else
#define VG_CHECK_VERIFY(x,y)
#endif
static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) {
void *ret = malloc(size);
if (ret == NULL) {

View File

@ -4,12 +4,11 @@
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
***********************************************************************/
#include <valgrind/memcheck.h>
#include <stdio.h>
#include "../include/secp256k1.h"
#include "assumptions.h"
#include "util.h"
#include "checkmem.h"
#ifdef ENABLE_MODULE_ECDH
# include "../include/secp256k1_ecdh.h"
@ -34,7 +33,7 @@ int main(void) {
unsigned char key[32];
int ret, i;
if (!RUNNING_ON_VALGRIND) {
if (!SECP256K1_CHECKMEM_RUNNING()) {
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;
@ -51,9 +50,9 @@ int main(void) {
/* Test context randomisation. Do this last because it leaves the context
* tainted. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_context_randomize(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret);
secp256k1_context_destroy(ctx);
@ -83,89 +82,89 @@ void run_tests(secp256k1_context *ctx, unsigned char *key) {
}
/* Test keygen. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key);
VALGRIND_MAKE_MEM_DEFINED(&pubkey, sizeof(secp256k1_pubkey));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&pubkey, sizeof(secp256k1_pubkey));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret);
CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1);
/* Test signing. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&signature, sizeof(secp256k1_ecdsa_signature));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&signature, sizeof(secp256k1_ecdsa_signature));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret);
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature));
#ifdef ENABLE_MODULE_ECDH
/* Test ECDH. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdh(ctx, msg, &pubkey, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
#endif
#ifdef ENABLE_MODULE_RECOVERY
/* Test signing a recoverable signature. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL);
VALGRIND_MAKE_MEM_DEFINED(&recoverable_signature, sizeof(recoverable_signature));
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&recoverable_signature, sizeof(recoverable_signature));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret);
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature));
CHECK(recid >= 0 && recid <= 3);
#endif
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_seckey_verify(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ec_seckey_negate(ctx, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(msg, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(msg, 32);
ret = secp256k1_ec_seckey_tweak_add(ctx, key, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(msg, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(msg, 32);
ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
/* Test keypair_create and keypair_xonly_tweak_add. */
#ifdef ENABLE_MODULE_EXTRAKEYS
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
/* The tweak is not treated as a secret in keypair_tweak_add */
VALGRIND_MAKE_MEM_DEFINED(msg, 32);
SECP256K1_CHECKMEM_DEFINE(msg, 32);
ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
VALGRIND_MAKE_MEM_UNDEFINED(&keypair, sizeof(keypair));
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair));
ret = secp256k1_keypair_sec(ctx, key, &keypair);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
#endif
#ifdef ENABLE_MODULE_SCHNORRSIG
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
#endif
}