#!/usr/bin/env python
# coding=utf-8
# Copyright (c) 2020, 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.

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("""/* Copyright (c) 2020, 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. */

// 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()
