blob: 604fb85b847a056ce8b9bebec1273f66e57e2ebe [file] [log] [blame]
/* Copyright (c) 2018, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
package main
import (
"crypto/elliptic"
"fmt"
"math/big"
"os"
)
const fileHeader = `/*
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2015, Intel Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
// This is the precomputed constant time access table for the code in
// p256-x86_64.c, for the default generator. The table consists of 37
// subtables, each subtable contains 64 affine points. The affine points are
// encoded as eight uint64's, four for the x coordinate and four for the y.
// Both values are in little-endian order. There are 37 tables because a
// signed, 6-bit wNAF form of the scalar is used and ceil(256/(6 + 1)) = 37.
// Within each table there are 64 values because the 6-bit wNAF value can take
// 64 values, ignoring the sign bit, which is implemented by performing a
// negation of the affine point when required. We would like to align it to 2MB
// in order to increase the chances of using a large page but that appears to
// lead to invalid ELF files being produced.
// This file is generated by make_p256-x86_64-table.go.
static const alignas(4096) PRECOMP256_ROW ecp_nistz256_precomputed[37] = {
`
func main() {
os.Stdout.WriteString(fileHeader)
scalar, tmp := new(big.Int), new(big.Int)
p256 := elliptic.P256()
p := p256.Params().P
// The wNAF windows are 7 bits wide, so advance across the 256-bit scalar
// space in 7-bit increments.
for shift := uint(0); shift < 256; shift += 7 {
// For each window, encode 64 multiples of the base point.
for multiple := 1; multiple <= 64; multiple++ {
scalar.SetInt64(int64(multiple))
scalar.Lsh(scalar, shift)
x, y := p256.ScalarBaseMult(scalar.Bytes())
toMontgomery(x, p)
toMontgomery(y, p)
if multiple == 1 {
os.Stdout.WriteString(" {{")
} else {
os.Stdout.WriteString(" {")
}
printNum(x, tmp)
os.Stdout.WriteString(",\n ")
printNum(y, tmp)
if multiple == 64 {
os.Stdout.WriteString("}}")
} else {
os.Stdout.WriteString("},\n")
}
}
if shift+7 < 256 {
os.Stdout.WriteString(",\n")
} else {
os.Stdout.WriteString("};\n")
}
}
}
var mask, R *big.Int
func init() {
mask = new(big.Int).SetUint64(0xffffffffffffffff)
R = new(big.Int).SetInt64(1)
R.Lsh(R, 256)
}
func printNum(n, tmp *big.Int) {
fmt.Printf("{")
for i := 0; i < 4; i++ {
tmp.And(n, mask)
limb := tmp.Uint64()
fmt.Printf("TOBN(0x%08x, 0x%08x)", uint32(limb>>32), uint32(limb))
n.Rsh(n, 64)
switch i {
case 0, 2:
os.Stdout.WriteString(", ")
case 1:
os.Stdout.WriteString(",\n ")
}
}
fmt.Printf("}")
}
// toMontgomery sets n to be n×R mod p
func toMontgomery(n, p *big.Int) {
n.Mul(n, R)
n.Mod(n, p)
}