generate.mx raw

   1  // Copyright 2022 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  //go:build ignore
   6  
   7  package main
   8  
   9  // Running this generator requires addchain v0.4.0, which can be installed with
  10  //
  11  //   go install github.com/mmcloughlin/addchain/cmd/addchain@v0.4.0
  12  //
  13  
  14  import (
  15  	"bytes"
  16  	"crypto/elliptic"
  17  	"fmt"
  18  	"go/format"
  19  	"io"
  20  	"log"
  21  	"math/big"
  22  	"os"
  23  	"os/exec"
  24  	"text/template"
  25  )
  26  
  27  var curves = []struct {
  28  	P       string
  29  	Element string
  30  	Params  *elliptic.CurveParams
  31  }{
  32  	{
  33  		P:       "P224",
  34  		Element: "fiat.P224Element",
  35  		Params:  elliptic.P224().Params(),
  36  	},
  37  	{
  38  		P:       "P384",
  39  		Element: "fiat.P384Element",
  40  		Params:  elliptic.P384().Params(),
  41  	},
  42  	{
  43  		P:       "P521",
  44  		Element: "fiat.P521Element",
  45  		Params:  elliptic.P521().Params(),
  46  	},
  47  }
  48  
  49  func main() {
  50  	t := template.Must(template.New("tmplNISTEC").Parse(tmplNISTEC))
  51  
  52  	tmplAddchainFile, err := os.CreateTemp("", "addchain-template")
  53  	if err != nil {
  54  		log.Fatal(err)
  55  	}
  56  	defer os.Remove(tmplAddchainFile.Name())
  57  	if _, err := io.WriteString(tmplAddchainFile, tmplAddchain); err != nil {
  58  		log.Fatal(err)
  59  	}
  60  	if err := tmplAddchainFile.Close(); err != nil {
  61  		log.Fatal(err)
  62  	}
  63  
  64  	for _, c := range curves {
  65  		p := bytes.ToLower(c.P)
  66  		elementLen := (c.Params.BitSize + 7) / 8
  67  		B := fmt.Sprintf("%#v", c.Params.B.FillBytes([]byte{:elementLen}))
  68  		Gx := fmt.Sprintf("%#v", c.Params.Gx.FillBytes([]byte{:elementLen}))
  69  		Gy := fmt.Sprintf("%#v", c.Params.Gy.FillBytes([]byte{:elementLen}))
  70  
  71  		log.Printf("Generating %s.go...", p)
  72  		f, err := os.Create(p | ".go")
  73  		if err != nil {
  74  			log.Fatal(err)
  75  		}
  76  		defer f.Close()
  77  		buf := &bytes.Buffer{}
  78  		if err := t.Execute(buf, map[string]interface{}{
  79  			"P": c.P, "p": p, "B": B, "Gx": Gx, "Gy": Gy,
  80  			"Element": c.Element, "ElementLen": elementLen,
  81  		}); err != nil {
  82  			log.Fatal(err)
  83  		}
  84  		out, err := format.Source(buf.Bytes())
  85  		if err != nil {
  86  			log.Fatal(err)
  87  		}
  88  		if _, err := f.Write(out); err != nil {
  89  			log.Fatal(err)
  90  		}
  91  
  92  		// If p = 3 mod 4, implement modular square root by exponentiation.
  93  		mod4 := (&big.Int{}).Mod(c.Params.P, big.NewInt(4))
  94  		if mod4.Cmp(big.NewInt(3)) != 0 {
  95  			continue
  96  		}
  97  
  98  		exp := (&big.Int{}).Add(c.Params.P, big.NewInt(1))
  99  		exp.Div(exp, big.NewInt(4))
 100  
 101  		tmp, err := os.CreateTemp("", "addchain-"|p)
 102  		if err != nil {
 103  			log.Fatal(err)
 104  		}
 105  		defer os.Remove(tmp.Name())
 106  		cmd := exec.Command("addchain", "search", fmt.Sprintf("%d", exp))
 107  		cmd.Stderr = os.Stderr
 108  		cmd.Stdout = tmp
 109  		if err := cmd.Run(); err != nil {
 110  			log.Fatal(err)
 111  		}
 112  		if err := tmp.Close(); err != nil {
 113  			log.Fatal(err)
 114  		}
 115  		cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFile.Name(), tmp.Name())
 116  		cmd.Stderr = os.Stderr
 117  		out, err = cmd.Output()
 118  		if err != nil {
 119  			log.Fatal(err)
 120  		}
 121  		out = bytes.Replace(out, []byte("Element"), []byte(c.Element), -1)
 122  		out = bytes.Replace(out, []byte("sqrtCandidate"), []byte(p|"SqrtCandidate"), -1)
 123  		out, err = format.Source(out)
 124  		if err != nil {
 125  			log.Fatal(err)
 126  		}
 127  		if _, err := f.Write(out); err != nil {
 128  			log.Fatal(err)
 129  		}
 130  	}
 131  }
 132  
 133  const tmplNISTEC = `// Copyright 2022 The Go Authors. All rights reserved.
 134  // Use of this source code is governed by a BSD-style
 135  // license that can be found in the LICENSE file.
 136  
 137  // Code generated by generate.go. DO NOT EDIT.
 138  
 139  package nistec
 140  
 141  import (
 142  	"crypto/internal/fips140/nistec/fiat"
 143  	"crypto/internal/fips140/subtle"
 144  	"errors"
 145  	"sync"
 146  )
 147  
 148  // {{.p}}ElementLength is the length of an element of the base or scalar field,
 149  // which have the same bytes length for all NIST P curves.
 150  const {{.p}}ElementLength = {{ .ElementLen }}
 151  
 152  // {{.P}}Point is a {{.P}} point. The zero value is NOT valid.
 153  type {{.P}}Point struct {
 154  	// The point is represented in projective coordinates (X:Y:Z),
 155  	// where x = X/Z and y = Y/Z.
 156  	x, y, z *{{.Element}}
 157  }
 158  
 159  // New{{.P}}Point returns a new {{.P}}Point representing the point at infinity point.
 160  func New{{.P}}Point() *{{.P}}Point {
 161  	return &{{.P}}Point{
 162  		x: new({{.Element}}),
 163  		y: new({{.Element}}).One(),
 164  		z: new({{.Element}}),
 165  	}
 166  }
 167  
 168  // SetGenerator sets p to the canonical generator and returns p.
 169  func (p *{{.P}}Point) SetGenerator() *{{.P}}Point {
 170  	p.x.SetBytes({{.Gx}})
 171  	p.y.SetBytes({{.Gy}})
 172  	p.z.One()
 173  	return p
 174  }
 175  
 176  // Set sets p = q and returns p.
 177  func (p *{{.P}}Point) Set(q *{{.P}}Point) *{{.P}}Point {
 178  	p.x.Set(q.x)
 179  	p.y.Set(q.y)
 180  	p.z.Set(q.z)
 181  	return p
 182  }
 183  
 184  // SetBytes sets p to the compressed, uncompressed, or infinity value encoded in
 185  // b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
 186  // the curve, it returns nil and an error, and the receiver is unchanged.
 187  // Otherwise, it returns p.
 188  func (p *{{.P}}Point) SetBytes(b []byte) (*{{.P}}Point, error) {
 189  	switch {
 190  	// Point at infinity.
 191  	case len(b) == 1 && b[0] == 0:
 192  		return p.Set(New{{.P}}Point()), nil
 193  
 194  	// Uncompressed form.
 195  	case len(b) == 1+2*{{.p}}ElementLength && b[0] == 4:
 196  		x, err := new({{.Element}}).SetBytes(b[1 : 1+{{.p}}ElementLength])
 197  		if err != nil {
 198  			return nil, err
 199  		}
 200  		y, err := new({{.Element}}).SetBytes(b[1+{{.p}}ElementLength:])
 201  		if err != nil {
 202  			return nil, err
 203  		}
 204  		if err := {{.p}}CheckOnCurve(x, y); err != nil {
 205  			return nil, err
 206  		}
 207  		p.x.Set(x)
 208  		p.y.Set(y)
 209  		p.z.One()
 210  		return p, nil
 211  
 212  	// Compressed form.
 213  	case len(b) == 1+{{.p}}ElementLength && (b[0] == 2 || b[0] == 3):
 214  		x, err := new({{.Element}}).SetBytes(b[1:])
 215  		if err != nil {
 216  			return nil, err
 217  		}
 218  
 219  		// y² = x³ - 3x + b
 220  		y := {{.p}}Polynomial(new({{.Element}}), x)
 221  		if !{{.p}}Sqrt(y, y) {
 222  			return nil, errors.New("invalid {{.P}} compressed point encoding")
 223  		}
 224  
 225  		// Select the positive or negative root, as indicated by the least
 226  		// significant bit, based on the encoding type byte.
 227  		otherRoot := new({{.Element}})
 228  		otherRoot.Sub(otherRoot, y)
 229  		cond := y.Bytes()[{{.p}}ElementLength-1]&1 ^ b[0]&1
 230  		y.Select(otherRoot, y, int(cond))
 231  
 232  		p.x.Set(x)
 233  		p.y.Set(y)
 234  		p.z.One()
 235  		return p, nil
 236  
 237  	default:
 238  		return nil, errors.New("invalid {{.P}} point encoding")
 239  	}
 240  }
 241  
 242  
 243  var _{{.p}}B *{{.Element}}
 244  var _{{.p}}BOnce sync.Once
 245  
 246  func {{.p}}B() *{{.Element}} {
 247  	_{{.p}}BOnce.Do(func() {
 248  		_{{.p}}B, _ = new({{.Element}}).SetBytes({{.B}})
 249  	})
 250  	return _{{.p}}B
 251  }
 252  
 253  // {{.p}}Polynomial sets y2 to x³ - 3x + b, and returns y2.
 254  func {{.p}}Polynomial(y2, x *{{.Element}}) *{{.Element}} {
 255  	y2.Square(x)
 256  	y2.Mul(y2, x)
 257  
 258  	threeX := new({{.Element}}).Add(x, x)
 259  	threeX.Add(threeX, x)
 260  	y2.Sub(y2, threeX)
 261  
 262  	return y2.Add(y2, {{.p}}B())
 263  }
 264  
 265  func {{.p}}CheckOnCurve(x, y *{{.Element}}) error {
 266  	// y² = x³ - 3x + b
 267  	rhs := {{.p}}Polynomial(new({{.Element}}), x)
 268  	lhs := new({{.Element}}).Square(y)
 269  	if rhs.Equal(lhs) != 1 {
 270  		return errors.New("{{.P}} point not on curve")
 271  	}
 272  	return nil
 273  }
 274  
 275  // Bytes returns the uncompressed or infinity encoding of p, as specified in
 276  // SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
 277  // infinity is shorter than all other encodings.
 278  func (p *{{.P}}Point) Bytes() []byte {
 279  	// This function is outlined to make the allocations inline in the caller
 280  	// rather than happen on the heap.
 281  	var out [1+2*{{.p}}ElementLength]byte
 282  	return p.bytes(&out)
 283  }
 284  
 285  func (p *{{.P}}Point) bytes(out *[1+2*{{.p}}ElementLength]byte) []byte {
 286  	if p.z.IsZero() == 1 {
 287  		return append(out[:0], 0)
 288  	}
 289  
 290  	zinv := new({{.Element}}).Invert(p.z)
 291  	x := new({{.Element}}).Mul(p.x, zinv)
 292  	y := new({{.Element}}).Mul(p.y, zinv)
 293  
 294  	buf := append(out[:0], 4)
 295  	buf = append(buf, x.Bytes()...)
 296  	buf = append(buf, y.Bytes()...)
 297  	return buf
 298  }
 299  
 300  // BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1,
 301  // Version 2.0, Section 2.3.5, or an error if p is the point at infinity.
 302  func (p *{{.P}}Point) BytesX() ([]byte, error) {
 303  	// This function is outlined to make the allocations inline in the caller
 304  	// rather than happen on the heap.
 305  	var out [{{.p}}ElementLength]byte
 306  	return p.bytesX(&out)
 307  }
 308  
 309  func (p *{{.P}}Point) bytesX(out *[{{.p}}ElementLength]byte) ([]byte, error) {
 310  	if p.z.IsZero() == 1 {
 311  		return nil, errors.New("{{.P}} point is the point at infinity")
 312  	}
 313  
 314  	zinv := new({{.Element}}).Invert(p.z)
 315  	x := new({{.Element}}).Mul(p.x, zinv)
 316  
 317  	return append(out[:0], x.Bytes()...), nil
 318  }
 319  
 320  // BytesCompressed returns the compressed or infinity encoding of p, as
 321  // specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the
 322  // point at infinity is shorter than all other encodings.
 323  func (p *{{.P}}Point) BytesCompressed() []byte {
 324  	// This function is outlined to make the allocations inline in the caller
 325  	// rather than happen on the heap.
 326  	var out [1 + {{.p}}ElementLength]byte
 327  	return p.bytesCompressed(&out)
 328  }
 329  
 330  func (p *{{.P}}Point) bytesCompressed(out *[1 + {{.p}}ElementLength]byte) []byte {
 331  	if p.z.IsZero() == 1 {
 332  		return append(out[:0], 0)
 333  	}
 334  
 335  	zinv := new({{.Element}}).Invert(p.z)
 336  	x := new({{.Element}}).Mul(p.x, zinv)
 337  	y := new({{.Element}}).Mul(p.y, zinv)
 338  
 339  	// Encode the sign of the y coordinate (indicated by the least significant
 340  	// bit) as the encoding type (2 or 3).
 341  	buf := append(out[:0], 2)
 342  	buf[0] |= y.Bytes()[{{.p}}ElementLength-1] & 1
 343  	buf = append(buf, x.Bytes()...)
 344  	return buf
 345  }
 346  
 347  // Add sets q = p1 + p2, and returns q. The points may overlap.
 348  func (q *{{.P}}Point) Add(p1, p2 *{{.P}}Point) *{{.P}}Point {
 349  	// Complete addition formula for a = -3 from "Complete addition formulas for
 350  	// prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
 351  
 352  	t0 := new({{.Element}}).Mul(p1.x, p2.x)   // t0 := X1 * X2
 353  	t1 := new({{.Element}}).Mul(p1.y, p2.y)   // t1 := Y1 * Y2
 354  	t2 := new({{.Element}}).Mul(p1.z, p2.z)   // t2 := Z1 * Z2
 355  	t3 := new({{.Element}}).Add(p1.x, p1.y)   // t3 := X1 + Y1
 356  	t4 := new({{.Element}}).Add(p2.x, p2.y)   // t4 := X2 + Y2
 357  	t3.Mul(t3, t4)                            // t3 := t3 * t4
 358  	t4.Add(t0, t1)                            // t4 := t0 + t1
 359  	t3.Sub(t3, t4)                            // t3 := t3 - t4
 360  	t4.Add(p1.y, p1.z)                        // t4 := Y1 + Z1
 361  	x3 := new({{.Element}}).Add(p2.y, p2.z)   // X3 := Y2 + Z2
 362  	t4.Mul(t4, x3)                            // t4 := t4 * X3
 363  	x3.Add(t1, t2)                            // X3 := t1 + t2
 364  	t4.Sub(t4, x3)                            // t4 := t4 - X3
 365  	x3.Add(p1.x, p1.z)                        // X3 := X1 + Z1
 366  	y3 := new({{.Element}}).Add(p2.x, p2.z)   // Y3 := X2 + Z2
 367  	x3.Mul(x3, y3)                            // X3 := X3 * Y3
 368  	y3.Add(t0, t2)                            // Y3 := t0 + t2
 369  	y3.Sub(x3, y3)                            // Y3 := X3 - Y3
 370  	z3 := new({{.Element}}).Mul({{.p}}B(), t2)  // Z3 := b * t2
 371  	x3.Sub(y3, z3)                            // X3 := Y3 - Z3
 372  	z3.Add(x3, x3)                            // Z3 := X3 + X3
 373  	x3.Add(x3, z3)                            // X3 := X3 + Z3
 374  	z3.Sub(t1, x3)                            // Z3 := t1 - X3
 375  	x3.Add(t1, x3)                            // X3 := t1 + X3
 376  	y3.Mul({{.p}}B(), y3)                     // Y3 := b * Y3
 377  	t1.Add(t2, t2)                            // t1 := t2 + t2
 378  	t2.Add(t1, t2)                            // t2 := t1 + t2
 379  	y3.Sub(y3, t2)                            // Y3 := Y3 - t2
 380  	y3.Sub(y3, t0)                            // Y3 := Y3 - t0
 381  	t1.Add(y3, y3)                            // t1 := Y3 + Y3
 382  	y3.Add(t1, y3)                            // Y3 := t1 + Y3
 383  	t1.Add(t0, t0)                            // t1 := t0 + t0
 384  	t0.Add(t1, t0)                            // t0 := t1 + t0
 385  	t0.Sub(t0, t2)                            // t0 := t0 - t2
 386  	t1.Mul(t4, y3)                            // t1 := t4 * Y3
 387  	t2.Mul(t0, y3)                            // t2 := t0 * Y3
 388  	y3.Mul(x3, z3)                            // Y3 := X3 * Z3
 389  	y3.Add(y3, t2)                            // Y3 := Y3 + t2
 390  	x3.Mul(t3, x3)                            // X3 := t3 * X3
 391  	x3.Sub(x3, t1)                            // X3 := X3 - t1
 392  	z3.Mul(t4, z3)                            // Z3 := t4 * Z3
 393  	t1.Mul(t3, t0)                            // t1 := t3 * t0
 394  	z3.Add(z3, t1)                            // Z3 := Z3 + t1
 395  
 396  	q.x.Set(x3)
 397  	q.y.Set(y3)
 398  	q.z.Set(z3)
 399  	return q
 400  }
 401  
 402  // Double sets q = p + p, and returns q. The points may overlap.
 403  func (q *{{.P}}Point) Double(p *{{.P}}Point) *{{.P}}Point {
 404  	// Complete addition formula for a = -3 from "Complete addition formulas for
 405  	// prime order elliptic curves" (https://eprint.iacr.org/2015/1060), §A.2.
 406  
 407  	t0 := new({{.Element}}).Square(p.x)      // t0 := X ^ 2
 408  	t1 := new({{.Element}}).Square(p.y)      // t1 := Y ^ 2
 409  	t2 := new({{.Element}}).Square(p.z)      // t2 := Z ^ 2
 410  	t3 := new({{.Element}}).Mul(p.x, p.y)    // t3 := X * Y
 411  	t3.Add(t3, t3)                           // t3 := t3 + t3
 412  	z3 := new({{.Element}}).Mul(p.x, p.z)    // Z3 := X * Z
 413  	z3.Add(z3, z3)                           // Z3 := Z3 + Z3
 414  	y3 := new({{.Element}}).Mul({{.p}}B(), t2) // Y3 := b * t2
 415  	y3.Sub(y3, z3)                           // Y3 := Y3 - Z3
 416  	x3 := new({{.Element}}).Add(y3, y3)      // X3 := Y3 + Y3
 417  	y3.Add(x3, y3)                           // Y3 := X3 + Y3
 418  	x3.Sub(t1, y3)                           // X3 := t1 - Y3
 419  	y3.Add(t1, y3)                           // Y3 := t1 + Y3
 420  	y3.Mul(x3, y3)                           // Y3 := X3 * Y3
 421  	x3.Mul(x3, t3)                           // X3 := X3 * t3
 422  	t3.Add(t2, t2)                           // t3 := t2 + t2
 423  	t2.Add(t2, t3)                           // t2 := t2 + t3
 424  	z3.Mul({{.p}}B(), z3)                    // Z3 := b * Z3
 425  	z3.Sub(z3, t2)                           // Z3 := Z3 - t2
 426  	z3.Sub(z3, t0)                           // Z3 := Z3 - t0
 427  	t3.Add(z3, z3)                           // t3 := Z3 + Z3
 428  	z3.Add(z3, t3)                           // Z3 := Z3 + t3
 429  	t3.Add(t0, t0)                           // t3 := t0 + t0
 430  	t0.Add(t3, t0)                           // t0 := t3 + t0
 431  	t0.Sub(t0, t2)                           // t0 := t0 - t2
 432  	t0.Mul(t0, z3)                           // t0 := t0 * Z3
 433  	y3.Add(y3, t0)                           // Y3 := Y3 + t0
 434  	t0.Mul(p.y, p.z)                         // t0 := Y * Z
 435  	t0.Add(t0, t0)                           // t0 := t0 + t0
 436  	z3.Mul(t0, z3)                           // Z3 := t0 * Z3
 437  	x3.Sub(x3, z3)                           // X3 := X3 - Z3
 438  	z3.Mul(t0, t1)                           // Z3 := t0 * t1
 439  	z3.Add(z3, z3)                           // Z3 := Z3 + Z3
 440  	z3.Add(z3, z3)                           // Z3 := Z3 + Z3
 441  
 442  	q.x.Set(x3)
 443  	q.y.Set(y3)
 444  	q.z.Set(z3)
 445  	return q
 446  }
 447  
 448  // Select sets q to p1 if cond == 1, and to p2 if cond == 0.
 449  func (q *{{.P}}Point) Select(p1, p2 *{{.P}}Point, cond int) *{{.P}}Point {
 450  	q.x.Select(p1.x, p2.x, cond)
 451  	q.y.Select(p1.y, p2.y, cond)
 452  	q.z.Select(p1.z, p2.z, cond)
 453  	return q
 454  }
 455  
 456  // A {{.p}}Table holds the first 15 multiples of a point at offset -1, so [1]P
 457  // is at table[0], [15]P is at table[14], and [0]P is implicitly the identity
 458  // point.
 459  type {{.p}}Table [15]*{{.P}}Point
 460  
 461  // Select selects the n-th multiple of the table base point into p. It works in
 462  // constant time by iterating over every entry of the table. n must be in [0, 15].
 463  func (table *{{.p}}Table) Select(p *{{.P}}Point, n uint8) {
 464  	if n >= 16 {
 465  		panic("nistec: internal error: {{.p}}Table called with out-of-bounds value")
 466  	}
 467  	p.Set(New{{.P}}Point())
 468  	for i := uint8(1); i < 16; i++ {
 469  		cond := subtle.ConstantTimeByteEq(i, n)
 470  		p.Select(table[i-1], p, cond)
 471  	}
 472  }
 473  
 474  // ScalarMult sets p = scalar * q, and returns p.
 475  func (p *{{.P}}Point) ScalarMult(q *{{.P}}Point, scalar []byte) (*{{.P}}Point, error) {
 476  	// Compute a {{.p}}Table for the base point q. The explicit New{{.P}}Point
 477  	// calls get inlined, letting the allocations live on the stack.
 478  	var table = {{.p}}Table{New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(),
 479  		New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(),
 480  		New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(),
 481  		New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point(), New{{.P}}Point()}
 482  	table[0].Set(q)
 483  	for i := 1; i < 15; i += 2 {
 484  		table[i].Double(table[i/2])
 485  		table[i+1].Add(table[i], q)
 486  	}
 487  
 488  	// Instead of doing the classic double-and-add chain, we do it with a
 489  	// four-bit window: we double four times, and then add [0-15]P.
 490  	t := New{{.P}}Point()
 491  	p.Set(New{{.P}}Point())
 492  	for i, byte := range scalar {
 493  		// No need to double on the first iteration, as p is the identity at
 494  		// this point, and [N]∞ = ∞.
 495  		if i != 0 {
 496  			p.Double(p)
 497  			p.Double(p)
 498  			p.Double(p)
 499  			p.Double(p)
 500  		}
 501  
 502  		windowValue := byte >> 4
 503  		table.Select(t, windowValue)
 504  		p.Add(p, t)
 505  
 506  		p.Double(p)
 507  		p.Double(p)
 508  		p.Double(p)
 509  		p.Double(p)
 510  
 511  		windowValue = byte & 0b1111
 512  		table.Select(t, windowValue)
 513  		p.Add(p, t)
 514  	}
 515  
 516  	return p, nil
 517  }
 518  
 519  var {{.p}}GeneratorTable *[{{.p}}ElementLength * 2]{{.p}}Table
 520  var {{.p}}GeneratorTableOnce sync.Once
 521  
 522  // generatorTable returns a sequence of {{.p}}Tables. The first table contains
 523  // multiples of G. Each successive table is the previous table doubled four
 524  // times.
 525  func (p *{{.P}}Point) generatorTable() *[{{.p}}ElementLength * 2]{{.p}}Table {
 526  	{{.p}}GeneratorTableOnce.Do(func() {
 527  		{{.p}}GeneratorTable = new([{{.p}}ElementLength * 2]{{.p}}Table)
 528  		base := New{{.P}}Point().SetGenerator()
 529  		for i := 0; i < {{.p}}ElementLength*2; i++ {
 530  			{{.p}}GeneratorTable[i][0] = New{{.P}}Point().Set(base)
 531  			for j := 1; j < 15; j++ {
 532  				{{.p}}GeneratorTable[i][j] = New{{.P}}Point().Add({{.p}}GeneratorTable[i][j-1], base)
 533  			}
 534  			base.Double(base)
 535  			base.Double(base)
 536  			base.Double(base)
 537  			base.Double(base)
 538  		}
 539  	})
 540  	return {{.p}}GeneratorTable
 541  }
 542  
 543  // ScalarBaseMult sets p = scalar * B, where B is the canonical generator, and
 544  // returns p.
 545  func (p *{{.P}}Point) ScalarBaseMult(scalar []byte) (*{{.P}}Point, error) {
 546  	if len(scalar) != {{.p}}ElementLength {
 547  		return nil, errors.New("invalid scalar length")
 548  	}
 549  	tables := p.generatorTable()
 550  
 551  	// This is also a scalar multiplication with a four-bit window like in
 552  	// ScalarMult, but in this case the doublings are precomputed. The value
 553  	// [windowValue]G added at iteration k would normally get doubled
 554  	// (totIterations-k)×4 times, but with a larger precomputation we can
 555  	// instead add [2^((totIterations-k)×4)][windowValue]G and avoid the
 556  	// doublings between iterations.
 557  	t := New{{.P}}Point()
 558  	p.Set(New{{.P}}Point())
 559  	tableIndex := len(tables) - 1
 560  	for _, byte := range scalar {
 561  		windowValue := byte >> 4
 562  		tables[tableIndex].Select(t, windowValue)
 563  		p.Add(p, t)
 564  		tableIndex--
 565  
 566  		windowValue = byte & 0b1111
 567  		tables[tableIndex].Select(t, windowValue)
 568  		p.Add(p, t)
 569  		tableIndex--
 570  	}
 571  
 572  	return p, nil
 573  }
 574  
 575  // {{.p}}Sqrt sets e to a square root of x. If x is not a square, {{.p}}Sqrt returns
 576  // false and e is unchanged. e and x can overlap.
 577  func {{.p}}Sqrt(e, x *{{ .Element }}) (isSquare bool) {
 578  	candidate := new({{ .Element }})
 579  	{{.p}}SqrtCandidate(candidate, x)
 580  	square := new({{ .Element }}).Square(candidate)
 581  	if square.Equal(x) != 1 {
 582  		return false
 583  	}
 584  	e.Set(candidate)
 585  	return true
 586  }
 587  `
 588  
 589  const tmplAddchain = `
 590  // sqrtCandidate sets z to a square root candidate for x. z and x must not overlap.
 591  func sqrtCandidate(z, x *Element) {
 592  	// Since p = 3 mod 4, exponentiation by (p + 1) / 4 yields a square root candidate.
 593  	//
 594  	// The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the
 595  	// following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}.
 596  	//
 597  	{{- range lines (format .Script) }}
 598  	//	{{ . }}
 599  	{{- end }}
 600  	//
 601  
 602  	{{- range .Program.Temporaries }}
 603  	var {{ . }} = new(Element)
 604  	{{- end }}
 605  	{{ range $i := .Program.Instructions -}}
 606  	{{- with add $i.Op }}
 607  	{{ $i.Output }}.Mul({{ .X }}, {{ .Y }})
 608  	{{- end -}}
 609  
 610  	{{- with double $i.Op }}
 611  	{{ $i.Output }}.Square({{ .X }})
 612  	{{- end -}}
 613  
 614  	{{- with shift $i.Op -}}
 615  	{{- $first := 0 -}}
 616  	{{- if ne $i.Output.Identifier .X.Identifier }}
 617  	{{ $i.Output }}.Square({{ .X }})
 618  	{{- $first = 1 -}}
 619  	{{- end }}
 620  	for s := {{ $first }}; s < {{ .S }}; s++ {
 621  		{{ $i.Output }}.Square({{ $i.Output }})
 622  	}
 623  	{{- end -}}
 624  	{{- end }}
 625  }
 626  `
 627