btcec: Ensure reduction when > P in all cases.
As noted in issue #706, the existing code had an issue where the normalized result was > P when both the first and second words of the field representation being normalized were BOTH greater than or equal to the first and second words of P. Although this condition is rare in practice, it needs to be handled properly. This resolves the issue by comparing the low words in the final reduction step against the normalized low order prime bits to ensure the final subtraction occurs correctly any time they're > P. This approach retains the constant time property as well.
This commit is contained in:
parent
d009185a56
commit
a52eb04aaa
1 changed files with 13 additions and 14 deletions
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Copyright (c) 2013-2014 Dave Collins
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2013-2016 Dave Collins
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -94,14 +94,16 @@ const (
|
|||
fieldMSBMask = (1 << fieldMSBBits) - 1
|
||||
|
||||
// fieldPrimeWordZero is word zero of the secp256k1 prime in the
|
||||
// internal field representation. It is used during modular reduction
|
||||
// and negation.
|
||||
// internal field representation. It is used during negation.
|
||||
fieldPrimeWordZero = 0x3fffc2f
|
||||
|
||||
// fieldPrimeWordOne is word one of the secp256k1 prime in the
|
||||
// internal field representation. It is used during modular reduction
|
||||
// and negation.
|
||||
// internal field representation. It is used during negation.
|
||||
fieldPrimeWordOne = 0x3ffffbf
|
||||
|
||||
// primeLowBits is the lower 2*fieldBase bits of the secp256k1 prime in
|
||||
// its standard normalized form. It is used during modular reduction.
|
||||
primeLowBits = 0xffffefffffc2f
|
||||
)
|
||||
|
||||
// fieldVal implements optimized fixed-precision arithmetic over the
|
||||
|
@ -331,12 +333,8 @@ func (f *fieldVal) Normalize() *fieldVal {
|
|||
// zero even though it won't change the value to ensure constant time
|
||||
// between the branches.
|
||||
var mask int32
|
||||
if t0 < fieldPrimeWordZero {
|
||||
mask |= -1
|
||||
} else {
|
||||
mask |= 0
|
||||
}
|
||||
if t1 < fieldPrimeWordOne {
|
||||
lowBits := uint64(t1)<<fieldBase | uint64(t0)
|
||||
if lowBits < primeLowBits {
|
||||
mask |= -1
|
||||
} else {
|
||||
mask |= 0
|
||||
|
@ -381,8 +379,9 @@ func (f *fieldVal) Normalize() *fieldVal {
|
|||
} else {
|
||||
mask |= 0
|
||||
}
|
||||
t0 = t0 - uint32(^mask&fieldPrimeWordZero)
|
||||
t1 = t1 - uint32(^mask&fieldPrimeWordOne)
|
||||
lowBits -= ^uint64(mask) & primeLowBits
|
||||
t0 = uint32(lowBits & fieldBaseMask)
|
||||
t1 = uint32((lowBits >> fieldBase) & fieldBaseMask)
|
||||
t2 = t2 & uint32(mask)
|
||||
t3 = t3 & uint32(mask)
|
||||
t4 = t4 & uint32(mask)
|
||||
|
|
Loading…
Reference in a new issue