github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/edwards_general.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 // Copyright 2013 The Go Authors. All rights reserved. 18 // Use of this source code is governed by a BSD-style 19 // license that can be found in the LICENSE-BSD file. 20 21 // Most of this is from the golang x/crypto package 22 23 // Package edwards25519 implements operations in GF(2**255-19) and on an 24 // Edwards curve that is isomorphic to curve25519. See 25 // http://ed25519.cr.yp.to/. 26 27 // +build !amd64 28 29 package crypto 30 31 // This code is a port of the public domain, "ref10" implementation of ed25519 32 // from SUPERCOP. 33 34 // FieldElement represents an element of the field GF(2^255 - 19). An element 35 // t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 36 // t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on 37 // context. 38 type FieldElement [10]int32 39 40 var FeMa = FieldElement{-486662, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* -A */ 41 var FeMa2 = FieldElement{-12721188, -3529, 0, 0, 0, 0, 0, 0, 0, 0} /* -A^2 */ 42 var FeFffb1 = FieldElement{-31702527, -2466483, -26106795, -12203692, -12169197, -321052, 14850977, -10296299, -16929438, -407568} /* sqrt(-2 * A * (A + 2)) */ 43 var FeFffb2 = FieldElement{8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080} /* sqrt(2 * A * (A + 2)) */ 44 var FeFffb3 = FieldElement{-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756} /* sqrt(-sqrt(-1) * A * (A + 2)) */ 45 var FeFffb4 = FieldElement{-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324} /* sqrt(sqrt(-1) * A * (A + 2)) */ 46 var FeSqrtM1 = FieldElement{-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482} /* sqrt(-1) */ 47 48 var one FieldElement 49 50 func init() { 51 one[0] = 1 52 } 53 54 func (f *FieldElement) Zero() { 55 copy(f[:], zero[:]) 56 } 57 58 func (f *FieldElement) One() { 59 copy(f[:], one[:]) 60 } 61 62 func FeAdd(dst, a, b *FieldElement) { 63 dst[0] = a[0] + b[0] 64 dst[1] = a[1] + b[1] 65 dst[2] = a[2] + b[2] 66 dst[3] = a[3] + b[3] 67 dst[4] = a[4] + b[4] 68 dst[5] = a[5] + b[5] 69 dst[6] = a[6] + b[6] 70 dst[7] = a[7] + b[7] 71 dst[8] = a[8] + b[8] 72 dst[9] = a[9] + b[9] 73 } 74 75 func FeSub(dst, a, b *FieldElement) { 76 dst[0] = a[0] - b[0] 77 dst[1] = a[1] - b[1] 78 dst[2] = a[2] - b[2] 79 dst[3] = a[3] - b[3] 80 dst[4] = a[4] - b[4] 81 dst[5] = a[5] - b[5] 82 dst[6] = a[6] - b[6] 83 dst[7] = a[7] - b[7] 84 dst[8] = a[8] - b[8] 85 dst[9] = a[9] - b[9] 86 } 87 88 // Replace (f,g) with (g,g) if b == 1; 89 // replace (f,g) with (f,g) if b == 0. 90 // 91 // Preconditions: b in {0,1}. 92 func FeCMove(f, g *FieldElement, b int32) { 93 b = -b 94 f[0] ^= b & (f[0] ^ g[0]) 95 f[1] ^= b & (f[1] ^ g[1]) 96 f[2] ^= b & (f[2] ^ g[2]) 97 f[3] ^= b & (f[3] ^ g[3]) 98 f[4] ^= b & (f[4] ^ g[4]) 99 f[5] ^= b & (f[5] ^ g[5]) 100 f[6] ^= b & (f[6] ^ g[6]) 101 f[7] ^= b & (f[7] ^ g[7]) 102 f[8] ^= b & (f[8] ^ g[8]) 103 f[9] ^= b & (f[9] ^ g[9]) 104 } 105 106 func FeFromBytes(dst *FieldElement, src *Key) { 107 h0 := load4(src[:]) 108 h1 := load3(src[4:]) << 6 109 h2 := load3(src[7:]) << 5 110 h3 := load3(src[10:]) << 3 111 h4 := load3(src[13:]) << 2 112 h5 := load4(src[16:]) 113 h6 := load3(src[20:]) << 7 114 h7 := load3(src[23:]) << 5 115 h8 := load3(src[26:]) << 4 116 h9 := (load3(src[29:]) & 8388607) << 2 117 118 FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) 119 } 120 121 // FeToBytes marshals h to s. 122 // Preconditions: 123 // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 124 // 125 // Write p=2^255-19; q=floor(h/p). 126 // Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 127 // 128 // Proof: 129 // Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 130 // Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. 131 // 132 // Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 133 // Then 0<y<1. 134 // 135 // Write r=h-pq. 136 // Have 0<=r<=p-1=2^255-20. 137 // Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1. 138 // 139 // Write x=r+19(2^-255)r+y. 140 // Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q. 141 // 142 // Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1)) 143 // so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q. 144 func FeToBytes(s *Key, h *FieldElement) { 145 var carry [10]int32 146 147 q := (19*h[9] + (1 << 24)) >> 25 148 q = (h[0] + q) >> 26 149 q = (h[1] + q) >> 25 150 q = (h[2] + q) >> 26 151 q = (h[3] + q) >> 25 152 q = (h[4] + q) >> 26 153 q = (h[5] + q) >> 25 154 q = (h[6] + q) >> 26 155 q = (h[7] + q) >> 25 156 q = (h[8] + q) >> 26 157 q = (h[9] + q) >> 25 158 159 // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. 160 h[0] += 19 * q 161 // Goal: Output h-2^255 q, which is between 0 and 2^255-20. 162 163 carry[0] = h[0] >> 26 164 h[1] += carry[0] 165 h[0] -= carry[0] << 26 166 carry[1] = h[1] >> 25 167 h[2] += carry[1] 168 h[1] -= carry[1] << 25 169 carry[2] = h[2] >> 26 170 h[3] += carry[2] 171 h[2] -= carry[2] << 26 172 carry[3] = h[3] >> 25 173 h[4] += carry[3] 174 h[3] -= carry[3] << 25 175 carry[4] = h[4] >> 26 176 h[5] += carry[4] 177 h[4] -= carry[4] << 26 178 carry[5] = h[5] >> 25 179 h[6] += carry[5] 180 h[5] -= carry[5] << 25 181 carry[6] = h[6] >> 26 182 h[7] += carry[6] 183 h[6] -= carry[6] << 26 184 carry[7] = h[7] >> 25 185 h[8] += carry[7] 186 h[7] -= carry[7] << 25 187 carry[8] = h[8] >> 26 188 h[9] += carry[8] 189 h[8] -= carry[8] << 26 190 carry[9] = h[9] >> 25 191 h[9] -= carry[9] << 25 192 // h10 = carry9 193 194 // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 195 // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; 196 // evidently 2^255 h10-2^255 q = 0. 197 // Goal: Output h[0]+...+2^230 h[9]. 198 199 s[0] = byte(h[0] >> 0) 200 s[1] = byte(h[0] >> 8) 201 s[2] = byte(h[0] >> 16) 202 s[3] = byte((h[0] >> 24) | (h[1] << 2)) 203 s[4] = byte(h[1] >> 6) 204 s[5] = byte(h[1] >> 14) 205 s[6] = byte((h[1] >> 22) | (h[2] << 3)) 206 s[7] = byte(h[2] >> 5) 207 s[8] = byte(h[2] >> 13) 208 s[9] = byte((h[2] >> 21) | (h[3] << 5)) 209 s[10] = byte(h[3] >> 3) 210 s[11] = byte(h[3] >> 11) 211 s[12] = byte((h[3] >> 19) | (h[4] << 6)) 212 s[13] = byte(h[4] >> 2) 213 s[14] = byte(h[4] >> 10) 214 s[15] = byte(h[4] >> 18) 215 s[16] = byte(h[5] >> 0) 216 s[17] = byte(h[5] >> 8) 217 s[18] = byte(h[5] >> 16) 218 s[19] = byte((h[5] >> 24) | (h[6] << 1)) 219 s[20] = byte(h[6] >> 7) 220 s[21] = byte(h[6] >> 15) 221 s[22] = byte((h[6] >> 23) | (h[7] << 3)) 222 s[23] = byte(h[7] >> 5) 223 s[24] = byte(h[7] >> 13) 224 s[25] = byte((h[7] >> 21) | (h[8] << 4)) 225 s[26] = byte(h[8] >> 4) 226 s[27] = byte(h[8] >> 12) 227 s[28] = byte((h[8] >> 20) | (h[9] << 6)) 228 s[29] = byte(h[9] >> 2) 229 s[30] = byte(h[9] >> 10) 230 s[31] = byte(h[9] >> 18) 231 } 232 233 func (f *FieldElement) IsNegative() byte { 234 var s Key 235 FeToBytes(&s, f) 236 return s[0] & 1 237 } 238 239 func (f *FieldElement) IsNonZero() int32 { 240 var s Key 241 FeToBytes(&s, f) 242 var x uint8 243 for _, b := range s { 244 x |= b 245 } 246 x |= x >> 4 247 x |= x >> 2 248 x |= x >> 1 249 return int32(x & 1) 250 } 251 252 // FeNeg sets h = -f 253 // 254 // Preconditions: 255 // |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 256 // 257 // Postconditions: 258 // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 259 func FeNeg(h, f *FieldElement) { 260 h[0] = -f[0] 261 h[1] = -f[1] 262 h[2] = -f[2] 263 h[3] = -f[3] 264 h[4] = -f[4] 265 h[5] = -f[5] 266 h[6] = -f[6] 267 h[7] = -f[7] 268 h[8] = -f[8] 269 h[9] = -f[9] 270 } 271 272 func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { 273 var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 274 275 /* 276 |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) 277 i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 278 |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) 279 i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 280 */ 281 282 c0 = (h0 + (1 << 25)) >> 26 283 h1 += c0 284 h0 -= c0 << 26 285 c4 = (h4 + (1 << 25)) >> 26 286 h5 += c4 287 h4 -= c4 << 26 288 /* |h0| <= 2^25 */ 289 /* |h4| <= 2^25 */ 290 /* |h1| <= 1.51*2^58 */ 291 /* |h5| <= 1.51*2^58 */ 292 293 c1 = (h1 + (1 << 24)) >> 25 294 h2 += c1 295 h1 -= c1 << 25 296 c5 = (h5 + (1 << 24)) >> 25 297 h6 += c5 298 h5 -= c5 << 25 299 /* |h1| <= 2^24; from now on fits into int32 */ 300 /* |h5| <= 2^24; from now on fits into int32 */ 301 /* |h2| <= 1.21*2^59 */ 302 /* |h6| <= 1.21*2^59 */ 303 304 c2 = (h2 + (1 << 25)) >> 26 305 h3 += c2 306 h2 -= c2 << 26 307 c6 = (h6 + (1 << 25)) >> 26 308 h7 += c6 309 h6 -= c6 << 26 310 /* |h2| <= 2^25; from now on fits into int32 unchanged */ 311 /* |h6| <= 2^25; from now on fits into int32 unchanged */ 312 /* |h3| <= 1.51*2^58 */ 313 /* |h7| <= 1.51*2^58 */ 314 315 c3 = (h3 + (1 << 24)) >> 25 316 h4 += c3 317 h3 -= c3 << 25 318 c7 = (h7 + (1 << 24)) >> 25 319 h8 += c7 320 h7 -= c7 << 25 321 /* |h3| <= 2^24; from now on fits into int32 unchanged */ 322 /* |h7| <= 2^24; from now on fits into int32 unchanged */ 323 /* |h4| <= 1.52*2^33 */ 324 /* |h8| <= 1.52*2^33 */ 325 326 c4 = (h4 + (1 << 25)) >> 26 327 h5 += c4 328 h4 -= c4 << 26 329 c8 = (h8 + (1 << 25)) >> 26 330 h9 += c8 331 h8 -= c8 << 26 332 /* |h4| <= 2^25; from now on fits into int32 unchanged */ 333 /* |h8| <= 2^25; from now on fits into int32 unchanged */ 334 /* |h5| <= 1.01*2^24 */ 335 /* |h9| <= 1.51*2^58 */ 336 337 c9 = (h9 + (1 << 24)) >> 25 338 h0 += c9 * 19 339 h9 -= c9 << 25 340 /* |h9| <= 2^24; from now on fits into int32 unchanged */ 341 /* |h0| <= 1.8*2^37 */ 342 343 c0 = (h0 + (1 << 25)) >> 26 344 h1 += c0 345 h0 -= c0 << 26 346 /* |h0| <= 2^25; from now on fits into int32 unchanged */ 347 /* |h1| <= 1.01*2^24 */ 348 349 h[0] = int32(h0) 350 h[1] = int32(h1) 351 h[2] = int32(h2) 352 h[3] = int32(h3) 353 h[4] = int32(h4) 354 h[5] = int32(h5) 355 h[6] = int32(h6) 356 h[7] = int32(h7) 357 h[8] = int32(h8) 358 h[9] = int32(h9) 359 } 360 361 // FeMul calculates h = f * g 362 // Can overlap h with f or g. 363 // 364 // Preconditions: 365 // |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 366 // |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 367 // 368 // Postconditions: 369 // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 370 // 371 // Notes on implementation strategy: 372 // 373 // Using schoolbook multiplication. 374 // Karatsuba would save a little in some cost models. 375 // 376 // Most multiplications by 2 and 19 are 32-bit precomputations; 377 // cheaper than 64-bit postcomputations. 378 // 379 // There is one remaining multiplication by 19 in the carry chain; 380 // one *19 precomputation can be merged into this, 381 // but the resulting data flow is considerably less clean. 382 // 383 // There are 12 carries below. 384 // 10 of them are 2-way parallelizable and vectorizable. 385 // Can get away with 11 carries, but then data flow is much deeper. 386 // 387 // With tighter constraints on inputs can squeeze carries into int32. 388 func FeMul(h, f, g *FieldElement) { 389 f0 := int64(f[0]) 390 f1 := int64(f[1]) 391 f2 := int64(f[2]) 392 f3 := int64(f[3]) 393 f4 := int64(f[4]) 394 f5 := int64(f[5]) 395 f6 := int64(f[6]) 396 f7 := int64(f[7]) 397 f8 := int64(f[8]) 398 f9 := int64(f[9]) 399 400 f1_2 := int64(2 * f[1]) 401 f3_2 := int64(2 * f[3]) 402 f5_2 := int64(2 * f[5]) 403 f7_2 := int64(2 * f[7]) 404 f9_2 := int64(2 * f[9]) 405 406 g0 := int64(g[0]) 407 g1 := int64(g[1]) 408 g2 := int64(g[2]) 409 g3 := int64(g[3]) 410 g4 := int64(g[4]) 411 g5 := int64(g[5]) 412 g6 := int64(g[6]) 413 g7 := int64(g[7]) 414 g8 := int64(g[8]) 415 g9 := int64(g[9]) 416 417 g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ 418 g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ 419 g3_19 := int64(19 * g[3]) 420 g4_19 := int64(19 * g[4]) 421 g5_19 := int64(19 * g[5]) 422 g6_19 := int64(19 * g[6]) 423 g7_19 := int64(19 * g[7]) 424 g8_19 := int64(19 * g[8]) 425 g9_19 := int64(19 * g[9]) 426 427 h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 428 h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 429 h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 430 h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 431 h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 432 h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 433 h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 434 h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 435 h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 436 h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 437 438 FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) 439 } 440 441 func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { 442 f0 := int64(f[0]) 443 f1 := int64(f[1]) 444 f2 := int64(f[2]) 445 f3 := int64(f[3]) 446 f4 := int64(f[4]) 447 f5 := int64(f[5]) 448 f6 := int64(f[6]) 449 f7 := int64(f[7]) 450 f8 := int64(f[8]) 451 f9 := int64(f[9]) 452 f0_2 := int64(2 * f[0]) 453 f1_2 := int64(2 * f[1]) 454 f2_2 := int64(2 * f[2]) 455 f3_2 := int64(2 * f[3]) 456 f4_2 := int64(2 * f[4]) 457 f5_2 := int64(2 * f[5]) 458 f6_2 := int64(2 * f[6]) 459 f7_2 := int64(2 * f[7]) 460 f5_38 := 38 * f5 // 1.31*2^30 461 f6_19 := 19 * f6 // 1.31*2^30 462 f7_38 := 38 * f7 // 1.31*2^30 463 f8_19 := 19 * f8 // 1.31*2^30 464 f9_38 := 38 * f9 // 1.31*2^30 465 466 h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 467 h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 468 h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 469 h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 470 h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 471 h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 472 h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 473 h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 474 h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 475 h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 476 477 return 478 } 479 480 // FeSquare calculates h = f*f. Can overlap h with f. 481 // 482 // Preconditions: 483 // |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 484 // 485 // Postconditions: 486 // |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 487 func FeSquare(h, f *FieldElement) { 488 h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) 489 FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) 490 } 491 492 // FeSquare2 sets h = 2 * f * f 493 // 494 // Can overlap h with f. 495 // 496 // Preconditions: 497 // |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 498 // 499 // Postconditions: 500 // |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 501 // See fe_mul.c for discussion of implementation strategy. 502 func FeSquare2(h, f *FieldElement) { 503 h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) 504 505 h0 += h0 506 h1 += h1 507 h2 += h2 508 h3 += h3 509 h4 += h4 510 h5 += h5 511 h6 += h6 512 h7 += h7 513 h8 += h8 514 h9 += h9 515 516 FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) 517 }