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 }