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