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