github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/crypto/elliptic/gen_p256_table.go (about)

     1  // Copyright 2021 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  import (
    10  	"bytes"
    11  	"crypto/elliptic"
    12  	"encoding/binary"
    13  	"fmt"
    14  	"go/format"
    15  	"log"
    16  	"os"
    17  )
    18  
    19  func main() {
    20  	buf := new(bytes.Buffer)
    21  	fmt.Fprint(buf, `
    22  // Copyright 2021 The Go Authors. All rights reserved.
    23  // Use of this source code is governed by a BSD-style
    24  // license that can be found in the LICENSE file.
    25  
    26  // Generated by gen_p256_table.go. DO NOT EDIT.
    27  
    28  //go:build amd64 || arm64
    29  
    30  package elliptic
    31  
    32  `[1:])
    33  
    34  	// Generate precomputed p256 tables.
    35  	var pre [43][32 * 8]uint64
    36  	basePoint := []uint64{
    37  		0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
    38  		0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85,
    39  		0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe,
    40  	}
    41  	t1 := make([]uint64, 12)
    42  	t2 := make([]uint64, 12)
    43  	copy(t2, basePoint)
    44  	zInv := make([]uint64, 4)
    45  	zInvSq := make([]uint64, 4)
    46  	for j := 0; j < 32; j++ {
    47  		copy(t1, t2)
    48  		for i := 0; i < 43; i++ {
    49  			// The window size is 6 so we need to double 6 times.
    50  			if i != 0 {
    51  				for k := 0; k < 6; k++ {
    52  					elliptic.P256PointDoubleAsm(t1, t1)
    53  				}
    54  			}
    55  			// Convert the point to affine form. (Its values are
    56  			// still in Montgomery form however.)
    57  			elliptic.P256Inverse(zInv, t1[8:12])
    58  			elliptic.P256Sqr(zInvSq, zInv, 1)
    59  			elliptic.P256Mul(zInv, zInv, zInvSq)
    60  			elliptic.P256Mul(t1[:4], t1[:4], zInvSq)
    61  			elliptic.P256Mul(t1[4:8], t1[4:8], zInv)
    62  			copy(t1[8:12], basePoint[8:12])
    63  			// Update the table entry
    64  			copy(pre[i][j*8:], t1[:8])
    65  		}
    66  		if j == 0 {
    67  			elliptic.P256PointDoubleAsm(t2, basePoint)
    68  		} else {
    69  			elliptic.P256PointAddAsm(t2, t2, basePoint)
    70  		}
    71  	}
    72  
    73  	fmt.Fprint(buf, "const p256Precomputed = \"\" +\n\n")
    74  
    75  	// Dump the precomputed tables, flattened, little-endian.
    76  	// These tables are used directly by assembly on little-endian platforms.
    77  	// Putting the data in a const string lets it be stored readonly.
    78  	for i := range &pre {
    79  		for j, v := range &pre[i] {
    80  			fmt.Fprintf(buf, "\"")
    81  			var u8 [8]byte
    82  			binary.LittleEndian.PutUint64(u8[:], v)
    83  			for _, b := range &u8 {
    84  				fmt.Fprintf(buf, "\\x%02x", b)
    85  			}
    86  			fmt.Fprintf(buf, "\"")
    87  			if i < len(pre)-1 || j < len(pre[i])-1 {
    88  				fmt.Fprint(buf, "+")
    89  			}
    90  			if j%8 == 7 {
    91  				fmt.Fprint(buf, "\n")
    92  			}
    93  		}
    94  		fmt.Fprint(buf, "\n")
    95  	}
    96  
    97  	src := buf.Bytes()
    98  	fmtsrc, fmterr := format.Source(src)
    99  	// If formatting failed, keep the original source for debugging.
   100  	if fmterr == nil {
   101  		src = fmtsrc
   102  	}
   103  	err := os.WriteFile("p256_asm_table.go", src, 0644)
   104  	if err != nil {
   105  		log.Fatal(err)
   106  	}
   107  	if fmterr != nil {
   108  		log.Fatal(fmterr)
   109  	}
   110  }