mirror of
https://github.com/ARMmbed/mbedtls.git
synced 2025-10-19 02:23:41 +08:00

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>