Add ECDH module which works by hashing the output of ecmult_const
This commit is contained in:
		
							parent
							
								
									4401500060
								
							
						
					
					
						commit
						0739bbb6f0
					
				| @ -8,12 +8,14 @@ compiler: | |||||||
|   - gcc |   - gcc | ||||||
| env: | env: | ||||||
|   global: |   global: | ||||||
|     - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=no ASM=no  BUILD=check  EXTRAFLAGS= HOST= |     - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=no ASM=no  BUILD=check  EXTRAFLAGS= HOST= ECDH=no | ||||||
|   matrix: |   matrix: | ||||||
|     - SCALAR=32bit |     - SCALAR=32bit | ||||||
|  |     - SCALAR=32bit    FIELD=32bit       ECDH=yes | ||||||
|     - SCALAR=64bit |     - SCALAR=64bit | ||||||
|     - FIELD=64bit |     - FIELD=64bit | ||||||
|     - FIELD=64bit     ENDOMORPHISM=yes |     - FIELD=64bit     ENDOMORPHISM=yes | ||||||
|  |     - FIELD=64bit     ENDOMORPHISM=yes  ECDH=yes | ||||||
|     - FIELD=64bit                       ASM=x86_64 |     - FIELD=64bit                       ASM=x86_64 | ||||||
|     - FIELD=64bit     ENDOMORPHISM=yes  ASM=x86_64 |     - FIELD=64bit     ENDOMORPHISM=yes  ASM=x86_64 | ||||||
|     - FIELD=32bit |     - FIELD=32bit | ||||||
| @ -56,5 +58,5 @@ before_script: ./autogen.sh | |||||||
| script: | script: | ||||||
|  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi |  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi | ||||||
|  - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi |  - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi | ||||||
|  - ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION $EXTRAFLAGS $USE_HOST && make -j2 $BUILD |  - ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH $EXTRAFLAGS $USE_HOST && make -j2 $BUILD | ||||||
| os: linux | os: linux | ||||||
|  | |||||||
| @ -97,3 +97,7 @@ CLEANFILES = gen_context src/ecmult_static_context.h | |||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h | EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h | ||||||
|  | 
 | ||||||
|  | if ENABLE_MODULE_ECDH | ||||||
|  | include src/modules/ecdh/Makefile.am.include | ||||||
|  | endif | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							| @ -102,6 +102,11 @@ AC_ARG_ENABLE(ecmult_static_precomputation, | |||||||
|     [use_ecmult_static_precomputation=$enableval], |     [use_ecmult_static_precomputation=$enableval], | ||||||
|     [use_ecmult_static_precomputation=yes]) |     [use_ecmult_static_precomputation=yes]) | ||||||
| 
 | 
 | ||||||
|  | AC_ARG_ENABLE(module_ecdh, | ||||||
|  |     AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (default is no)]), | ||||||
|  |     [enable_module_ecdh=$enableval], | ||||||
|  |     [enable_module_ecdh=no]) | ||||||
|  | 
 | ||||||
| AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], | AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], | ||||||
| [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) | [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) | ||||||
| 
 | 
 | ||||||
| @ -315,6 +320,10 @@ 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]) |   AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
|  | if test x"$enable_module_ecdh" = x"yes"; then | ||||||
|  |   AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) | ||||||
|  | fi | ||||||
|  | 
 | ||||||
| AC_C_BIGENDIAN() | AC_C_BIGENDIAN() | ||||||
| 
 | 
 | ||||||
| AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) | AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) | ||||||
| @ -322,6 +331,7 @@ AC_MSG_NOTICE([Using field implementation: $set_field]) | |||||||
| AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) | AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) | ||||||
| AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) | AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) | ||||||
| AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) | AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) | ||||||
|  | AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) | ||||||
| 
 | 
 | ||||||
| AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) | AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) | ||||||
| AC_CONFIG_FILES([Makefile libsecp256k1.pc]) | AC_CONFIG_FILES([Makefile libsecp256k1.pc]) | ||||||
| @ -332,6 +342,7 @@ AC_SUBST(SECP_TEST_INCLUDES) | |||||||
| AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) | AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) | ||||||
| AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) | AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) | ||||||
| AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_precomputation" = x"yes"]) | AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_precomputation" = x"yes"]) | ||||||
|  | AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) | ||||||
| 
 | 
 | ||||||
| dnl make sure nothing new is exported so that we don't break the cache | dnl make sure nothing new is exported so that we don't break the cache | ||||||
| PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" | PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								include/secp256k1_ecdh.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/secp256k1_ecdh.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | #ifndef _SECP256K1_ECDH_ | ||||||
|  | # define _SECP256K1_ECDH_ | ||||||
|  | 
 | ||||||
|  | # include "secp256k1.h" | ||||||
|  | 
 | ||||||
|  | # ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | # endif | ||||||
|  | 
 | ||||||
|  | /** Compute an EC Diffie-Hellman secret in constant time
 | ||||||
|  |  *  Returns: 1: exponentiation was successful | ||||||
|  |  *           0: scalar was invalid (zero or overflow) | ||||||
|  |  *  In:      ctx:      pointer to a context object (cannot be NULL) | ||||||
|  |  *           point:    pointer to a public point | ||||||
|  |  *           scalar:   a 32-byte scalar with which to multiply the point | ||||||
|  |  *  Out:     result:   a 32-byte array which will be populated by an ECDH | ||||||
|  |  *                     secret computed from the point and scalar | ||||||
|  |  */ | ||||||
|  | SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( | ||||||
|  |   const secp256k1_context_t* ctx, | ||||||
|  |   unsigned char *result, | ||||||
|  |   const secp256k1_pubkey_t *point, | ||||||
|  |   const unsigned char *scalar | ||||||
|  | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); | ||||||
|  | 
 | ||||||
|  | # ifdef __cplusplus | ||||||
|  | } | ||||||
|  | # endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										3
									
								
								src/modules/ecdh/Makefile.am.include
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/modules/ecdh/Makefile.am.include
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | include_HEADERS += include/secp256k1_ecdh.h | ||||||
|  | noinst_HEADERS += src/modules/ecdh/main_impl.h | ||||||
|  | noinst_HEADERS += src/modules/ecdh/tests_impl.h | ||||||
							
								
								
									
										53
									
								
								src/modules/ecdh/main_impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/modules/ecdh/main_impl.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | /**********************************************************************
 | ||||||
|  |  * Copyright (c) 2015 Andrew Poelstra                                 * | ||||||
|  |  * Distributed under the MIT software license, see the accompanying   * | ||||||
|  |  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||||
|  |  **********************************************************************/ | ||||||
|  | 
 | ||||||
|  | #ifndef _SECP256K1_MODULE_ECDH_MAIN_ | ||||||
|  | #define _SECP256K1_MODULE_ECDH_MAIN_ | ||||||
|  | 
 | ||||||
|  | #include "ecmult_const_impl.h" | ||||||
|  | 
 | ||||||
|  | int secp256k1_ecdh(const secp256k1_context_t* ctx, unsigned char *result, const secp256k1_pubkey_t *point, const unsigned char *scalar) { | ||||||
|  |     int ret = 0; | ||||||
|  |     int overflow = 0; | ||||||
|  |     secp256k1_gej_t res; | ||||||
|  |     secp256k1_ge_t pt; | ||||||
|  |     secp256k1_scalar_t s; | ||||||
|  |     ARG_CHECK(result != NULL); | ||||||
|  |     ARG_CHECK(point != NULL); | ||||||
|  |     ARG_CHECK(scalar != NULL); | ||||||
|  |     (void)ctx; | ||||||
|  | 
 | ||||||
|  |     secp256k1_pubkey_load(ctx, &pt, point); | ||||||
|  |     secp256k1_scalar_set_b32(&s, scalar, &overflow); | ||||||
|  |     if (overflow || secp256k1_scalar_is_zero(&s)) { | ||||||
|  |         ret = 0; | ||||||
|  |     } else { | ||||||
|  |         unsigned char x[32]; | ||||||
|  |         unsigned char y[1]; | ||||||
|  |         secp256k1_sha256_t sha; | ||||||
|  | 
 | ||||||
|  |         secp256k1_ecmult_const(&res, &pt, &s); | ||||||
|  |         secp256k1_ge_set_gej(&pt, &res); | ||||||
|  |         /* Compute a hash of the point in compressed form
 | ||||||
|  |          * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not | ||||||
|  |          * expect its output to be secret and has a timing sidechannel. */ | ||||||
|  |         secp256k1_fe_normalize(&pt.x); | ||||||
|  |         secp256k1_fe_normalize(&pt.y); | ||||||
|  |         secp256k1_fe_get_b32(x, &pt.x); | ||||||
|  |         y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); | ||||||
|  | 
 | ||||||
|  |         secp256k1_sha256_initialize(&sha); | ||||||
|  |         secp256k1_sha256_write(&sha, y, sizeof(y)); | ||||||
|  |         secp256k1_sha256_write(&sha, x, sizeof(x)); | ||||||
|  |         secp256k1_sha256_finalize(&sha, result); | ||||||
|  |         ret = 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     secp256k1_scalar_clear(&s); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										75
									
								
								src/modules/ecdh/tests_impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/modules/ecdh/tests_impl.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | /**********************************************************************
 | ||||||
|  |  * Copyright (c) 2015 Andrew Poelstra                                 * | ||||||
|  |  * Distributed under the MIT software license, see the accompanying   * | ||||||
|  |  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||||
|  |  **********************************************************************/ | ||||||
|  | 
 | ||||||
|  | #ifndef _SECP256K1_MODULE_ECDH_TESTS_ | ||||||
|  | #define _SECP256K1_MODULE_ECDH_TESTS_ | ||||||
|  | 
 | ||||||
|  | void test_ecdh_generator_basepoint(void) { | ||||||
|  |     unsigned char s_one[32] = { 0 }; | ||||||
|  |     secp256k1_pubkey_t point[2]; | ||||||
|  |     int i; | ||||||
|  | 
 | ||||||
|  |     s_one[31] = 1; | ||||||
|  |     /* Check against pubkey creation when the basepoint is the generator */ | ||||||
|  |     for (i = 0; i < 100; ++i) { | ||||||
|  |         secp256k1_sha256_t sha; | ||||||
|  |         unsigned char s_b32[32]; | ||||||
|  |         unsigned char output_ecdh[32]; | ||||||
|  |         unsigned char output_ser[32]; | ||||||
|  |         unsigned char point_ser[33]; | ||||||
|  |         int point_ser_len = sizeof(point_ser); | ||||||
|  |         secp256k1_scalar_t s; | ||||||
|  | 
 | ||||||
|  |         random_scalar_order(&s); | ||||||
|  |         secp256k1_scalar_get_b32(s_b32, &s); | ||||||
|  | 
 | ||||||
|  |         /* compute using ECDH function */ | ||||||
|  |         CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); | ||||||
|  |         CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); | ||||||
|  |         /* compute "explicitly" */ | ||||||
|  |         CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); | ||||||
|  |         CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], 1) == 1); | ||||||
|  |         CHECK(point_ser_len == sizeof(point_ser)); | ||||||
|  |         secp256k1_sha256_initialize(&sha); | ||||||
|  |         secp256k1_sha256_write(&sha, point_ser, point_ser_len); | ||||||
|  |         secp256k1_sha256_finalize(&sha, output_ser); | ||||||
|  |         /* compare */ | ||||||
|  |         CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_bad_scalar(void) { | ||||||
|  |     unsigned char s_zero[32] = { 0 }; | ||||||
|  |     unsigned char s_overflow[32] = { | ||||||
|  |         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||||||
|  |         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, | ||||||
|  |         0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, | ||||||
|  |         0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 | ||||||
|  |     }; | ||||||
|  |     unsigned char s_rand[32] = { 0 }; | ||||||
|  |     unsigned char output[32]; | ||||||
|  |     secp256k1_scalar_t rand; | ||||||
|  |     secp256k1_pubkey_t point; | ||||||
|  | 
 | ||||||
|  |     /* Create random point */ | ||||||
|  |     random_scalar_order(&rand); | ||||||
|  |     secp256k1_scalar_get_b32(s_rand, &rand); | ||||||
|  |     CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); | ||||||
|  | 
 | ||||||
|  |     /* Try to multiply it by bad values */ | ||||||
|  |     CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); | ||||||
|  |     CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); | ||||||
|  |     /* ...and a good one */ | ||||||
|  |     s_overflow[31] -= 1; | ||||||
|  |     CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void run_ecdh_tests(void) { | ||||||
|  |     test_ecdh_generator_basepoint(); | ||||||
|  |     test_bad_scalar(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -526,3 +526,7 @@ int secp256k1_context_randomize(secp256k1_context_t* ctx, const unsigned char *s | |||||||
|     secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); |     secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #ifdef ENABLE_MODULE_ECDH | ||||||
|  | # include "modules/ecdh/main_impl.h" | ||||||
|  | #endif | ||||||
|  | |||||||
| @ -2356,6 +2356,10 @@ void run_ecdsa_openssl(void) { | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef ENABLE_MODULE_ECDH | ||||||
|  | # include "modules/ecdh/tests_impl.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
|     unsigned char seed16[16] = {0}; |     unsigned char seed16[16] = {0}; | ||||||
|     unsigned char run32[32] = {0}; |     unsigned char run32[32] = {0}; | ||||||
| @ -2444,6 +2448,11 @@ int main(int argc, char **argv) { | |||||||
|     run_endomorphism_tests(); |     run_endomorphism_tests(); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef ENABLE_MODULE_ECDH | ||||||
|  |     /* ecdh tests */ | ||||||
|  |     run_ecdh_tests(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     /* ecdsa tests */ |     /* ecdsa tests */ | ||||||
|     run_random_pubkeys(); |     run_random_pubkeys(); | ||||||
|     run_ecdsa_sign_verify(); |     run_ecdsa_sign_verify(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user