boringssl/third_party/fiat/make_curve25519_tables.py
David Benjamin 0c1eafc6fe Add additional constants to make_curve25519_tables.py.
These are also constants that depend on the field representation.

Change-Id: I22333c099352ad64eb27fe15ffdc38c6ae7c07ff
Reviewed-on: https://boringssl-review.googlesource.com/24746
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
2018-01-23 21:35:03 +00:00

230 lines
6.8 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# coding=utf-8
# The MIT License (MIT)
#
# Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import StringIO
import subprocess
# Base field Z_p
p = 2**255 - 19
def modp_inv(x):
return pow(x, p-2, p)
# Square root of -1
modp_sqrt_m1 = pow(2, (p-1) // 4, p)
# Compute corresponding x-coordinate, with low bit corresponding to
# sign, or return None on failure
def recover_x(y, sign):
if y >= p:
return None
x2 = (y*y-1) * modp_inv(d*y*y+1)
if x2 == 0:
if sign:
return None
else:
return 0
# Compute square root of x2
x = pow(x2, (p+3) // 8, p)
if (x*x - x2) % p != 0:
x = x * modp_sqrt_m1 % p
if (x*x - x2) % p != 0:
return None
if (x & 1) != sign:
x = p - x
return x
# Curve constant
d = -121665 * modp_inv(121666) % p
# Base point
g_y = 4 * modp_inv(5) % p
g_x = recover_x(g_y, 0)
# Points are represented as affine tuples (x, y).
def point_add(P, Q):
x1, y1 = P
x2, y2 = Q
x3 = ((x1*y2 + y1*x2) * modp_inv(1 + d*x1*x2*y1*y2)) % p
y3 = ((y1*y2 + x1*x2) * modp_inv(1 - d*x1*x2*y1*y2)) % p
return (x3, y3)
# Computes Q = s * P
def point_mul(s, P):
Q = (0, 1) # Neutral element
while s > 0:
if s & 1:
Q = point_add(Q, P)
P = point_add(P, P)
s >>= 1
return Q
def to_bytes(x):
ret = bytearray(32)
for i in range(len(ret)):
ret[i] = x % 256
x >>= 8
assert x == 0
return ret
def to_ge_precomp(P):
# typedef struct {
# fe_loose yplusx;
# fe_loose yminusx;
# fe_loose xy2d;
# } ge_precomp;
x, y = P
return ((y + x) % p, (y - x) % p, (x * y * 2 * d) % p)
def to_base_25_5(x):
limbs = (26, 25, 26, 25, 26, 25, 26, 25, 26, 25)
ret = []
for l in limbs:
ret.append(x & ((1<<l) - 1))
x >>= l
assert x == 0
return ret
def main():
d2 = (2 * d) % p
small_precomp = bytearray()
for i in range(1, 16):
s = (i&1) | ((i&2) << (64-1)) | ((i&4) << (128-2)) | ((i&8) << (192-3))
P = point_mul(s, (g_x, g_y))
small_precomp += to_bytes(P[0])
small_precomp += to_bytes(P[1])
large_precomp = []
for i in range(32):
large_precomp.append([])
for j in range(8):
P = point_mul((j + 1) << (i * 8), (g_x, g_y))
large_precomp[-1].append(to_ge_precomp(P))
bi_precomp = []
for i in range(8):
P = point_mul(2*i + 1, (g_x, g_y))
bi_precomp.append(to_ge_precomp(P))
buf = StringIO.StringIO()
buf.write("""// The MIT License (MIT)
//
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// This file is generated from
// ./make_curve25519_tables.py > curve25519_tables.h
static const fe d = {{
""")
buf.write(", ".join(map(str, to_base_25_5(d))))
buf.write("""}};
static const fe sqrtm1 = {{
""")
buf.write(", ".join(map(str, to_base_25_5(modp_sqrt_m1))))
buf.write("""}};
static const fe d2 = {{
""")
buf.write(", ".join(map(str, to_base_25_5(d2))))
buf.write("""}};
#if defined(OPENSSL_SMALL)
// This block of code replaces the standard base-point table with a much smaller
// one. The standard table is 30,720 bytes while this one is just 960.
//
// This table contains 15 pairs of group elements, (x, y), where each field
// element is serialised with |fe_tobytes|. If |i| is the index of the group
// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
// is the most significant bit). The value of the group element is then:
// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator.
static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {""")
for i, b in enumerate(small_precomp):
buf.write("0x%02x, " % b)
buf.write("""
};
#else
// k25519Precomp[i][j] = (j+1)*256^i*B
static const ge_precomp k25519Precomp[32][8] = {
""")
for child in large_precomp:
buf.write("{\n")
for val in child:
buf.write("{\n")
for term in val:
buf.write("{{")
buf.write(", ".join(map(str, to_base_25_5(term))))
buf.write("}},\n")
buf.write("},\n")
buf.write("},\n")
buf.write("""};
#endif // OPENSSL_SMALL
// Bi[i] = (2*i+1)*B
static const ge_precomp Bi[8] = {
""")
for val in bi_precomp:
buf.write("{\n")
for term in val:
buf.write("{{")
buf.write(", ".join(map(str, to_base_25_5(term))))
buf.write("}},\n")
buf.write("},\n")
buf.write("""};
""")
proc = subprocess.Popen(["clang-format"], stdin=subprocess.PIPE)
proc.communicate(buf.getvalue())
if __name__ == "__main__":
main()