1/* Copyright (c) 2018, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15package main 16 17import ( 18 "crypto/elliptic" 19 "fmt" 20 "math/big" 21 "os" 22) 23 24const fileHeader = `/* 25 * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. 26 * Copyright (c) 2015, Intel Inc. 27 * 28 * Licensed under the OpenSSL license (the "License"). You may not use 29 * this file except in compliance with the License. You can obtain a copy 30 * in the file LICENSE in the source distribution or at 31 * https://www.openssl.org/source/license.html 32 */ 33 34// This is the precomputed constant time access table for the code in 35// p256-x86_64.c, for the default generator. The table consists of 37 36// subtables, each subtable contains 64 affine points. The affine points are 37// encoded as eight uint64's, four for the x coordinate and four for the y. 38// Both values are in little-endian order. There are 37 tables because a 39// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37. 40// Within each table there are 64 values because the 6-bit wNAF value can take 41// 64 values, ignoring the sign bit, which is implemented by performing a 42// negation of the affine point when required. We would like to align it to 2MB 43// in order to increase the chances of using a large page but that appears to 44// lead to invalid ELF files being produced. 45 46// This file is generated by make_p256-x86_64-table.go. 47 48static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = { 49` 50 51func main() { 52 os.Stdout.WriteString(fileHeader) 53 54 scalar, tmp := new(big.Int), new(big.Int) 55 p256 := elliptic.P256() 56 p := p256.Params().P 57 58 // The wNAF windows are 7 bits wide, so advance across the 256-bit scalar 59 // space in 7-bit increments. 60 for shift := uint(0); shift < 256; shift += 7 { 61 // For each window, encode 64 multiples of the base point. 62 for multiple := 1; multiple <= 64; multiple++ { 63 scalar.SetInt64(int64(multiple)) 64 scalar.Lsh(scalar, shift) 65 66 x, y := p256.ScalarBaseMult(scalar.Bytes()) 67 68 toMontgomery(x, p) 69 toMontgomery(y, p) 70 71 if multiple == 1 { 72 os.Stdout.WriteString(" {{") 73 } else { 74 os.Stdout.WriteString(" {") 75 } 76 printNum(x, tmp) 77 78 os.Stdout.WriteString(",\n ") 79 printNum(y, tmp) 80 81 if multiple == 64 { 82 os.Stdout.WriteString("}}") 83 } else { 84 os.Stdout.WriteString("},\n") 85 } 86 } 87 88 if shift+7 < 256 { 89 os.Stdout.WriteString(",\n") 90 } else { 91 os.Stdout.WriteString("};\n") 92 } 93 } 94} 95 96var mask, R *big.Int 97 98func init() { 99 mask = new(big.Int).SetUint64(0xffffffffffffffff) 100 R = new(big.Int).SetInt64(1) 101 R.Lsh(R, 256) 102} 103 104func printNum(n, tmp *big.Int) { 105 fmt.Printf("{") 106 for i := 0; i < 4; i++ { 107 tmp.And(n, mask) 108 limb := tmp.Uint64() 109 fmt.Printf("TOBN(0x%08x, 0x%08x)", uint32(limb>>32), uint32(limb)) 110 n.Rsh(n, 64) 111 112 switch i { 113 case 0, 2: 114 os.Stdout.WriteString(", ") 115 case 1: 116 os.Stdout.WriteString(",\n ") 117 } 118 } 119 fmt.Printf("}") 120} 121 122// toMontgomery sets n to be n×R mod p 123func toMontgomery(n, p *big.Int) { 124 n.Mul(n, R) 125 n.Mod(n, p) 126} 127