@@ -18,6 +18,15 @@ const (
18
18
_S = _W / 8
19
19
)
20
20
21
+ // Note: These functions make many loops over all the words in a Nat.
22
+ // These loops used to be in assembly, invisible to -race, -asan, and -msan,
23
+ // but now they are in Go and incur significant overhead in those modes.
24
+ // To bring the old performance back, we mark all functions that loop
25
+ // over Nat words with //go:norace. Because //go:norace does not
26
+ // propagate across inlining, we must also mark functions that inline
27
+ // //go:norace functions - specifically, those that inline add, addMulVVW,
28
+ // assign, cmpGeq, rshift1, and sub.
29
+
21
30
// choice represents a constant-time boolean. The value of choice is always
22
31
// either 1 or 0. We use an int instead of bool in order to make decisions in
23
32
// constant time by turning it into a mask.
@@ -152,6 +161,8 @@ func (x *Nat) Bytes(m *Modulus) []byte {
152
161
// SetBytes returns an error if b >= m.
153
162
//
154
163
// The output will be resized to the size of m and overwritten.
164
+ //
165
+ //go:norace
155
166
func (x * Nat ) SetBytes (b []byte , m * Modulus ) (* Nat , error ) {
156
167
x .resetFor (m )
157
168
if err := x .setBytes (b ); err != nil {
@@ -283,8 +294,6 @@ func (x *Nat) IsMinusOne(m *Modulus) choice {
283
294
}
284
295
285
296
// IsOdd returns 1 if x is odd, and 0 otherwise.
286
- //
287
- //go:norace
288
297
func (x * Nat ) IsOdd () choice {
289
298
if len (x .limbs ) == 0 {
290
299
return no
@@ -538,6 +547,8 @@ func NewModulus(b []byte) (*Modulus, error) {
538
547
539
548
// NewModulusProduct creates a new Modulus from the product of two numbers
540
549
// represented as big-endian byte slices. The result must be greater than one.
550
+ //
551
+ //go:norace
541
552
func NewModulusProduct (a , b []byte ) (* Modulus , error ) {
542
553
x := NewNat ().resetToBytes (a )
543
554
y := NewNat ().resetToBytes (b )
@@ -624,6 +635,8 @@ func (x *Nat) shiftIn(y uint, m *Modulus) *Nat {
624
635
// This works regardless how large the value of x is.
625
636
//
626
637
// The output will be resized to the size of m and overwritten.
638
+ //
639
+ //go:norace
627
640
func (out * Nat ) Mod (x * Nat , m * Modulus ) * Nat {
628
641
out .resetFor (m )
629
642
// Working our way from the most significant to the least significant limb,
@@ -673,6 +686,8 @@ func (out *Nat) resetFor(m *Modulus) *Nat {
673
686
// overflowed its size, meaning abstractly x > 2^_W*n > m even if x < m.
674
687
//
675
688
// x and m operands must have the same announced length.
689
+ //
690
+ //go:norace
676
691
func (x * Nat ) maybeSubtractModulus (always choice , m * Modulus ) {
677
692
t := NewNat ().set (x )
678
693
underflow := t .sub (m .nat )
@@ -686,6 +701,8 @@ func (x *Nat) maybeSubtractModulus(always choice, m *Modulus) {
686
701
//
687
702
// The length of both operands must be the same as the modulus. Both operands
688
703
// must already be reduced modulo m.
704
+ //
705
+ //go:norace
689
706
func (x * Nat ) Sub (y * Nat , m * Modulus ) * Nat {
690
707
underflow := x .sub (y )
691
708
// If the subtraction underflowed, add m.
@@ -710,6 +727,8 @@ func (x *Nat) SubOne(m *Modulus) *Nat {
710
727
//
711
728
// The length of both operands must be the same as the modulus. Both operands
712
729
// must already be reduced modulo m.
730
+ //
731
+ //go:norace
713
732
func (x * Nat ) Add (y * Nat , m * Modulus ) * Nat {
714
733
overflow := x .add (y )
715
734
x .maybeSubtractModulus (choice (overflow ), m )
@@ -747,6 +766,8 @@ func (x *Nat) montgomeryReduction(m *Modulus) *Nat {
747
766
//
748
767
// All inputs should be the same length and already reduced modulo m.
749
768
// x will be resized to the size of m and overwritten.
769
+ //
770
+ //go:norace
750
771
func (x * Nat ) montgomeryMul (a * Nat , b * Nat , m * Modulus ) * Nat {
751
772
n := len (m .nat .limbs )
752
773
mLimbs := m .nat .limbs [:n ]
@@ -890,6 +911,8 @@ func addMulVVW(z, x []uint, y uint) (carry uint) {
890
911
//
891
912
// The length of both operands must be the same as the modulus. Both operands
892
913
// must already be reduced modulo m.
914
+ //
915
+ //go:norace
893
916
func (x * Nat ) Mul (y * Nat , m * Modulus ) * Nat {
894
917
if m .odd {
895
918
// A Montgomery multiplication by a value out of the Montgomery domain
@@ -951,6 +974,8 @@ func (x *Nat) Mul(y *Nat, m *Modulus) *Nat {
951
974
// to the size of m and overwritten. x must already be reduced modulo m.
952
975
//
953
976
// m must be odd, or Exp will panic.
977
+ //
978
+ //go:norace
954
979
func (out * Nat ) Exp (x * Nat , e []byte , m * Modulus ) * Nat {
955
980
if ! m .odd {
956
981
panic ("bigmod: modulus for Exp must be odd" )
@@ -1030,6 +1055,8 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat {
1030
1055
//
1031
1056
// a must be reduced modulo m, but doesn't need to have the same size. The
1032
1057
// output will be resized to the size of m and overwritten.
1058
+ //
1059
+ //go:norace
1033
1060
func (x * Nat ) InverseVarTime (a * Nat , m * Modulus ) (* Nat , bool ) {
1034
1061
// This is the extended binary GCD algorithm described in the Handbook of
1035
1062
// Applied Cryptography, Algorithm 14.61, adapted by BoringSSL to bound
0 commit comments