Skip to content

Commit

Permalink
Bug: ModSqrt entered infinite loop with p == 1
Browse files Browse the repository at this point in the history
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 <ericornelissen@gmail.com>
  • Loading branch information
cronokirby and ericcornelissen committed Sep 8, 2021
1 parent d98b039 commit d39f5a2
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 0 deletions.
7 changes: 7 additions & 0 deletions num.go
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,13 @@ func (z *Nat) tonelliShanks(x *Nat, p *Modulus) *Nat {
one := new(Nat).SetUint64(1)
trailingZeros := 1
reducedPminusOne := new(Nat).Sub(&p.nat, one, p.BitLen())
// In this case, p must have been 1, so sqrt(x) mod p is 0. Explicitly checking
// this avoids an infinite loop when trying to remove the least significant zeros.
// Checking this value is fine, since ModSqrt is explicitly allowed to branch
// on the value of the modulus.
if reducedPminusOne.EqZero() == 1 {
return z.SetUint64(0)
}
shrVU(reducedPminusOne.limbs, reducedPminusOne.limbs, 1)

nonSquare := new(Nat).SetUint64(2)
Expand Down
6 changes: 6 additions & 0 deletions num_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,12 @@ func TestModSqrtExamples(t *testing.T) {
if x.Eq(z) != 1 {
t.Errorf("%+v != %+v", x, z)
}
m = ModulusFromUint64(1)
x.SetUint64(13)
x.ModSqrt(x, m)
if x.EqZero() != 1 {
t.Errorf("%+v != 0", x)
}
}

func TestBigExamples(t *testing.T) {
Expand Down

0 comments on commit d39f5a2

Please sign in to comment.