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 }