Valgrind does bit-level tracking of the "uninitialized" status of memory,
property tracks memory which is tainted by any uninitialized memory, and
warns if any branch or array access depends on an uninitialized bit.
That is exactly the verification we need on secret data to test for
constant-time behaviour. All we need to do is tell valgrind our
secret key is actually uninitialized memory.
This adds a valgrind_ctime_test which is compiled if valgrind is installed:
Run it with libtool --mode=execute:
$ libtool --mode=execute valgrind ./valgrind_ctime_test
We observe that when changing the b-value in the elliptic curve formula
`y^2 = x^3 + ax + b`, the group law is unchanged. Therefore our functions
for secp256k1 will be correct if and only if they are correct when applied
to the curve defined by `y^2 = x^3 + 4` defined over the same field. This
curve has a point P of order 199.
This commit adds a test which computes the subgroup generated by P and
exhaustively checks that addition of every pair of points gives the correct
result.
Unfortunately we cannot test const-time scalar multiplication by the same
mechanism. The reason is that these ecmult functions both compute a wNAF
representation of the scalar, and this representation is tied to the order
of the group.
Testing with the incomplete version of gej_add_ge (found in 5de4c5dff^)
shows that this detects the incompleteness when adding P - 106P, which
is exactly what we expected since 106 is a cube root of 1 mod 199.
This vastly shrinks the size of the context required for signing on devices with
memory-mapped Flash.
Tables are generated by the new gen_context tool into a header.