Add ability to use a statically generated ecmult context.
This vastly shrinks the size of the context required for signing on devices with memory-mapped Flash. Tables are generated by the new gen_context tool into a header.
This commit is contained in:
		
							parent
							
								
									0cbc8600f3
								
							
						
					
					
						commit
						fbecc38a89
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -4,6 +4,7 @@ bench_verify | ||||
| bench_recover | ||||
| bench_internal | ||||
| tests | ||||
| gen_context | ||||
| *.exe | ||||
| *.so | ||||
| *.a | ||||
| @ -28,6 +29,7 @@ build-aux/ | ||||
| *~ | ||||
| src/libsecp256k1-config.h | ||||
| src/libsecp256k1-config.h.in | ||||
| src/ecmult_static_context.h | ||||
| m4/libtool.m4 | ||||
| m4/ltoptions.m4 | ||||
| m4/ltsugar.m4 | ||||
|  | ||||
							
								
								
									
										18
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile.am
									
									
									
									
									
								
							| @ -74,4 +74,22 @@ tests_LDFLAGS = -static | ||||
| TESTS = tests | ||||
| endif | ||||
| 
 | ||||
| if USE_ECMULT_STATIC_PRECOMPUTATION | ||||
| CPPFLAGS_FOR_BUILD +=-I. | ||||
| CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function | ||||
| 
 | ||||
| gen_context_OBJECTS = gen_context.o | ||||
| 
 | ||||
| gen_%.o: src/gen_%.c | ||||
| 	$(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ | ||||
| 
 | ||||
| gen_context$(BUILD_EXEEXT): $(gen_context_OBJECTS) | ||||
| 	$(CC_FOR_BUILD) $^ -o $@ | ||||
| 
 | ||||
| BUILT_SOURCES = src/ecmult_static_context.h | ||||
| 
 | ||||
| src/ecmult_static_context.h: gen_context | ||||
| 	./gen_context | ||||
| endif | ||||
| 
 | ||||
| EXTRA_DIST = autogen.sh | ||||
|  | ||||
							
								
								
									
										125
									
								
								build-aux/m4/ax_prog_cc_for_build.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								build-aux/m4/ax_prog_cc_for_build.m4
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,125 @@ | ||||
| # =========================================================================== | ||||
| #   http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html | ||||
| # =========================================================================== | ||||
| # | ||||
| # SYNOPSIS | ||||
| # | ||||
| #   AX_PROG_CC_FOR_BUILD | ||||
| # | ||||
| # DESCRIPTION | ||||
| # | ||||
| #   This macro searches for a C compiler that generates native executables, | ||||
| #   that is a C compiler that surely is not a cross-compiler. This can be | ||||
| #   useful if you have to generate source code at compile-time like for | ||||
| #   example GCC does. | ||||
| # | ||||
| #   The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything | ||||
| #   needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). | ||||
| #   The value of these variables can be overridden by the user by specifying | ||||
| #   a compiler with an environment variable (like you do for standard CC). | ||||
| # | ||||
| #   It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object | ||||
| #   file extensions for the build platform, and GCC_FOR_BUILD to `yes' if | ||||
| #   the compiler we found is GCC. All these variables but GCC_FOR_BUILD are | ||||
| #   substituted in the Makefile. | ||||
| # | ||||
| # LICENSE | ||||
| # | ||||
| #   Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org> | ||||
| # | ||||
| #   Copying and distribution of this file, with or without modification, are | ||||
| #   permitted in any medium without royalty provided the copyright notice | ||||
| #   and this notice are preserved. This file is offered as-is, without any | ||||
| #   warranty. | ||||
| 
 | ||||
| #serial 8 | ||||
| 
 | ||||
| AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) | ||||
| AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl | ||||
| AC_REQUIRE([AC_PROG_CC])dnl | ||||
| AC_REQUIRE([AC_PROG_CPP])dnl | ||||
| AC_REQUIRE([AC_EXEEXT])dnl | ||||
| AC_REQUIRE([AC_CANONICAL_HOST])dnl | ||||
| 
 | ||||
| dnl Use the standard macros, but make them use other variable names | ||||
| dnl | ||||
| pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl | ||||
| pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl | ||||
| pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl | ||||
| pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl | ||||
| pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl | ||||
| pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl | ||||
| pushdef([ac_cv_objext], ac_cv_build_objext)dnl | ||||
| pushdef([ac_exeext], ac_build_exeext)dnl | ||||
| pushdef([ac_objext], ac_build_objext)dnl | ||||
| pushdef([CC], CC_FOR_BUILD)dnl | ||||
| pushdef([CPP], CPP_FOR_BUILD)dnl | ||||
| pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl | ||||
| pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl | ||||
| pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl | ||||
| pushdef([host], build)dnl | ||||
| pushdef([host_alias], build_alias)dnl | ||||
| pushdef([host_cpu], build_cpu)dnl | ||||
| pushdef([host_vendor], build_vendor)dnl | ||||
| pushdef([host_os], build_os)dnl | ||||
| pushdef([ac_cv_host], ac_cv_build)dnl | ||||
| pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl | ||||
| pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl | ||||
| pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl | ||||
| pushdef([ac_cv_host_os], ac_cv_build_os)dnl | ||||
| pushdef([ac_cpp], ac_build_cpp)dnl | ||||
| pushdef([ac_compile], ac_build_compile)dnl | ||||
| pushdef([ac_link], ac_build_link)dnl | ||||
| 
 | ||||
| save_cross_compiling=$cross_compiling | ||||
| save_ac_tool_prefix=$ac_tool_prefix | ||||
| cross_compiling=no | ||||
| ac_tool_prefix= | ||||
| 
 | ||||
| AC_PROG_CC | ||||
| AC_PROG_CPP | ||||
| AC_EXEEXT | ||||
| 
 | ||||
| ac_tool_prefix=$save_ac_tool_prefix | ||||
| cross_compiling=$save_cross_compiling | ||||
| 
 | ||||
| dnl Restore the old definitions | ||||
| dnl | ||||
| popdef([ac_link])dnl | ||||
| popdef([ac_compile])dnl | ||||
| popdef([ac_cpp])dnl | ||||
| popdef([ac_cv_host_os])dnl | ||||
| popdef([ac_cv_host_vendor])dnl | ||||
| popdef([ac_cv_host_cpu])dnl | ||||
| popdef([ac_cv_host_alias])dnl | ||||
| popdef([ac_cv_host])dnl | ||||
| popdef([host_os])dnl | ||||
| popdef([host_vendor])dnl | ||||
| popdef([host_cpu])dnl | ||||
| popdef([host_alias])dnl | ||||
| popdef([host])dnl | ||||
| popdef([LDFLAGS])dnl | ||||
| popdef([CPPFLAGS])dnl | ||||
| popdef([CFLAGS])dnl | ||||
| popdef([CPP])dnl | ||||
| popdef([CC])dnl | ||||
| popdef([ac_objext])dnl | ||||
| popdef([ac_exeext])dnl | ||||
| popdef([ac_cv_objext])dnl | ||||
| popdef([ac_cv_exeext])dnl | ||||
| popdef([ac_cv_prog_cc_g])dnl | ||||
| popdef([ac_cv_prog_cc_cross])dnl | ||||
| popdef([ac_cv_prog_cc_works])dnl | ||||
| popdef([ac_cv_prog_gcc])dnl | ||||
| popdef([ac_cv_prog_CPP])dnl | ||||
| 
 | ||||
| dnl Finally, set Makefile variables | ||||
| dnl | ||||
| BUILD_EXEEXT=$ac_build_exeext | ||||
| BUILD_OBJEXT=$ac_build_objext | ||||
| AC_SUBST(BUILD_EXEEXT)dnl | ||||
| AC_SUBST(BUILD_OBJEXT)dnl | ||||
| AC_SUBST([CFLAGS_FOR_BUILD])dnl | ||||
| AC_SUBST([CPPFLAGS_FOR_BUILD])dnl | ||||
| AC_SUBST([LDFLAGS_FOR_BUILD])dnl | ||||
| ]) | ||||
							
								
								
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							| @ -17,6 +17,7 @@ PKG_PROG_PKG_CONFIG | ||||
| AC_PATH_TOOL(AR, ar) | ||||
| AC_PATH_TOOL(RANLIB, ranlib) | ||||
| AC_PATH_TOOL(STRIP, strip) | ||||
| AX_PROG_CC_FOR_BUILD | ||||
| 
 | ||||
| if test "x$CFLAGS" = "x"; then | ||||
|   CFLAGS="-O3 -g" | ||||
| @ -95,6 +96,11 @@ AC_ARG_ENABLE(endomorphism, | ||||
|     AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), | ||||
|     [use_endomorphism=$enableval], | ||||
|     [use_endomorphism=no]) | ||||
|      | ||||
| AC_ARG_ENABLE(ecmult_static_precomputation, | ||||
|     AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is no)]), | ||||
|     [use_ecmult_static_precomputation=$enableval], | ||||
|     [use_ecmult_static_precomputation=no]) | ||||
| 
 | ||||
| AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], | ||||
| [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) | ||||
| @ -305,6 +311,10 @@ if test x"$use_endomorphism" = x"yes"; then | ||||
|   AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) | ||||
| fi | ||||
| 
 | ||||
| if test x"$use_ecmult_static_precomputation" = x"yes"; then | ||||
|   AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) | ||||
| fi | ||||
| 
 | ||||
| AC_C_BIGENDIAN() | ||||
| 
 | ||||
| AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) | ||||
| @ -321,6 +331,7 @@ AC_SUBST(SECP_TEST_LIBS) | ||||
| AC_SUBST(SECP_TEST_INCLUDES) | ||||
| AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) | ||||
| AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) | ||||
| AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_precomputation" = x"yes"]) | ||||
| 
 | ||||
| dnl make sure nothing new is exported so that we don't break the cache | ||||
| PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" | ||||
|  | ||||
							
								
								
									
										32
									
								
								src/basic-config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/basic-config.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| /**********************************************************************
 | ||||
|  * Copyright (c) 2013, 2014 Pieter Wuille                             * | ||||
|  * Distributed under the MIT software license, see the accompanying   * | ||||
|  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||
|  **********************************************************************/ | ||||
| 
 | ||||
| #ifndef _SECP256K1_BASIC_CONFIG_ | ||||
| #define _SECP256K1_BASIC_CONFIG_ | ||||
| 
 | ||||
| #ifdef USE_BASIC_CONFIG | ||||
| 
 | ||||
| #undef USE_ASM_X86_64 | ||||
| #undef USE_ENDOMORPHISM | ||||
| #undef USE_FIELD_10X26 | ||||
| #undef USE_FIELD_5X52 | ||||
| #undef USE_FIELD_INV_BUILTIN | ||||
| #undef USE_FIELD_INV_NUM | ||||
| #undef USE_NUM_GMP | ||||
| #undef USE_NUM_NONE | ||||
| #undef USE_SCALAR_4X64 | ||||
| #undef USE_SCALAR_8X32 | ||||
| #undef USE_SCALAR_INV_BUILTIN | ||||
| #undef USE_SCALAR_INV_NUM | ||||
| 
 | ||||
| #define USE_NUM_NONE 1 | ||||
| #define USE_FIELD_INV_BUILTIN 1 | ||||
| #define USE_SCALAR_INV_BUILTIN 1 | ||||
| #define USE_FIELD_10X26 1 | ||||
| #define USE_SCALAR_8X32 1 | ||||
| 
 | ||||
| #endif // USE_BASIC_CONFIG
 | ||||
| #endif // _SECP256K1_BASIC_CONFIG_
 | ||||
| @ -11,21 +11,25 @@ | ||||
| #include "group.h" | ||||
| #include "ecmult_gen.h" | ||||
| #include "hash_impl.h" | ||||
| 
 | ||||
| #ifdef USE_ECMULT_STATIC_PRECOMPUTATION | ||||
| #include "ecmult_static_context.h" | ||||
| #endif | ||||
| static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t *ctx) { | ||||
|     ctx->prec = NULL; | ||||
| } | ||||
| 
 | ||||
| static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *ctx) { | ||||
| #ifndef USE_ECMULT_STATIC_PRECOMPUTATION | ||||
|     secp256k1_ge_t prec[1024]; | ||||
|     secp256k1_gej_t gj; | ||||
|     secp256k1_gej_t nums_gej; | ||||
|     int i, j; | ||||
| #endif | ||||
| 
 | ||||
|     if (ctx->prec != NULL) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| #ifndef USE_ECMULT_STATIC_PRECOMPUTATION | ||||
|     ctx->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*ctx->prec)); | ||||
| 
 | ||||
|     /* get the generator */ | ||||
| @ -75,6 +79,9 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *c | ||||
|             secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); | ||||
|         } | ||||
|     } | ||||
| #else | ||||
|     ctx->prec = (secp256k1_ge_storage_t (*)[64][16])secp256k1_ecmult_static_context; | ||||
| #endif | ||||
|     secp256k1_ecmult_gen_blind(ctx, NULL); | ||||
| } | ||||
| 
 | ||||
| @ -87,15 +94,21 @@ static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context_t *d | ||||
|     if (src->prec == NULL) { | ||||
|         dst->prec = NULL; | ||||
|     } else { | ||||
| #ifndef USE_ECMULT_STATIC_PRECOMPUTATION | ||||
|         dst->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*dst->prec)); | ||||
|         memcpy(dst->prec, src->prec, sizeof(*dst->prec)); | ||||
| #else | ||||
|         dst->prec = src->prec; | ||||
| #endif | ||||
|         dst->initial = src->initial; | ||||
|         dst->blind = src->blind; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) { | ||||
| #ifndef USE_ECMULT_STATIC_PRECOMPUTATION | ||||
|     free(ctx->prec); | ||||
| #endif | ||||
|     secp256k1_scalar_clear(&ctx->blind); | ||||
|     secp256k1_gej_clear(&ctx->initial); | ||||
|     ctx->prec = NULL; | ||||
|  | ||||
| @ -43,5 +43,5 @@ typedef struct { | ||||
| } secp256k1_fe_storage_t; | ||||
| 
 | ||||
| #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} | ||||
| 
 | ||||
| #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										63
									
								
								src/gen_context.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/gen_context.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| /**********************************************************************
 | ||||
|  * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields           * | ||||
|  * Distributed under the MIT software license, see the accompanying   * | ||||
|  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||
|  **********************************************************************/ | ||||
| 
 | ||||
| #define USE_BASIC_CONFIG 1 | ||||
| 
 | ||||
| #include "basic-config.h" | ||||
| #include "include/secp256k1.h" | ||||
| #include "field_impl.h" | ||||
| #include "scalar_impl.h" | ||||
| #include "group_impl.h" | ||||
| #include "ecmult_gen_impl.h" | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
|     secp256k1_ecmult_gen_context_t ctx; | ||||
|     int inner; | ||||
|     int outer; | ||||
|     FILE* fp; | ||||
| 
 | ||||
|     (void)argc; | ||||
|     (void)argv; | ||||
| 
 | ||||
|     fp = fopen("src/ecmult_static_context.h","w"); | ||||
|     if (fp == NULL) { | ||||
|         fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); | ||||
|     fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); | ||||
|     fprintf(fp, "#include \"group.h\"\n"); | ||||
|     fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); | ||||
|     fprintf(fp, "static const secp256k1_ge_storage_t secp256k1_ecmult_static_context[64][16] = {\n"); | ||||
| 
 | ||||
|     secp256k1_ecmult_gen_context_init(&ctx); | ||||
|     secp256k1_ecmult_gen_context_build(&ctx); | ||||
|     for(outer = 0; outer != 64; outer++) { | ||||
|         fprintf(fp,"{\n"); | ||||
|         for(inner = 0; inner != 16; inner++) { | ||||
|             fprintf(fp,"    SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); | ||||
|             if (inner != 15) { | ||||
|                 fprintf(fp,",\n"); | ||||
|             } else { | ||||
|                 fprintf(fp,"\n"); | ||||
|             } | ||||
|         } | ||||
|         if (outer != 63) { | ||||
|             fprintf(fp,"},\n"); | ||||
|         } else { | ||||
|             fprintf(fp,"}\n"); | ||||
|         } | ||||
|     } | ||||
|     fprintf(fp,"};\n"); | ||||
|     secp256k1_ecmult_gen_context_clear(&ctx); | ||||
|      | ||||
|     fprintf(fp, "#undef SC\n"); | ||||
|     fprintf(fp, "#endif\n"); | ||||
|     fclose(fp); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
| @ -38,6 +38,8 @@ typedef struct { | ||||
| 
 | ||||
| #define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} | ||||
| 
 | ||||
| #define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) | ||||
| 
 | ||||
| /** Set a group element equal to the point at infinity */ | ||||
| static void secp256k1_ge_set_infinity(secp256k1_ge_t *r); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user