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 | ||||
| env: | ||||
|   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: | ||||
|     - SCALAR=32bit | ||||
|     - SCALAR=32bit    FIELD=32bit       ECDH=yes | ||||
|     - SCALAR=64bit | ||||
|     - FIELD=64bit | ||||
|     - FIELD=64bit     ENDOMORPHISM=yes | ||||
|     - FIELD=64bit     ENDOMORPHISM=yes  ECDH=yes | ||||
|     - FIELD=64bit                       ASM=x86_64 | ||||
|     - FIELD=64bit     ENDOMORPHISM=yes  ASM=x86_64 | ||||
|     - FIELD=32bit | ||||
| @ -56,5 +58,5 @@ before_script: ./autogen.sh | ||||
| script: | ||||
|  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; 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 | ||||
|  | ||||
| @ -97,3 +97,7 @@ CLEANFILES = gen_context src/ecmult_static_context.h | ||||
| endif | ||||
| 
 | ||||
| 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=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], | ||||
| [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]) | ||||
| 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_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 scalar implementation: $set_scalar]) | ||||
| 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_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_BENCHMARK], [test x"$use_benchmark" = 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 | ||||
| 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); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #ifdef ENABLE_MODULE_ECDH | ||||
| # include "modules/ecdh/main_impl.h" | ||||
| #endif | ||||
|  | ||||
| @ -2356,6 +2356,10 @@ void run_ecdsa_openssl(void) { | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ENABLE_MODULE_ECDH | ||||
| # include "modules/ecdh/tests_impl.h" | ||||
| #endif | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
|     unsigned char seed16[16] = {0}; | ||||
|     unsigned char run32[32] = {0}; | ||||
| @ -2444,6 +2448,11 @@ int main(int argc, char **argv) { | ||||
|     run_endomorphism_tests(); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ENABLE_MODULE_ECDH | ||||
|     /* ecdh tests */ | ||||
|     run_ecdh_tests(); | ||||
| #endif | ||||
| 
 | ||||
|     /* ecdsa tests */ | ||||
|     run_random_pubkeys(); | ||||
|     run_ecdsa_sign_verify(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user