1#!/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 10# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 11 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" 117 "MBEDTLS_ECP_FIXED_POINT_OPTIM is enabled in mbedtls_config.h\n" ); 118 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() 238