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