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  }