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