github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/edwards25519_fe_amd64.go (about)

     1  // Copyright (c) 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build amd64
     6  
     7  package crypto
     8  
     9  // Field arithmetic in radix 2^51 representation. This code is a port of the
    10  // public domain amd64-51-30k version of ed25519 from SUPERCOP.
    11  
    12  // FieldElement represents an element of the field GF(2^255-19). An element t
    13  // represents the integer t[0] + t[1]*2^51 + t[2]*2^102 + t[3]*2^153 +
    14  // t[4]*2^204.
    15  type FieldElement [5]uint64
    16  
    17  //const maskLow51Bits = (1 << 51) - 1
    18  
    19  // FeAdd sets out = a + b. Long sequences of additions without reduction that
    20  // let coefficients grow larger than 54 bits would be a problem. Paper
    21  // cautions: "do not have such sequences of additions".
    22  func FeAdd(out, a, b *FieldElement) {
    23  	out[0] = a[0] + b[0]
    24  	out[1] = a[1] + b[1]
    25  	out[2] = a[2] + b[2]
    26  	out[3] = a[3] + b[3]
    27  	out[4] = a[4] + b[4]
    28  }
    29  
    30  // FeSub sets out = a - b
    31  func FeSub(out, a, b *FieldElement) {
    32  	var t FieldElement
    33  	t = *b
    34  
    35  	// Reduce each limb below 2^51, propagating carries. Ensures that results
    36  	// fit within the limbs. This would not be required for reduced input.
    37  	t[1] += t[0] >> 51
    38  	t[0] = t[0] & maskLow51Bits
    39  	t[2] += t[1] >> 51
    40  	t[1] = t[1] & maskLow51Bits
    41  	t[3] += t[2] >> 51
    42  	t[2] = t[2] & maskLow51Bits
    43  	t[4] += t[3] >> 51
    44  	t[3] = t[3] & maskLow51Bits
    45  	t[0] += (t[4] >> 51) * 19
    46  	t[4] = t[4] & maskLow51Bits
    47  
    48  	// This is slightly more complicated. Because we use unsigned coefficients,
    49  	// we first add a multiple of p and then subtract.
    50  	out[0] = (a[0] + 0xFFFFFFFFFFFDA) - t[0]
    51  	out[1] = (a[1] + 0xFFFFFFFFFFFFE) - t[1]
    52  	out[2] = (a[2] + 0xFFFFFFFFFFFFE) - t[2]
    53  	out[3] = (a[3] + 0xFFFFFFFFFFFFE) - t[3]
    54  	out[4] = (a[4] + 0xFFFFFFFFFFFFE) - t[4]
    55  }
    56  
    57  // FeNeg sets out = -a
    58  func FeNeg(out, a *FieldElement) {
    59  	var t FieldElement
    60  	FeZero(&t)
    61  	FeSub(out, &t, a)
    62  }
    63  
    64  //go:noescape
    65  // FeMul calculates out = a * b.
    66  func FeMul(out, a, b *FieldElement)
    67  
    68  //go:noescape
    69  // FeSquare calculates out = a * a.
    70  func FeSquare(out, a *FieldElement)
    71  
    72  // FeSquare2 calculates out = 2 * a * a.
    73  func FeSquare2(out, a *FieldElement) {
    74  	FeSquare(out, a)
    75  	FeAdd(out, out, out)
    76  }
    77  
    78  // Replace (f,g) with (g,g) if b == 1;
    79  // replace (f,g) with (f,g) if b == 0.
    80  //
    81  // Preconditions: b in {0,1}.
    82  // it is a condition move like cmov instruction in assembly
    83  // all the 3 implementations are equal, but some are optmised
    84  /*func FeCMove(f, g *FieldElement, b int32) {
    85  	negate := (1<<64 - 1) * uint64(b)
    86  	f[0] ^= negate & (f[0] ^ g[0])
    87  	f[1] ^= negate & (f[1] ^ g[1])
    88  	f[2] ^= negate & (f[2] ^ g[2])
    89  	f[3] ^= negate & (f[3] ^ g[3])
    90  	f[4] ^= negate & (f[4] ^ g[4])
    91  }*/
    92  
    93  func FeCMove(f, g *FieldElement, b int32) {
    94  	if b == 0 { // do nothing
    95  
    96  	} else {
    97  		f[0] = g[0]
    98  		f[1] = g[1]
    99  		f[2] = g[2]
   100  		f[3] = g[3]
   101  		f[4] = g[4]
   102  	}
   103  }
   104  
   105  /*
   106  func FeCMove(f, g *FieldElement, b int32) {
   107  
   108  	var tmp [32]byte
   109  	var g32,f32 FieldElement32
   110  	g64 := FieldElement64(*g)
   111  	FeToBytes64(&tmp,&g64)
   112  
   113  	// import the field element as 32 bit
   114  	FeFromBytes32(&g32, &tmp)
   115  
   116  	f64 := FieldElement64(*f)
   117  	FeToBytes64(&tmp,&f64)
   118  
   119  	// import the field element as 32 bit
   120  	FeFromBytes32(&f32, &tmp)
   121  
   122  
   123  
   124  	b = -b
   125  	f32[0] ^= b & (f32[0] ^ g32[0])
   126  	f32[1] ^= b & (f32[1] ^ g32[1])
   127  	f32[2] ^= b & (f32[2] ^ g32[2])
   128  	f32[3] ^= b & (f32[3] ^ g32[3])
   129  	f32[4] ^= b & (f32[4] ^ g32[4])
   130  	f32[5] ^= b & (f32[5] ^ g32[5])
   131  	f32[6] ^= b & (f32[6] ^ g32[6])
   132  	f32[7] ^= b & (f32[7] ^ g32[7])
   133  	f32[8] ^= b & (f32[8] ^ g32[8])
   134  	f32[9] ^= b & (f32[9] ^ g32[9])
   135  
   136  	// convert back the result to f64
   137  	FeToBytes32(&tmp,&f32)
   138  	var x Key
   139  	copy(x[:],tmp[:])
   140  	FeFromBytes(f,&x)
   141  
   142  	FeToBytes32(&tmp,&g32)
   143  	copy(x[:],tmp[:])
   144  	FeFromBytes(g,&x)
   145  
   146  }*/
   147  
   148  func FeFromBytes(v *FieldElement, x *Key) {
   149  	v[0] = uint64(x[0])
   150  	v[0] |= uint64(x[1]) << 8
   151  	v[0] |= uint64(x[2]) << 16
   152  	v[0] |= uint64(x[3]) << 24
   153  	v[0] |= uint64(x[4]) << 32
   154  	v[0] |= uint64(x[5]) << 40
   155  	v[0] |= uint64(x[6]&7) << 48
   156  
   157  	v[1] = uint64(x[6]) >> 3
   158  	v[1] |= uint64(x[7]) << 5
   159  	v[1] |= uint64(x[8]) << 13
   160  	v[1] |= uint64(x[9]) << 21
   161  	v[1] |= uint64(x[10]) << 29
   162  	v[1] |= uint64(x[11]) << 37
   163  	v[1] |= uint64(x[12]&63) << 45
   164  
   165  	v[2] = uint64(x[12]) >> 6
   166  	v[2] |= uint64(x[13]) << 2
   167  	v[2] |= uint64(x[14]) << 10
   168  	v[2] |= uint64(x[15]) << 18
   169  	v[2] |= uint64(x[16]) << 26
   170  	v[2] |= uint64(x[17]) << 34
   171  	v[2] |= uint64(x[18]) << 42
   172  	v[2] |= uint64(x[19]&1) << 50
   173  
   174  	v[3] = uint64(x[19]) >> 1
   175  	v[3] |= uint64(x[20]) << 7
   176  	v[3] |= uint64(x[21]) << 15
   177  	v[3] |= uint64(x[22]) << 23
   178  	v[3] |= uint64(x[23]) << 31
   179  	v[3] |= uint64(x[24]) << 39
   180  	v[3] |= uint64(x[25]&15) << 47
   181  
   182  	v[4] = uint64(x[25]) >> 4
   183  	v[4] |= uint64(x[26]) << 4
   184  	v[4] |= uint64(x[27]) << 12
   185  	v[4] |= uint64(x[28]) << 20
   186  	v[4] |= uint64(x[29]) << 28
   187  	v[4] |= uint64(x[30]) << 36
   188  	v[4] |= uint64(x[31]&127) << 44
   189  }
   190  
   191  func FeToBytes(r *Key, v *FieldElement) {
   192  	var t FieldElement
   193  	feReduce(&t, v)
   194  
   195  	r[0] = byte(t[0] & 0xff)
   196  	r[1] = byte((t[0] >> 8) & 0xff)
   197  	r[2] = byte((t[0] >> 16) & 0xff)
   198  	r[3] = byte((t[0] >> 24) & 0xff)
   199  	r[4] = byte((t[0] >> 32) & 0xff)
   200  	r[5] = byte((t[0] >> 40) & 0xff)
   201  	r[6] = byte((t[0] >> 48))
   202  
   203  	r[6] ^= byte((t[1] << 3) & 0xf8)
   204  	r[7] = byte((t[1] >> 5) & 0xff)
   205  	r[8] = byte((t[1] >> 13) & 0xff)
   206  	r[9] = byte((t[1] >> 21) & 0xff)
   207  	r[10] = byte((t[1] >> 29) & 0xff)
   208  	r[11] = byte((t[1] >> 37) & 0xff)
   209  	r[12] = byte((t[1] >> 45))
   210  
   211  	r[12] ^= byte((t[2] << 6) & 0xc0)
   212  	r[13] = byte((t[2] >> 2) & 0xff)
   213  	r[14] = byte((t[2] >> 10) & 0xff)
   214  	r[15] = byte((t[2] >> 18) & 0xff)
   215  	r[16] = byte((t[2] >> 26) & 0xff)
   216  	r[17] = byte((t[2] >> 34) & 0xff)
   217  	r[18] = byte((t[2] >> 42) & 0xff)
   218  	r[19] = byte((t[2] >> 50))
   219  
   220  	r[19] ^= byte((t[3] << 1) & 0xfe)
   221  	r[20] = byte((t[3] >> 7) & 0xff)
   222  	r[21] = byte((t[3] >> 15) & 0xff)
   223  	r[22] = byte((t[3] >> 23) & 0xff)
   224  	r[23] = byte((t[3] >> 31) & 0xff)
   225  	r[24] = byte((t[3] >> 39) & 0xff)
   226  	r[25] = byte((t[3] >> 47))
   227  
   228  	r[25] ^= byte((t[4] << 4) & 0xf0)
   229  	r[26] = byte((t[4] >> 4) & 0xff)
   230  	r[27] = byte((t[4] >> 12) & 0xff)
   231  	r[28] = byte((t[4] >> 20) & 0xff)
   232  	r[29] = byte((t[4] >> 28) & 0xff)
   233  	r[30] = byte((t[4] >> 36) & 0xff)
   234  	r[31] = byte((t[4] >> 44))
   235  }
   236  
   237  func feReduce(t, v *FieldElement) {
   238  	// Copy v
   239  	*t = *v
   240  
   241  	// Let v = v[0] + v[1]*2^51 + v[2]*2^102 + v[3]*2^153 + v[4]*2^204
   242  	// Reduce each limb below 2^51, propagating carries.
   243  	t[1] += t[0] >> 51
   244  	t[0] = t[0] & maskLow51Bits
   245  	t[2] += t[1] >> 51
   246  	t[1] = t[1] & maskLow51Bits
   247  	t[3] += t[2] >> 51
   248  	t[2] = t[2] & maskLow51Bits
   249  	t[4] += t[3] >> 51
   250  	t[3] = t[3] & maskLow51Bits
   251  	t[0] += (t[4] >> 51) * 19
   252  	t[4] = t[4] & maskLow51Bits
   253  
   254  	// We now have a field element t < 2^255, but need t <= 2^255-19
   255  
   256  	// Get the carry bit
   257  	c := (t[0] + 19) >> 51
   258  	c = (t[1] + c) >> 51
   259  	c = (t[2] + c) >> 51
   260  	c = (t[3] + c) >> 51
   261  	c = (t[4] + c) >> 51
   262  
   263  	t[0] += 19 * c
   264  
   265  	t[1] += t[0] >> 51
   266  	t[0] = t[0] & maskLow51Bits
   267  	t[2] += t[1] >> 51
   268  	t[1] = t[1] & maskLow51Bits
   269  	t[3] += t[2] >> 51
   270  	t[2] = t[2] & maskLow51Bits
   271  	t[4] += t[3] >> 51
   272  	t[3] = t[3] & maskLow51Bits
   273  	// no additional carry
   274  	t[4] = t[4] & maskLow51Bits
   275  }