Merge pull request #4315 from Kxuan/feat-pre-compute-tls
Static initialize comb table
This commit is contained in:
commit
84191eab06
7 changed files with 4300 additions and 27 deletions
4
ChangeLog.d/issue4128.txt
Normal file
4
ChangeLog.d/issue4128.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
API changes
|
||||||
|
* The option MBEDTLS_ECP_FIXED_POINT_OPTIM use pre-computed comb tables
|
||||||
|
instead of computing tables in runtime. Thus, this option now increase
|
||||||
|
code size, and it does not increase RAM usage in runtime anymore.
|
|
@ -0,0 +1,11 @@
|
||||||
|
Change MBEDTLS_ECP_FIXED_POINT_OPTIM behaviour
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
The option `MBEDTLS_ECP_FIXED_POINT_OPTIM` now increase code size and it does
|
||||||
|
not increase peak RAM usage anymore.
|
||||||
|
|
||||||
|
If you are limited by code size, you can define `MBEDTLS_ECP_FIXED_POINT_OPTIM`
|
||||||
|
to `0` in your config file. The impact depends on the number and size of
|
||||||
|
enabled curves. For example, for P-256 the difference is 1KB; see the documentation
|
||||||
|
of this option for details.
|
||||||
|
|
|
@ -229,7 +229,7 @@ typedef struct mbedtls_ecp_group
|
||||||
int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */
|
int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */
|
||||||
void *t_data; /*!< Unused. */
|
void *t_data; /*!< Unused. */
|
||||||
mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */
|
mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */
|
||||||
size_t T_size; /*!< The number of pre-computed points. */
|
size_t T_size; /*!< The number of dynamic allocated pre-computed points. */
|
||||||
}
|
}
|
||||||
mbedtls_ecp_group;
|
mbedtls_ecp_group;
|
||||||
|
|
||||||
|
@ -276,15 +276,16 @@ mbedtls_ecp_group;
|
||||||
|
|
||||||
#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
|
#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
|
||||||
/*
|
/*
|
||||||
* Trade memory for speed on fixed-point multiplication.
|
* Trade code size for speed on fixed-point multiplication.
|
||||||
*
|
*
|
||||||
* This speeds up repeated multiplication of the generator (that is, the
|
* This speeds up repeated multiplication of the generator (that is, the
|
||||||
* multiplication in ECDSA signatures, and half of the multiplications in
|
* multiplication in ECDSA signatures, and half of the multiplications in
|
||||||
* ECDSA verification and ECDHE) by a factor roughly 3 to 4.
|
* ECDSA verification and ECDHE) by a factor roughly 3 to 4.
|
||||||
*
|
*
|
||||||
* The cost is increasing EC peak memory usage by a factor roughly 2.
|
* For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes
|
||||||
|
* of code size if n < 384 and 8n otherwise.
|
||||||
*
|
*
|
||||||
* Change this value to 0 to reduce peak memory usage.
|
* Change this value to 0 to reduce code size.
|
||||||
*/
|
*/
|
||||||
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
|
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
|
||||||
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
|
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
|
||||||
|
|
|
@ -728,6 +728,18 @@ void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
|
||||||
mbedtls_mpi_free( &( pt->Z ) );
|
mbedtls_mpi_free( &( pt->Z ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the comb table (grp->T) is static initialized.
|
||||||
|
*/
|
||||||
|
static int ecp_group_is_static_comb_table( const mbedtls_ecp_group *grp ) {
|
||||||
|
#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
|
||||||
|
return grp->T != NULL && grp->T_size == 0;
|
||||||
|
#else
|
||||||
|
(void) grp;
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unallocate (the components of) a group
|
* Unallocate (the components of) a group
|
||||||
*/
|
*/
|
||||||
|
@ -747,7 +759,7 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
|
||||||
mbedtls_mpi_free( &grp->N );
|
mbedtls_mpi_free( &grp->N );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( grp->T != NULL )
|
if( !ecp_group_is_static_comb_table(grp) && grp->T != NULL )
|
||||||
{
|
{
|
||||||
for( i = 0; i < grp->T_size; i++ )
|
for( i = 0; i < grp->T_size; i++ )
|
||||||
mbedtls_ecp_point_free( &grp->T[i] );
|
mbedtls_ecp_point_free( &grp->T[i] );
|
||||||
|
@ -2245,11 +2257,16 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
|
||||||
w++;
|
w++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure w is within bounds.
|
* If static comb table may not be used (!p_eq_g) or static comb table does
|
||||||
|
* not exists, make sure w is within bounds.
|
||||||
* (The last test is useful only for very small curves in the test suite.)
|
* (The last test is useful only for very small curves in the test suite.)
|
||||||
|
*
|
||||||
|
* The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of
|
||||||
|
* static comb table, because the size of static comb table is fixed when
|
||||||
|
* it is generated.
|
||||||
*/
|
*/
|
||||||
#if( MBEDTLS_ECP_WINDOW_SIZE < 6 )
|
#if( MBEDTLS_ECP_WINDOW_SIZE < 6 )
|
||||||
if( w > MBEDTLS_ECP_WINDOW_SIZE )
|
if( (!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE )
|
||||||
w = MBEDTLS_ECP_WINDOW_SIZE;
|
w = MBEDTLS_ECP_WINDOW_SIZE;
|
||||||
#endif
|
#endif
|
||||||
if( w >= grp->nbits )
|
if( w >= grp->nbits )
|
||||||
|
|
4025
library/ecp_curves.c
4025
library/ecp_curves.c
File diff suppressed because it is too large
Load diff
|
@ -251,7 +251,11 @@ static int myrand( void *rng_state, unsigned char *output, size_t len )
|
||||||
#if defined(MBEDTLS_ECP_C)
|
#if defined(MBEDTLS_ECP_C)
|
||||||
void ecp_clear_precomputed( mbedtls_ecp_group *grp )
|
void ecp_clear_precomputed( mbedtls_ecp_group *grp )
|
||||||
{
|
{
|
||||||
if( grp->T != NULL )
|
if( grp->T != NULL
|
||||||
|
#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
|
||||||
|
&& grp->T_size != 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
for( i = 0; i < grp->T_size; i++ )
|
for( i = 0; i < grp->T_size; i++ )
|
||||||
|
|
249
scripts/ecp_comb_table.py
Executable file
249
scripts/ecp_comb_table.py
Executable file
|
@ -0,0 +1,249 @@
|
||||||
|
#!/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 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()
|
Loading…
Reference in a new issue