ecp_comb_table.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #!/usr/bin/env python3
  2. """
  3. Purpose
  4. This script dumps comb table of ec curve. When you add a new ec curve, you
  5. can use this script to generate codes to define `<curve>_T` in ecp_curves.c
  6. """
  7. # Copyright The Mbed TLS Contributors
  8. # SPDX-License-Identifier: Apache-2.0
  9. #
  10. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  11. # not use this file except in compliance with the License.
  12. # You may obtain a copy of the License at
  13. #
  14. # http://www.apache.org/licenses/LICENSE-2.0
  15. #
  16. # Unless required by applicable law or agreed to in writing, software
  17. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  18. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. # See the License for the specific language governing permissions and
  20. # limitations under the License.
  21. import os
  22. import subprocess
  23. import sys
  24. import tempfile
  25. HOW_TO_ADD_NEW_CURVE = """
  26. If you are trying to add new curve, you can follow these steps:
  27. 1. Define curve parameters (<curve>_p, <curve>_gx, etc...) in ecp_curves.c.
  28. 2. Add a macro to define <curve>_T to NULL following these parameters.
  29. 3. Build mbedcrypto
  30. 4. Run this script with an argument of new curve
  31. 5. Copy the output of this script into ecp_curves.c and replace the macro added
  32. in Step 2
  33. 6. Rebuild and test if everything is ok
  34. Replace the <curve> in the above with the name of the curve you want to add."""
  35. CC = os.getenv('CC', 'cc')
  36. MBEDTLS_LIBRARY_PATH = os.getenv('MBEDTLS_LIBRARY_PATH', "library")
  37. SRC_DUMP_COMB_TABLE = r'''
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include "mbedtls/ecp.h"
  41. #include "mbedtls/error.h"
  42. static void dump_mpi_initialize( const char *name, const mbedtls_mpi *d )
  43. {
  44. uint8_t buf[128] = {0};
  45. size_t olen;
  46. uint8_t *p;
  47. olen = mbedtls_mpi_size( d );
  48. mbedtls_mpi_write_binary_le( d, buf, olen );
  49. printf("static const mbedtls_mpi_uint %s[] = {\n", name);
  50. for (p = buf; p < buf + olen; p += 8) {
  51. printf( " BYTES_TO_T_UINT_8( 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X ),\n",
  52. p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] );
  53. }
  54. printf("};\n");
  55. }
  56. static void dump_T( const mbedtls_ecp_group *grp )
  57. {
  58. char name[128];
  59. printf( "#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\n" );
  60. for (size_t i = 0; i < grp->T_size; ++i) {
  61. snprintf( name, sizeof(name), "%s_T_%zu_X", CURVE_NAME, i );
  62. dump_mpi_initialize( name, &grp->T[i].X );
  63. snprintf( name, sizeof(name), "%s_T_%zu_Y", CURVE_NAME, i );
  64. dump_mpi_initialize( name, &grp->T[i].Y );
  65. }
  66. printf( "static const mbedtls_ecp_point %s_T[%zu] = {\n", CURVE_NAME, grp->T_size );
  67. size_t olen;
  68. for (size_t i = 0; i < grp->T_size; ++i) {
  69. int z;
  70. if ( mbedtls_mpi_cmp_int(&grp->T[i].Z, 0) == 0 ) {
  71. z = 0;
  72. } else if ( mbedtls_mpi_cmp_int(&grp->T[i].Z, 1) == 0 ) {
  73. z = 1;
  74. } else {
  75. fprintf( stderr, "Unexpected value of Z (i = %d)\n", (int)i );
  76. exit( 1 );
  77. }
  78. printf( " ECP_POINT_INIT_XY_Z%d(%s_T_%zu_X, %s_T_%zu_Y),\n",
  79. z,
  80. CURVE_NAME, i,
  81. CURVE_NAME, i
  82. );
  83. }
  84. printf("};\n#endif\n\n");
  85. }
  86. int main()
  87. {
  88. int rc;
  89. mbedtls_mpi m;
  90. mbedtls_ecp_point R;
  91. mbedtls_ecp_group grp;
  92. mbedtls_ecp_group_init( &grp );
  93. rc = mbedtls_ecp_group_load( &grp, CURVE_ID );
  94. if (rc != 0) {
  95. char buf[100];
  96. mbedtls_strerror( rc, buf, sizeof(buf) );
  97. fprintf( stderr, "mbedtls_ecp_group_load: %s (-0x%x)\n", buf, -rc );
  98. return 1;
  99. }
  100. grp.T = NULL;
  101. mbedtls_ecp_point_init( &R );
  102. mbedtls_mpi_init( &m);
  103. mbedtls_mpi_lset( &m, 1 );
  104. rc = mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL );
  105. if ( rc != 0 ) {
  106. char buf[100];
  107. mbedtls_strerror( rc, buf, sizeof(buf) );
  108. fprintf( stderr, "mbedtls_ecp_mul: %s (-0x%x)\n", buf, -rc );
  109. return 1;
  110. }
  111. if ( grp.T == NULL ) {
  112. fprintf( stderr, "grp.T is not generated. Please make sure"
  113. "MBEDTLS_ECP_FIXED_POINT_OPTIM is enabled in mbedtls_config.h\n" );
  114. return 1;
  115. }
  116. dump_T( &grp );
  117. return 0;
  118. }
  119. '''
  120. SRC_DUMP_KNOWN_CURVE = r'''
  121. #include <stdio.h>
  122. #include <stdlib.h>
  123. #include "mbedtls/ecp.h"
  124. int main() {
  125. const mbedtls_ecp_curve_info *info = mbedtls_ecp_curve_list();
  126. mbedtls_ecp_group grp;
  127. mbedtls_ecp_group_init( &grp );
  128. while ( info->name != NULL ) {
  129. mbedtls_ecp_group_load( &grp, info->grp_id );
  130. if ( mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) {
  131. printf( " %s", info->name );
  132. }
  133. info++;
  134. }
  135. printf( "\n" );
  136. return 0;
  137. }
  138. '''
  139. def join_src_path(*args):
  140. return os.path.normpath(os.path.join(os.path.dirname(__file__), "..", *args))
  141. def run_c_source(src, cflags):
  142. """
  143. Compile and run C source code
  144. :param src: the c language code to run
  145. :param cflags: additional cflags passing to compiler
  146. :return:
  147. """
  148. binname = tempfile.mktemp(prefix="mbedtls")
  149. fd, srcname = tempfile.mkstemp(prefix="mbedtls", suffix=".c")
  150. srcfile = os.fdopen(fd, mode="w")
  151. srcfile.write(src)
  152. srcfile.close()
  153. args = [CC,
  154. *cflags,
  155. '-I' + join_src_path("include"),
  156. "-o", binname,
  157. '-L' + MBEDTLS_LIBRARY_PATH,
  158. srcname,
  159. '-lmbedcrypto']
  160. p = subprocess.run(args=args, check=False)
  161. if p.returncode != 0:
  162. return False
  163. p = subprocess.run(args=[binname], check=False, env={
  164. 'LD_LIBRARY_PATH': MBEDTLS_LIBRARY_PATH
  165. })
  166. if p.returncode != 0:
  167. return False
  168. os.unlink(srcname)
  169. os.unlink(binname)
  170. return True
  171. def compute_curve(curve):
  172. """compute comb table for curve"""
  173. r = run_c_source(
  174. SRC_DUMP_COMB_TABLE,
  175. [
  176. '-g',
  177. '-DCURVE_ID=MBEDTLS_ECP_DP_%s' % curve.upper(),
  178. '-DCURVE_NAME="%s"' % curve.lower(),
  179. ])
  180. if not r:
  181. print("""\
  182. Unable to compile and run utility.""", file=sys.stderr)
  183. sys.exit(1)
  184. def usage():
  185. print("""
  186. Usage: python %s <curve>...
  187. Arguments:
  188. curve Specify one or more curve names (e.g secp256r1)
  189. All possible curves: """ % sys.argv[0])
  190. run_c_source(SRC_DUMP_KNOWN_CURVE, [])
  191. print("""
  192. Environment Variable:
  193. CC Specify which c compile to use to compile utility.
  194. MBEDTLS_LIBRARY_PATH
  195. Specify the path to mbedcrypto library. (e.g. build/library/)
  196. How to add a new curve: %s""" % HOW_TO_ADD_NEW_CURVE)
  197. def run_main():
  198. shared_lib_path = os.path.normpath(os.path.join(MBEDTLS_LIBRARY_PATH, "libmbedcrypto.so"))
  199. static_lib_path = os.path.normpath(os.path.join(MBEDTLS_LIBRARY_PATH, "libmbedcrypto.a"))
  200. if not os.path.exists(shared_lib_path) and not os.path.exists(static_lib_path):
  201. print("Warning: both '%s' and '%s' are not exists. This script will use "
  202. "the library from your system instead of the library compiled by "
  203. "this source directory.\n"
  204. "You can specify library path using environment variable "
  205. "'MBEDTLS_LIBRARY_PATH'." % (shared_lib_path, static_lib_path),
  206. file=sys.stderr)
  207. if len(sys.argv) <= 1:
  208. usage()
  209. else:
  210. for curve in sys.argv[1:]:
  211. compute_curve(curve)
  212. if __name__ == '__main__':
  213. run_main()