From f51c8fc353190fce2a2cb46f77fced2cc19cc3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 10 Jan 2014 18:17:18 +0100 Subject: [PATCH 1/8] Add support for secp256k1 arithmetic --- include/polarssl/config.h | 3 +++ include/polarssl/ecp.h | 3 +++ library/ecp_curves.c | 38 ++++++++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 4 ++++ 4 files changed, 48 insertions(+) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index ca0c1763f..19d5c6f1b 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -259,6 +259,9 @@ #define POLARSSL_ECP_DP_SECP256R1_ENABLED #define POLARSSL_ECP_DP_SECP384R1_ENABLED #define POLARSSL_ECP_DP_SECP521R1_ENABLED +//#define POLARSSL_ECP_DP_SECP192K1_ENABLED // Not implemented yet! +//#define POLARSSL_ECP_DP_SECP224K1_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_SECP256K1_ENABLED #define POLARSSL_ECP_DP_BP256R1_ENABLED #define POLARSSL_ECP_DP_BP384R1_ENABLED #define POLARSSL_ECP_DP_BP512R1_ENABLED diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 1e9e73786..1bc989ec5 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -68,6 +68,9 @@ typedef enum POLARSSL_ECP_DP_M255, /*!< Curve25519 */ POLARSSL_ECP_DP_M383, /*!< (not implemented yet) */ POLARSSL_ECP_DP_M511, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_SECP192K1, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_SECP224K1, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_SECP256K1, /*!< 256-bits Koblitz curve */ } ecp_group_id; /** diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 706e0ee4d..762c3f248 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -318,6 +318,39 @@ static t_uint secp521r1_n[] = { }; #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static t_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static t_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static t_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static t_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static t_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static t_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + /* * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) */ @@ -648,6 +681,11 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) return( LOAD_GROUP( secp521r1 ) ); #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + case POLARSSL_ECP_DP_SECP256K1: + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + #if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) case POLARSSL_ECP_DP_BP256R1: return( LOAD_GROUP_A( brainpoolP256r1 ) ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 8cce3e62e..b7aa06fcd 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -423,5 +423,9 @@ ECP test vectors M255 aka Curve25519 depends_on:POLARSSL_ECP_DP_M255_ENABLED ecp_test_vec_x:POLARSSL_ECP_DP_M255:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"057E23EA9F1CBE8A27168F6E696A791DE61DD3AF7ACD4EEACC6E7BA514FDA863":"47DC3D214174820E1154B49BC6CDB2ABD45EE95817055D255AA35831B70D3260":"6EB89DA91989AE37C7EAC7618D9E5C4951DBA1D73C285AE1CD26A855020EEF04":"61450CD98E36016B58776A897A9F0AEF738B99F09468B8D6B8511184D53494AB" +ECP test vectors secp256k1 +depends_on:POLARSSL_ECP_DP_SECP256K1_ENABLED +ecp_test_vect:POLARSSL_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938E6D60246030AE4B0D8D4E9DE":"20A865B295E93C5B090F324B84D7AC7526AA1CFE86DD80E792CECCD16B657D55":"38AC87141A4854A8DFD87333E107B61692323721FE2EAD6E52206FE471A4771B":"4F5036A8ED5809AB7E70AEDA68A174ECC1F3800561B2D4FABE97C5D2A1A94D08":"029F5D2CC5A2C7E538FBA321439B4EC8DD79B7FEB9C0A8A5114EEA39856E22E8":"165171AFC3411A427F24FDDE1192A551C90983EB421BC982AB4CF4E21F18F04B":"E4B5B537D3ACEA7624F2E9C185BFFD80BC7035E515F33E0D4CFAE747FD20038E":"2BC685B7DCDBC694F5E036C4EAE9BFB489D7BF8940C4681F734B71D68501514C" + ECP selftest ecp_selftest: From 9bcff3905bdf6ee22b6dac786ac4f073889f7bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 10 Jan 2014 18:26:48 +0100 Subject: [PATCH 2/8] Add OIDs and TLS IDs for prime Koblitz curves --- include/polarssl/ecp.h | 2 +- include/polarssl/oid.h | 14 +++++++++++++- library/ecp.c | 9 +++++++++ library/oid.c | 12 ++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 1bc989ec5..d98146c95 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -78,7 +78,7 @@ typedef enum * * (Montgomery curves excluded for now.) */ -#define POLARSSL_ECP_DP_MAX 9 +#define POLARSSL_ECP_DP_MAX 12 /** * Curve information for use by other modules diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index 93ef8a6ab..f000b8e7e 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -263,7 +263,7 @@ #define OID_EC_ALG_ECDH OID_CERTICOM "\x01\x0c" /* - * ECParameters namedCurve identifiers, from RFC 5480 and RFC 5639 + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 */ /* secp192r1 OBJECT IDENTIFIER ::= { @@ -286,6 +286,18 @@ * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ #define OID_EC_GRP_SECP521R1 OID_CERTICOM "\x00\x23" +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define OID_EC_GRP_SECP192K1 OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define OID_EC_GRP_SECP224K1 OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define OID_EC_GRP_SECP256K1 OID_CERTICOM "\x00\x0a" + /* RFC 5639 4.1 * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) * identified-organization(3) teletrust(36) algorithm(3) signature- diff --git a/library/ecp.c b/library/ecp.c index 8b34bf375..0bef9553b 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -140,6 +140,15 @@ static const ecp_curve_info ecp_supported_curves[] = #endif #if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) { POLARSSL_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + { POLARSSL_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + { POLARSSL_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + { POLARSSL_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, #endif { POLARSSL_ECP_DP_NONE, 0, 0, NULL }, }; diff --git a/library/oid.c b/library/oid.c index b0b551dea..f943c6d34 100644 --- a/library/oid.c +++ b/library/oid.c @@ -402,6 +402,18 @@ static const oid_ecp_grp_t oid_ecp_grp[] = { ADD_LEN( OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, POLARSSL_ECP_DP_SECP521R1, }, + { + { ADD_LEN( OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + POLARSSL_ECP_DP_SECP192K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + POLARSSL_ECP_DP_SECP224K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + POLARSSL_ECP_DP_SECP256K1, + }, { { ADD_LEN( OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, POLARSSL_ECP_DP_BP256R1, From 18e3ec9b4d5076413965a792314b35e39b5dd151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 11 Jan 2014 15:22:07 +0100 Subject: [PATCH 3/8] Add support for secp224k1 --- include/polarssl/config.h | 2 +- library/ecp_curves.c | 38 ++++++++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 4 ++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 19d5c6f1b..f879016c5 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -260,7 +260,7 @@ #define POLARSSL_ECP_DP_SECP384R1_ENABLED #define POLARSSL_ECP_DP_SECP521R1_ENABLED //#define POLARSSL_ECP_DP_SECP192K1_ENABLED // Not implemented yet! -//#define POLARSSL_ECP_DP_SECP224K1_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_SECP224K1_ENABLED #define POLARSSL_ECP_DP_SECP256K1_ENABLED #define POLARSSL_ECP_DP_BP256R1_ENABLED #define POLARSSL_ECP_DP_BP384R1_ENABLED diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 762c3f248..41fa2f345 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -318,6 +318,39 @@ static t_uint secp521r1_n[] = { }; #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static t_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static t_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static t_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static t_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static t_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static t_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + #if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) static t_uint secp256k1_p[] = { BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), @@ -681,6 +714,11 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) return( LOAD_GROUP( secp521r1 ) ); #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + case POLARSSL_ECP_DP_SECP224K1: + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + #if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) case POLARSSL_ECP_DP_SECP256K1: return( LOAD_GROUP_A( secp256k1 ) ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index b7aa06fcd..960675fa2 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -423,6 +423,10 @@ ECP test vectors M255 aka Curve25519 depends_on:POLARSSL_ECP_DP_M255_ENABLED ecp_test_vec_x:POLARSSL_ECP_DP_M255:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"057E23EA9F1CBE8A27168F6E696A791DE61DD3AF7ACD4EEACC6E7BA514FDA863":"47DC3D214174820E1154B49BC6CDB2ABD45EE95817055D255AA35831B70D3260":"6EB89DA91989AE37C7EAC7618D9E5C4951DBA1D73C285AE1CD26A855020EEF04":"61450CD98E36016B58776A897A9F0AEF738B99F09468B8D6B8511184D53494AB" +ECP test vectors secp224k1 +depends_on:POLARSSL_ECP_DP_SECP224K1_ENABLED +ecp_test_vect:POLARSSL_ECP_DP_SECP224K1:"8EAD9B2819A3C2746B3EDC1E0D30F23271CDAC048C0615C961B1A9D3":"DEE0A75EF26CF8F501DB80807A3A0908E5CF01852709C1D35B31428B":"276D2B817918F7CD1DA5CCA081EC4B62CD255E0ACDC9F85FA8C52CAC":"AB7E70AEDA68A174ECC1F3800561B2D4FABE97C5D2A1A94D081E3FAC":"D2E94B00FD30201C40EDF73B137427916687AEA1935B277A5960DD1C":"DE728A614B17D91EB3CB2C17DA195562B6281585986332B3E12DA0ED":"B66B673D29038A3487A2D9C10CDCE67646F7C39C984EBE9E8795AD3C":"928C6147AF5EE4B54FA6ECF77B70CA3FEE5F4182DB057878F129DF": + ECP test vectors secp256k1 depends_on:POLARSSL_ECP_DP_SECP256K1_ENABLED ecp_test_vect:POLARSSL_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938E6D60246030AE4B0D8D4E9DE":"20A865B295E93C5B090F324B84D7AC7526AA1CFE86DD80E792CECCD16B657D55":"38AC87141A4854A8DFD87333E107B61692323721FE2EAD6E52206FE471A4771B":"4F5036A8ED5809AB7E70AEDA68A174ECC1F3800561B2D4FABE97C5D2A1A94D08":"029F5D2CC5A2C7E538FBA321439B4EC8DD79B7FEB9C0A8A5114EEA39856E22E8":"165171AFC3411A427F24FDDE1192A551C90983EB421BC982AB4CF4E21F18F04B":"E4B5B537D3ACEA7624F2E9C185BFFD80BC7035E515F33E0D4CFAE747FD20038E":"2BC685B7DCDBC694F5E036C4EAE9BFB489D7BF8940C4681F734B71D68501514C" From 5304812b2d228fa6e0e769017d9c004fee272e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 3 Jan 2014 12:55:15 +0100 Subject: [PATCH 4/8] Fix theoretical compliance issue in ECDSA The issue would happen for curves whose bitlength is not a multiple of eight (the only case is NIST P-521) with hashes that are longer than the bitlength of the curve: since the wides hash is 512 bits long, this can't happen. Fixing however as a matter of principle and readability. --- library/ecdsa.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 2072d5559..6f099943e 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -43,8 +43,16 @@ static int derive_mpi( const ecp_group *grp, mpi *x, const unsigned char *buf, size_t blen ) { + int ret; size_t n_size = (grp->nbits + 7) / 8; - return( mpi_read_binary( x, buf, blen > n_size ? n_size : blen ) ); + size_t use_size = blen > n_size ? n_size : blen; + + MPI_CHK( mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + +cleanup: + return( ret ); } /* From 0a56c2c6984cf62cb6408c002a2ff1ab7b542138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 17 Jan 2014 21:24:04 +0100 Subject: [PATCH 5/8] Fix bug in ecdh_calc_secret() Only affects curves with nbits != pbits (currently only secp224k1) --- library/ecdh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ecdh.c b/library/ecdh.c index 302531db8..ebc167674 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -246,7 +246,7 @@ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, if( mpi_size( &ctx->z ) > blen ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); - *olen = ctx->grp.nbits / 8 + ( ( ctx->grp.nbits % 8 ) != 0 ); + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); return mpi_write_binary( &ctx->z, buf, *olen ); } From ea499a73216357372708f689e2916c2f6601f7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 11 Jan 2014 15:58:47 +0100 Subject: [PATCH 6/8] Add support for secp192k1 --- include/polarssl/config.h | 2 +- library/ecp_curves.c | 34 ++++++++++++++++++++++++++++++++ tests/suites/test_suite_ecp.data | 4 ++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index f879016c5..42556dda9 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -259,7 +259,7 @@ #define POLARSSL_ECP_DP_SECP256R1_ENABLED #define POLARSSL_ECP_DP_SECP384R1_ENABLED #define POLARSSL_ECP_DP_SECP521R1_ENABLED -//#define POLARSSL_ECP_DP_SECP192K1_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_SECP192K1_ENABLED #define POLARSSL_ECP_DP_SECP224K1_ENABLED #define POLARSSL_ECP_DP_SECP256K1_ENABLED #define POLARSSL_ECP_DP_BP256R1_ENABLED diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 41fa2f345..4ebe31c64 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -318,6 +318,35 @@ static t_uint secp521r1_n[] = { }; #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static t_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static t_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static t_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static t_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static t_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static t_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + #if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) static t_uint secp224k1_p[] = { BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), @@ -714,6 +743,11 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) return( LOAD_GROUP( secp521r1 ) ); #endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + case POLARSSL_ECP_DP_SECP192K1: + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + #if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) case POLARSSL_ECP_DP_SECP224K1: return( LOAD_GROUP_A( secp224k1 ) ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 960675fa2..444e207db 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -423,6 +423,10 @@ ECP test vectors M255 aka Curve25519 depends_on:POLARSSL_ECP_DP_M255_ENABLED ecp_test_vec_x:POLARSSL_ECP_DP_M255:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"057E23EA9F1CBE8A27168F6E696A791DE61DD3AF7ACD4EEACC6E7BA514FDA863":"47DC3D214174820E1154B49BC6CDB2ABD45EE95817055D255AA35831B70D3260":"6EB89DA91989AE37C7EAC7618D9E5C4951DBA1D73C285AE1CD26A855020EEF04":"61450CD98E36016B58776A897A9F0AEF738B99F09468B8D6B8511184D53494AB" +ECP test vectors secp192k1 +depends_on:POLARSSL_ECP_DP_SECP192K1_ENABLED +ecp_test_vect:POLARSSL_ECP_DP_SECP192K1:"D1E13A359F6E0F0698791938E6D60246030AE4B0D8D4E9DE":"281BCA982F187ED30AD5E088461EBE0A5FADBB682546DF79":"3F68A8E9441FB93A4DD48CB70B504FCC9AA01902EF5BE0F3":"BE97C5D2A1A94D081E3FACE53E65A27108B7467BDF58DE43":"5EB35E922CD693F7947124F5920022C4891C04F6A8B8DCB2":"60ECF73D0FC43E0C42E8E155FFE39F9F0B531F87B34B6C3C":"372F5C5D0E18313C82AEF940EC3AFEE26087A46F1EBAE923":"D5A9F9182EC09CEAEA5F57EA10225EC77FA44174511985FD" + ECP test vectors secp224k1 depends_on:POLARSSL_ECP_DP_SECP224K1_ENABLED ecp_test_vect:POLARSSL_ECP_DP_SECP224K1:"8EAD9B2819A3C2746B3EDC1E0D30F23271CDAC048C0615C961B1A9D3":"DEE0A75EF26CF8F501DB80807A3A0908E5CF01852709C1D35B31428B":"276D2B817918F7CD1DA5CCA081EC4B62CD255E0ACDC9F85FA8C52CAC":"AB7E70AEDA68A174ECC1F3800561B2D4FABE97C5D2A1A94D081E3FAC":"D2E94B00FD30201C40EDF73B137427916687AEA1935B277A5960DD1C":"DE728A614B17D91EB3CB2C17DA195562B6281585986332B3E12DA0ED":"B66B673D29038A3487A2D9C10CDCE67646F7C39C984EBE9E8795AD3C":"928C6147AF5EE4B54FA6ECF77B70CA3FEE5F4182DB057878F129DF": From 8887d8d37ca9aee96a17d9fff716e50d9b2c03e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 17 Jan 2014 23:17:10 +0100 Subject: [PATCH 7/8] Add mod_p256k1 Makes secp256k1 about 4x faster --- library/ecp_curves.c | 90 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 4ebe31c64..366f7fa19 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -643,15 +643,20 @@ static int ecp_mod_p384( mpi * ); #if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) static int ecp_mod_p521( mpi * ); #endif -#if defined(POLARSSL_ECP_DP_M255_ENABLED) -static int ecp_mod_p255( mpi * ); -#endif #define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; #else #define NIST_MODP( P ) #endif /* POLARSSL_ECP_NIST_OPTIM */ +/* Additional forward declarations */ +#if defined(POLARSSL_ECP_DP_M255_ENABLED) +static int ecp_mod_p255( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mpi * ); +#endif + #define LOAD_GROUP_A( G ) ecp_group_load( grp, \ G ## _p, sizeof( G ## _p ), \ G ## _a, sizeof( G ## _a ), \ @@ -755,6 +760,7 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) #if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) case POLARSSL_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; return( LOAD_GROUP_A( secp256k1 ) ); #endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ @@ -1195,7 +1201,7 @@ cleanup: /* * Fast quasi-reduction modulo p255 = 2^255 - 19 - * Write N as A1 + 2^255 A1, return A0 + 19 * A1 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 */ static int ecp_mod_p255( mpi *N ) { @@ -1232,4 +1238,80 @@ cleanup: } #endif /* POLARSSL_ECP_DP_M255_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + +/* Size of p256k1 in terms of t_uint */ +#define P256K1_WIDTH ( 256 / 8 / sizeof( t_uint ) ) + +/* Value of R (see below) */ +static t_uint p256k1_r_p[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#define P256K1_R_WIDTH ( sizeof( p256k1_r_p ) / sizeof( t_uint ) ) + +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 4294968273 + * + * Write N as A0 + 2^256 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +static int ecp_mod_p256k1( mpi *N ) +{ + int ret; + size_t i; + mpi M, R; + t_uint Mp[P256K1_WIDTH + P256K1_R_WIDTH]; + + if( N->n < P256K1_WIDTH ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = p256k1_r_p; + R.n = P256K1_R_WIDTH; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - P256K1_WIDTH; + if( M.n > P256K1_WIDTH ) + M.n = P256K1_WIDTH; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P256K1_WIDTH, M.n * sizeof( t_uint ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + for( i = P256K1_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - P256K1_WIDTH; + if( M.n > P256K1_WIDTH ) + M.n = P256K1_WIDTH; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P256K1_WIDTH, M.n * sizeof( t_uint ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + for( i = P256K1_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + #endif From 9af7d3a35be835e48f4aa9a23d7869e339d84a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 18 Jan 2014 17:28:59 +0100 Subject: [PATCH 8/8] Add fast reduction for the other Koblitz curves --- library/ecp_curves.c | 121 ++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 366f7fa19..db158fe41 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -653,6 +653,12 @@ static int ecp_mod_p521( mpi * ); #if defined(POLARSSL_ECP_DP_M255_ENABLED) static int ecp_mod_p255( mpi * ); #endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mpi * ); +#endif #if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) static int ecp_mod_p256k1( mpi * ); #endif @@ -750,11 +756,13 @@ int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) #if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) case POLARSSL_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; return( LOAD_GROUP_A( secp192k1 ) ); #endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ #if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) case POLARSSL_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; return( LOAD_GROUP_A( secp224k1 ) ); #endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ @@ -1238,53 +1246,52 @@ cleanup: } #endif /* POLARSSL_ECP_DP_M255_ENABLED */ -#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) - -/* Size of p256k1 in terms of t_uint */ -#define P256K1_WIDTH ( 256 / 8 / sizeof( t_uint ) ) - -/* Value of R (see below) */ -static t_uint p256k1_r_p[] = { - BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), -}; -#define P256K1_R_WIDTH ( sizeof( p256k1_r_p ) / sizeof( t_uint ) ) - +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) /* - * Fast quasi-reduction modulo p256k1 = 2^256 - R, - * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 4294968273 + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. * - * Write N as A0 + 2^256 A1, return A0 + R * A1. + * Write N as A0 + 2^224 A1, return A0 + R * A1. * Actually do two passes, since R is big. */ -static int ecp_mod_p256k1( mpi *N ) +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( t_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( t_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mpi *N, t_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, t_uint mask ) { int ret; size_t i; mpi M, R; - t_uint Mp[P256K1_WIDTH + P256K1_R_WIDTH]; + t_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R]; - if( N->n < P256K1_WIDTH ) + if( N->n < p_limbs ) return( 0 ); /* Init R */ R.s = 1; - R.p = p256k1_r_p; - R.n = P256K1_R_WIDTH; + R.p = Rp; + R.n = P_KOBLITZ_R; /* Common setup for M */ M.s = 1; M.p = Mp; /* M = A1 */ - M.n = N->n - P256K1_WIDTH; - if( M.n > P256K1_WIDTH ) - M.n = P256K1_WIDTH; + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + P256K1_WIDTH, M.n * sizeof( t_uint ) ); - M.n += R.n; /* Make room for multiplication by R */ + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) ); + if (shift != 0 ) + MPI_CHK( mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ /* N = A0 */ - for( i = P256K1_WIDTH; i < N->n; i++ ) + if (mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) N->p[i] = 0; /* N = A0 + R * A1 */ @@ -1294,15 +1301,19 @@ static int ecp_mod_p256k1( mpi *N ) /* Second pass */ /* M = A1 */ - M.n = N->n - P256K1_WIDTH; - if( M.n > P256K1_WIDTH ) - M.n = P256K1_WIDTH; + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + P256K1_WIDTH, M.n * sizeof( t_uint ) ); - M.n += R.n; /* Make room for multiplication by R */ + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) ); + if (shift != 0 ) + MPI_CHK( mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ /* N = A0 */ - for( i = P256K1_WIDTH; i < N->n; i++ ) + if (mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) N->p[i] = 0; /* N = A0 + R * A1 */ @@ -1312,6 +1323,54 @@ static int ecp_mod_p256k1( mpi *N ) cleanup: return( ret ); } +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED) || + POLARSSL_ECP_DP_SECP224K1_ENABLED) || + POLARSSL_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(POLARSSL_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} #endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ #endif