xref: /aosp_15_r20/external/mbedtls/scripts/ecp_comb_table.py (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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