From a52eb04aaabfb7f6ec03b8cdab8a432b58fd3862 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 20 Jun 2016 16:18:48 -0500 Subject: [PATCH] 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. --- btcec/field.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/btcec/field.go b/btcec/field.go index 2a74878b..c2c6a645 100644 --- a/btcec/field.go +++ b/btcec/field.go @@ -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) & fieldBaseMask) t2 = t2 & uint32(mask) t3 = t3 & uint32(mask) t4 = t4 & uint32(mask)