|
- #!/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 to_base_51(x):
- ret = []
- for _ in range(5):
- ret.append(x & ((1<<51) - 1))
- x >>= 51
- assert x == 0
- return ret
-
- def to_literal(x):
- ret = "{{\n#if defined(BORINGSSL_CURVE25519_64BIT)\n"
- ret += ", ".join(map(str, to_base_51(x)))
- ret += "\n#else\n"
- ret += ", ".join(map(str, to_base_25_5(x)))
- ret += "\n#endif\n}}"
- 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(to_literal(d))
- buf.write(""";
-
- static const fe sqrtm1 = """)
- buf.write(to_literal(modp_sqrt_m1))
- buf.write(""";
-
- static const fe d2 = """)
- buf.write(to_literal(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(to_literal(term) + ",\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(to_literal(term) + ",\n")
- buf.write("},\n")
- buf.write("""};
- """)
-
- proc = subprocess.Popen(["clang-format"], stdin=subprocess.PIPE)
- proc.communicate(buf.getvalue())
-
- if __name__ == "__main__":
- main()
|