You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

239 lines
6.9 KiB

  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. # The MIT License (MIT)
  4. #
  5. # Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in all
  15. # copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. # SOFTWARE.
  24. import StringIO
  25. import subprocess
  26. # Base field Z_p
  27. p = 2**255 - 19
  28. def modp_inv(x):
  29. return pow(x, p-2, p)
  30. # Square root of -1
  31. modp_sqrt_m1 = pow(2, (p-1) // 4, p)
  32. # Compute corresponding x-coordinate, with low bit corresponding to
  33. # sign, or return None on failure
  34. def recover_x(y, sign):
  35. if y >= p:
  36. return None
  37. x2 = (y*y-1) * modp_inv(d*y*y+1)
  38. if x2 == 0:
  39. if sign:
  40. return None
  41. else:
  42. return 0
  43. # Compute square root of x2
  44. x = pow(x2, (p+3) // 8, p)
  45. if (x*x - x2) % p != 0:
  46. x = x * modp_sqrt_m1 % p
  47. if (x*x - x2) % p != 0:
  48. return None
  49. if (x & 1) != sign:
  50. x = p - x
  51. return x
  52. # Curve constant
  53. d = -121665 * modp_inv(121666) % p
  54. # Base point
  55. g_y = 4 * modp_inv(5) % p
  56. g_x = recover_x(g_y, 0)
  57. # Points are represented as affine tuples (x, y).
  58. def point_add(P, Q):
  59. x1, y1 = P
  60. x2, y2 = Q
  61. x3 = ((x1*y2 + y1*x2) * modp_inv(1 + d*x1*x2*y1*y2)) % p
  62. y3 = ((y1*y2 + x1*x2) * modp_inv(1 - d*x1*x2*y1*y2)) % p
  63. return (x3, y3)
  64. # Computes Q = s * P
  65. def point_mul(s, P):
  66. Q = (0, 1) # Neutral element
  67. while s > 0:
  68. if s & 1:
  69. Q = point_add(Q, P)
  70. P = point_add(P, P)
  71. s >>= 1
  72. return Q
  73. def to_bytes(x):
  74. ret = bytearray(32)
  75. for i in range(len(ret)):
  76. ret[i] = x % 256
  77. x >>= 8
  78. assert x == 0
  79. return ret
  80. def to_ge_precomp(P):
  81. # typedef struct {
  82. # fe_loose yplusx;
  83. # fe_loose yminusx;
  84. # fe_loose xy2d;
  85. # } ge_precomp;
  86. x, y = P
  87. return ((y + x) % p, (y - x) % p, (x * y * 2 * d) % p)
  88. def to_base_25_5(x):
  89. limbs = (26, 25, 26, 25, 26, 25, 26, 25, 26, 25)
  90. ret = []
  91. for l in limbs:
  92. ret.append(x & ((1<<l) - 1))
  93. x >>= l
  94. assert x == 0
  95. return ret
  96. def to_base_51(x):
  97. ret = []
  98. for _ in range(5):
  99. ret.append(x & ((1<<51) - 1))
  100. x >>= 51
  101. assert x == 0
  102. return ret
  103. def to_literal(x):
  104. ret = "{{\n#if defined(BORINGSSL_CURVE25519_64BIT)\n"
  105. ret += ", ".join(map(str, to_base_51(x)))
  106. ret += "\n#else\n"
  107. ret += ", ".join(map(str, to_base_25_5(x)))
  108. ret += "\n#endif\n}}"
  109. return ret
  110. def main():
  111. d2 = (2 * d) % p
  112. small_precomp = bytearray()
  113. for i in range(1, 16):
  114. s = (i&1) | ((i&2) << (64-1)) | ((i&4) << (128-2)) | ((i&8) << (192-3))
  115. P = point_mul(s, (g_x, g_y))
  116. small_precomp += to_bytes(P[0])
  117. small_precomp += to_bytes(P[1])
  118. large_precomp = []
  119. for i in range(32):
  120. large_precomp.append([])
  121. for j in range(8):
  122. P = point_mul((j + 1) << (i * 8), (g_x, g_y))
  123. large_precomp[-1].append(to_ge_precomp(P))
  124. bi_precomp = []
  125. for i in range(8):
  126. P = point_mul(2*i + 1, (g_x, g_y))
  127. bi_precomp.append(to_ge_precomp(P))
  128. buf = StringIO.StringIO()
  129. buf.write("""// The MIT License (MIT)
  130. //
  131. // Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
  132. //
  133. // Permission is hereby granted, free of charge, to any person obtaining a copy
  134. // of this software and associated documentation files (the "Software"), to deal
  135. // in the Software without restriction, including without limitation the rights
  136. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  137. // copies of the Software, and to permit persons to whom the Software is
  138. // furnished to do so, subject to the following conditions:
  139. //
  140. // The above copyright notice and this permission notice shall be included in
  141. // all copies or substantial portions of the Software.
  142. //
  143. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  144. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  145. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  146. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  147. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  148. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  149. // SOFTWARE.
  150. // This file is generated from
  151. // ./make_curve25519_tables.py > curve25519_tables.h
  152. static const fe d = """)
  153. buf.write(to_literal(d))
  154. buf.write(""";
  155. static const fe sqrtm1 = """)
  156. buf.write(to_literal(modp_sqrt_m1))
  157. buf.write(""";
  158. static const fe d2 = """)
  159. buf.write(to_literal(d2))
  160. buf.write(""";
  161. #if defined(OPENSSL_SMALL)
  162. // This block of code replaces the standard base-point table with a much smaller
  163. // one. The standard table is 30,720 bytes while this one is just 960.
  164. //
  165. // This table contains 15 pairs of group elements, (x, y), where each field
  166. // element is serialised with |fe_tobytes|. If |i| is the index of the group
  167. // element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
  168. // is the most significant bit). The value of the group element is then:
  169. // (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator.
  170. static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {""")
  171. for i, b in enumerate(small_precomp):
  172. buf.write("0x%02x, " % b)
  173. buf.write("""
  174. };
  175. #else
  176. // k25519Precomp[i][j] = (j+1)*256^i*B
  177. static const ge_precomp k25519Precomp[32][8] = {
  178. """)
  179. for child in large_precomp:
  180. buf.write("{\n")
  181. for val in child:
  182. buf.write("{\n")
  183. for term in val:
  184. buf.write(to_literal(term) + ",\n")
  185. buf.write("},\n")
  186. buf.write("},\n")
  187. buf.write("""};
  188. #endif // OPENSSL_SMALL
  189. // Bi[i] = (2*i+1)*B
  190. static const ge_precomp Bi[8] = {
  191. """)
  192. for val in bi_precomp:
  193. buf.write("{\n")
  194. for term in val:
  195. buf.write(to_literal(term) + ",\n")
  196. buf.write("},\n")
  197. buf.write("""};
  198. """)
  199. proc = subprocess.Popen(["clang-format"], stdin=subprocess.PIPE)
  200. proc.communicate(buf.getvalue())
  201. if __name__ == "__main__":
  202. main()