With this data, the loop only settles to its final state u == 0 and v ==
GCD(A, N) at the last iteration. However it already has v == GCD(A, N)
at the previous iteration. Concretely, this means that if in
mbedtls_mpi_core_gcd_modinv_odd() we change the main loop as follows
- for (size_t i = 0; i < (A_limbs + N_limbs) * biL; i++) {
+ for (size_t i = 0; i < (A_limbs + N_limbs) * biL - 2; i++) {
then this test case would fail. Ideally we'd like a test case that would
fail with -1 above but I've not been able to find one and I have no idea
whether that's possible.
Experimentally I've systematically tried small values (8 bit) and
noticed the case A = 2^n and N significantly larger then A is promising,
so I explored that further. Clearly we want A and N's bitlength to be a
multiple of biL because the bound in the paper is with bitlenths while
we use limbs * biL.
Anyway, I ended up with the following Python script.
import secrets
import math
bil = 64
def bitlimbs(x):
return (x.bit_length() + bil - 1) // bil * bil
def sict_gcd(p, a):
assert p >= a >= 0
assert p & 1 != 0 or a & 1 != 0
u, v = a, p
for i in range(2 * p.bit_length()):
s, z = u & 1, v & 1
t1 = (s ^ z) * v + (2 * s * z - 1) * u
t2 = (s * v + (2 - 2 * s - z) * u) >> 1
if t2 >= t1:
u, v = t1, t2
else:
u, v = t2, t1
if u == 0: # v == 1 ideally, but can't get it
return bitlimbs(a) + bitlimbs(p) - (i + 1)
return 0
a = 2 ** (bil - 1)
m = 1000
while m != 0:
n = secrets.randbits(2 * bil) | 1
d = sict_gcd(n, a)
if d < m:
m = d
print(d)
g = math.gcd(a, n)
i = pow(a, -1, n)
print(f'mpi_core_gcd_modinv_odd:"{a:x}":"{n:x}":"{g:x}":"{i:x}"')
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
This function has specific code to handle carries and it's not clear how
to exercises that code through the modinv function, so well, that's what
unit tests are for.
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
This is a direct translation of sict_mi2() from
https://github.com/mpg/cryptohack/blob/main/ct-pres.py
which was presented in the book club's special session.
This commit only includes two test cases which is very little. Most of
the test cases will be generated by Python modules that belong to the
framework. However we can't have the framework generate those before we
have the corresponding test function in the consuming branches. So,
extended tests are coming as a 2nd step, after the test function has
been merged.
(The test cases in .misc should stay, as they can be convenient when
working on the test function.)
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Compare a single-limb MPI with a multi-limb MPI. This is rather ad hoc, but
will be useful for mbedtls_mpi_core_random.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
A core MPI must have at least 1 limb. We can no longer test with 0 limbs,
and we don't need to anyway, so don't try.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
Legacy Bignum is excluded as it doesn't get regular extensions like new
ones.
Each slot uses comments of their respective filetype. Since .data files
don't have a syntax for comments, dummy test cases are used. (These test
cases will never be executed and no noise will be added to tests.)
Signed-off-by: Janos Follath <janos.follath@arm.com>
Turn mpi_fill_random_internal() into mbedtls_mpi_core_fill_random(). It
had basically the right code except for how X is passed to the function.
Write unit tests.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This patch moves the following tests to test_suite_bignum_core:
* `mbedtls_mpi_core_get_mont_r2_unsafe_neg()`
* `mbedtls_mpi_core_get_mont_r2_unsafe()`
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
Although our build scripts support that, it's annoying, because it makes
"test_suite_XXX" ambiguous between "all the data for
test_suite_XXX.function" and "just test_suite_XXX.data".
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>