quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ecp_comb_table.py (6924B)


      1 #!/usr/bin/env python3
      2 """
      3 Purpose
      4 
      5 This script dumps comb table of ec curve. When you add a new ec curve, you
      6 can 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 
     12 import os
     13 import subprocess
     14 import sys
     15 import tempfile
     16 
     17 HOW_TO_ADD_NEW_CURVE = """
     18 If you are trying to add new curve, you can follow these steps:
     19 
     20 1. Define curve parameters (<curve>_p, <curve>_gx, etc...) in ecp_curves.c.
     21 2. Add a macro to define <curve>_T to NULL following these parameters.
     22 3. Build mbedcrypto
     23 4. Run this script with an argument of new curve
     24 5. Copy the output of this script into ecp_curves.c and replace the macro added
     25    in Step 2
     26 6. Rebuild and test if everything is ok
     27 
     28 Replace the <curve> in the above with the name of the curve you want to add."""
     29 
     30 CC = os.getenv('CC', 'cc')
     31 MBEDTLS_LIBRARY_PATH = os.getenv('MBEDTLS_LIBRARY_PATH', "library")
     32 
     33 SRC_DUMP_COMB_TABLE = r'''
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include "mbedtls/ecp.h"
     37 #include "mbedtls/error.h"
     38 
     39 static 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 
     55 static 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 
     89 int 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 
    125 SRC_DUMP_KNOWN_CURVE = r'''
    126 #include <stdio.h>
    127 #include <stdlib.h>
    128 #include "mbedtls/ecp.h"
    129 
    130 int 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 
    148 def join_src_path(*args):
    149     return os.path.normpath(os.path.join(os.path.dirname(__file__), "..", *args))
    150 
    151 
    152 def 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 
    185 def 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("""\
    196 Unable to compile and run utility.""", file=sys.stderr)
    197         sys.exit(1)
    198 
    199 
    200 def usage():
    201     print("""
    202 Usage: python %s <curve>...
    203 
    204 Arguments:
    205     curve       Specify one or more curve names (e.g secp256r1)
    206 
    207 All possible curves: """ % sys.argv[0])
    208     run_c_source(SRC_DUMP_KNOWN_CURVE, [])
    209     print("""
    210 Environment 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 
    215 How to add a new curve: %s""" % HOW_TO_ADD_NEW_CURVE)
    216 
    217 
    218 def 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 
    236 if __name__ == '__main__':
    237     run_main()