| #!/usr/bin/env python3 |
| """ |
| Purpose |
| |
| This script dumps comb table of ec curve. When you add a new ec curve, you |
| can use this script to generate codes to define `<curve>_T` in ecp_curves.c |
| """ |
| |
| # Copyright The Mbed TLS Contributors |
| # SPDX-License-Identifier: Apache-2.0 |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import os |
| import subprocess |
| import sys |
| import tempfile |
| |
| HOW_TO_ADD_NEW_CURVE = """ |
| If you are trying to add new curve, you can follow these steps: |
| |
| 1. Define curve parameters (<curve>_p, <curve>_gx, etc...) in ecp_curves.c. |
| 2. Add a macro to define <curve>_T to NULL following these parameters. |
| 3. Build mbedcrypto |
| 4. Run this script with an argument of new curve |
| 5. Copy the output of this script into ecp_curves.c and replace the macro added |
| in Step 2 |
| 6. Rebuild and test if everything is ok |
| |
| Replace the <curve> in the above with the name of the curve you want to add.""" |
| |
| CC = os.getenv('CC', 'cc') |
| MBEDTLS_LIBRARY_PATH = os.getenv('MBEDTLS_LIBRARY_PATH', "library") |
| |
| SRC_DUMP_COMB_TABLE = r''' |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "mbedtls/ecp.h" |
| #include "mbedtls/error.h" |
| |
| static void dump_mpi_initialize( const char *name, const mbedtls_mpi *d ) |
| { |
| uint8_t buf[128] = {0}; |
| size_t olen; |
| uint8_t *p; |
| |
| olen = mbedtls_mpi_size( d ); |
| mbedtls_mpi_write_binary_le( d, buf, olen ); |
| printf("static const mbedtls_mpi_uint %s[] = {\n", name); |
| for (p = buf; p < buf + olen; p += 8) { |
| printf( " BYTES_TO_T_UINT_8( 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X ),\n", |
| p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] ); |
| } |
| printf("};\n"); |
| } |
| |
| static void dump_T( const mbedtls_ecp_group *grp ) |
| { |
| char name[128]; |
| |
| printf( "#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\n" ); |
| |
| for (size_t i = 0; i < grp->T_size; ++i) { |
| snprintf( name, sizeof(name), "%s_T_%zu_X", CURVE_NAME, i ); |
| dump_mpi_initialize( name, &grp->T[i].X ); |
| |
| snprintf( name, sizeof(name), "%s_T_%zu_Y", CURVE_NAME, i ); |
| dump_mpi_initialize( name, &grp->T[i].Y ); |
| } |
| printf( "static const mbedtls_ecp_point %s_T[%zu] = {\n", CURVE_NAME, grp->T_size ); |
| size_t olen; |
| for (size_t i = 0; i < grp->T_size; ++i) { |
| int z; |
| if ( mbedtls_mpi_cmp_int(&grp->T[i].Z, 0) == 0 ) { |
| z = 0; |
| } else if ( mbedtls_mpi_cmp_int(&grp->T[i].Z, 1) == 0 ) { |
| z = 1; |
| } else { |
| fprintf( stderr, "Unexpected value of Z (i = %d)\n", (int)i ); |
| exit( 1 ); |
| } |
| printf( " ECP_POINT_INIT_XY_Z%d(%s_T_%zu_X, %s_T_%zu_Y),\n", |
| z, |
| CURVE_NAME, i, |
| CURVE_NAME, i |
| ); |
| } |
| printf("};\n#endif\n\n"); |
| } |
| |
| int main() |
| { |
| int rc; |
| mbedtls_mpi m; |
| mbedtls_ecp_point R; |
| mbedtls_ecp_group grp; |
| |
| mbedtls_ecp_group_init( &grp ); |
| rc = mbedtls_ecp_group_load( &grp, CURVE_ID ); |
| if (rc != 0) { |
| char buf[100]; |
| mbedtls_strerror( rc, buf, sizeof(buf) ); |
| fprintf( stderr, "mbedtls_ecp_group_load: %s (-0x%x)\n", buf, -rc ); |
| return 1; |
| } |
| grp.T = NULL; |
| mbedtls_ecp_point_init( &R ); |
| mbedtls_mpi_init( &m); |
| mbedtls_mpi_lset( &m, 1 ); |
| rc = mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ); |
| if ( rc != 0 ) { |
| char buf[100]; |
| mbedtls_strerror( rc, buf, sizeof(buf) ); |
| fprintf( stderr, "mbedtls_ecp_mul: %s (-0x%x)\n", buf, -rc ); |
| return 1; |
| } |
| if ( grp.T == NULL ) { |
| fprintf( stderr, "grp.T is not generated. Please make sure" |
| "MBEDTLS_ECP_FIXED_POINT_OPTIM is enabled in mbedtls_config.h\n" ); |
| return 1; |
| } |
| dump_T( &grp ); |
| return 0; |
| } |
| ''' |
| |
| SRC_DUMP_KNOWN_CURVE = r''' |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "mbedtls/ecp.h" |
| |
| int main() { |
| const mbedtls_ecp_curve_info *info = mbedtls_ecp_curve_list(); |
| mbedtls_ecp_group grp; |
| |
| mbedtls_ecp_group_init( &grp ); |
| while ( info->name != NULL ) { |
| mbedtls_ecp_group_load( &grp, info->grp_id ); |
| if ( mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) { |
| printf( " %s", info->name ); |
| } |
| info++; |
| } |
| printf( "\n" ); |
| return 0; |
| } |
| ''' |
| |
| |
| def join_src_path(*args): |
| return os.path.normpath(os.path.join(os.path.dirname(__file__), "..", *args)) |
| |
| |
| def run_c_source(src, cflags): |
| """ |
| Compile and run C source code |
| :param src: the c language code to run |
| :param cflags: additional cflags passing to compiler |
| :return: |
| """ |
| binname = tempfile.mktemp(prefix="mbedtls") |
| fd, srcname = tempfile.mkstemp(prefix="mbedtls", suffix=".c") |
| srcfile = os.fdopen(fd, mode="w") |
| srcfile.write(src) |
| srcfile.close() |
| args = [CC, |
| *cflags, |
| '-I' + join_src_path("include"), |
| "-o", binname, |
| '-L' + MBEDTLS_LIBRARY_PATH, |
| srcname, |
| '-lmbedcrypto'] |
| |
| p = subprocess.run(args=args, check=False) |
| if p.returncode != 0: |
| return False |
| p = subprocess.run(args=[binname], check=False, env={ |
| 'LD_LIBRARY_PATH': MBEDTLS_LIBRARY_PATH |
| }) |
| if p.returncode != 0: |
| return False |
| os.unlink(srcname) |
| os.unlink(binname) |
| return True |
| |
| |
| def compute_curve(curve): |
| """compute comb table for curve""" |
| r = run_c_source( |
| SRC_DUMP_COMB_TABLE, |
| [ |
| '-g', |
| '-DCURVE_ID=MBEDTLS_ECP_DP_%s' % curve.upper(), |
| '-DCURVE_NAME="%s"' % curve.lower(), |
| ]) |
| if not r: |
| print("""\ |
| Unable to compile and run utility.""", file=sys.stderr) |
| sys.exit(1) |
| |
| |
| def usage(): |
| print(""" |
| Usage: python %s <curve>... |
| |
| Arguments: |
| curve Specify one or more curve names (e.g secp256r1) |
| |
| All possible curves: """ % sys.argv[0]) |
| run_c_source(SRC_DUMP_KNOWN_CURVE, []) |
| print(""" |
| Environment Variable: |
| CC Specify which c compile to use to compile utility. |
| MBEDTLS_LIBRARY_PATH |
| Specify the path to mbedcrypto library. (e.g. build/library/) |
| |
| How to add a new curve: %s""" % HOW_TO_ADD_NEW_CURVE) |
| |
| |
| def run_main(): |
| shared_lib_path = os.path.normpath(os.path.join(MBEDTLS_LIBRARY_PATH, "libmbedcrypto.so")) |
| static_lib_path = os.path.normpath(os.path.join(MBEDTLS_LIBRARY_PATH, "libmbedcrypto.a")) |
| if not os.path.exists(shared_lib_path) and not os.path.exists(static_lib_path): |
| print("Warning: both '%s' and '%s' are not exists. This script will use " |
| "the library from your system instead of the library compiled by " |
| "this source directory.\n" |
| "You can specify library path using environment variable " |
| "'MBEDTLS_LIBRARY_PATH'." % (shared_lib_path, static_lib_path), |
| file=sys.stderr) |
| |
| if len(sys.argv) <= 1: |
| usage() |
| else: |
| for curve in sys.argv[1:]: |
| compute_curve(curve) |
| |
| |
| if __name__ == '__main__': |
| run_main() |