Skip to content

Commit d39f5a2

Browse files
Bug: ModSqrt entered infinite loop with p == 1
Thanks to Eric Cornelissen for discovering and responsibly reporting this vulnerability. The problem was that our tonelliShanks algorithm needed to calculate the number of least significant zeros in p - 1. This was done by shifting right until the LSB becomes 1. With p == 1, this process never ends, because p - 1 == 0, sending us into an infinite loop. This could be a potential vulnerability, because if a modulus can be controlled by an adversary, they can cause a process to deadlock. The fix is to simply check if p == 1, and return 0 in that case, which makes perfect sense mathematically. Checking the value of the modulus is also fine from a leakage perspective, because ModSqrt is explicitly allowed to leak the value of the modulus. Co-authored-by: Eric Cornelissen <[email protected]>
1 parent d98b039 commit d39f5a2

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

num.go

+7
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,13 @@ func (z *Nat) tonelliShanks(x *Nat, p *Modulus) *Nat {
18681868
one := new(Nat).SetUint64(1)
18691869
trailingZeros := 1
18701870
reducedPminusOne := new(Nat).Sub(&p.nat, one, p.BitLen())
1871+
// In this case, p must have been 1, so sqrt(x) mod p is 0. Explicitly checking
1872+
// this avoids an infinite loop when trying to remove the least significant zeros.
1873+
// Checking this value is fine, since ModSqrt is explicitly allowed to branch
1874+
// on the value of the modulus.
1875+
if reducedPminusOne.EqZero() == 1 {
1876+
return z.SetUint64(0)
1877+
}
18711878
shrVU(reducedPminusOne.limbs, reducedPminusOne.limbs, 1)
18721879

18731880
nonSquare := new(Nat).SetUint64(2)

num_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,12 @@ func TestModSqrtExamples(t *testing.T) {
10751075
if x.Eq(z) != 1 {
10761076
t.Errorf("%+v != %+v", x, z)
10771077
}
1078+
m = ModulusFromUint64(1)
1079+
x.SetUint64(13)
1080+
x.ModSqrt(x, m)
1081+
if x.EqZero() != 1 {
1082+
t.Errorf("%+v != 0", x)
1083+
}
10781084
}
10791085

10801086
func TestBigExamples(t *testing.T) {

0 commit comments

Comments
 (0)