New experimental EC implementation (P-256, only 32-bit multiplications, meant for Cortex-M0/M0+).

This commit is contained in:
Thomas Pornin 2017-01-02 22:19:49 +01:00
parent bf809dfae5
commit 6dd8c51ba7
7 changed files with 1092 additions and 3 deletions

View file

@ -47,7 +47,7 @@ TESTX509 = testx509
TESTMATH = testmath TESTMATH = testmath
OBJCODEC = $(BUILD)/ccopy.o $(BUILD)/dec16be.o $(BUILD)/dec16le.o $(BUILD)/dec32be.o $(BUILD)/dec32le.o $(BUILD)/dec64be.o $(BUILD)/dec64le.o $(BUILD)/enc16be.o $(BUILD)/enc16le.o $(BUILD)/enc32be.o $(BUILD)/enc32le.o $(BUILD)/enc64be.o $(BUILD)/enc64le.o $(BUILD)/pemdec.o OBJCODEC = $(BUILD)/ccopy.o $(BUILD)/dec16be.o $(BUILD)/dec16le.o $(BUILD)/dec32be.o $(BUILD)/dec32le.o $(BUILD)/dec64be.o $(BUILD)/dec64le.o $(BUILD)/enc16be.o $(BUILD)/enc16le.o $(BUILD)/enc32be.o $(BUILD)/enc32le.o $(BUILD)/enc64be.o $(BUILD)/enc64le.o $(BUILD)/pemdec.o
OBJEC = $(BUILD)/ec_prime_i31.o $(BUILD)/ec_prime_i31_secp256r1.o $(BUILD)/ec_prime_i31_secp384r1.o $(BUILD)/ec_prime_i31_secp521r1.o $(BUILD)/ec_secp256r1.o $(BUILD)/ec_secp384r1.o $(BUILD)/ec_secp521r1.o $(BUILD)/ecdsa_atr.o $(BUILD)/ecdsa_i31_bits.o $(BUILD)/ecdsa_i31_sign_asn1.o $(BUILD)/ecdsa_i31_sign_raw.o $(BUILD)/ecdsa_i31_vrfy_asn1.o $(BUILD)/ecdsa_i31_vrfy_raw.o $(BUILD)/ecdsa_rta.o OBJEC = $(BUILD)/ec_p256_i15.o $(BUILD)/ec_prime_i31.o $(BUILD)/ec_prime_i31_secp256r1.o $(BUILD)/ec_prime_i31_secp384r1.o $(BUILD)/ec_prime_i31_secp521r1.o $(BUILD)/ec_secp256r1.o $(BUILD)/ec_secp384r1.o $(BUILD)/ec_secp521r1.o $(BUILD)/ecdsa_atr.o $(BUILD)/ecdsa_i31_bits.o $(BUILD)/ecdsa_i31_sign_asn1.o $(BUILD)/ecdsa_i31_sign_raw.o $(BUILD)/ecdsa_i31_vrfy_asn1.o $(BUILD)/ecdsa_i31_vrfy_raw.o $(BUILD)/ecdsa_rta.o
OBJHASH = $(BUILD)/dig_oid.o $(BUILD)/dig_size.o $(BUILD)/ghash_ctmul.o $(BUILD)/ghash_ctmul32.o $(BUILD)/ghash_ctmul64.o $(BUILD)/md5.o $(BUILD)/md5sha1.o $(BUILD)/multihash.o $(BUILD)/sha1.o $(BUILD)/sha2big.o $(BUILD)/sha2small.o OBJHASH = $(BUILD)/dig_oid.o $(BUILD)/dig_size.o $(BUILD)/ghash_ctmul.o $(BUILD)/ghash_ctmul32.o $(BUILD)/ghash_ctmul64.o $(BUILD)/md5.o $(BUILD)/md5sha1.o $(BUILD)/multihash.o $(BUILD)/sha1.o $(BUILD)/sha2big.o $(BUILD)/sha2small.o
OBJINT31 = $(BUILD)/i31_add.o $(BUILD)/i31_bitlen.o $(BUILD)/i31_decmod.o $(BUILD)/i31_decode.o $(BUILD)/i31_decred.o $(BUILD)/i31_encode.o $(BUILD)/i31_fmont.o $(BUILD)/i31_iszero.o $(BUILD)/i31_modpow.o $(BUILD)/i31_montmul.o $(BUILD)/i31_mulacc.o $(BUILD)/i31_muladd.o $(BUILD)/i31_ninv31.o $(BUILD)/i31_reduce.o $(BUILD)/i31_rshift.o $(BUILD)/i31_sub.o $(BUILD)/i31_tmont.o OBJINT31 = $(BUILD)/i31_add.o $(BUILD)/i31_bitlen.o $(BUILD)/i31_decmod.o $(BUILD)/i31_decode.o $(BUILD)/i31_decred.o $(BUILD)/i31_encode.o $(BUILD)/i31_fmont.o $(BUILD)/i31_iszero.o $(BUILD)/i31_modpow.o $(BUILD)/i31_montmul.o $(BUILD)/i31_mulacc.o $(BUILD)/i31_muladd.o $(BUILD)/i31_ninv31.o $(BUILD)/i31_reduce.o $(BUILD)/i31_rshift.o $(BUILD)/i31_sub.o $(BUILD)/i31_tmont.o
OBJINT32 = $(BUILD)/i32_add.o $(BUILD)/i32_bitlen.o $(BUILD)/i32_decmod.o $(BUILD)/i32_decode.o $(BUILD)/i32_decred.o $(BUILD)/i32_div32.o $(BUILD)/i32_encode.o $(BUILD)/i32_fmont.o $(BUILD)/i32_iszero.o $(BUILD)/i32_modpow.o $(BUILD)/i32_montmul.o $(BUILD)/i32_mulacc.o $(BUILD)/i32_muladd.o $(BUILD)/i32_ninv32.o $(BUILD)/i32_reduce.o $(BUILD)/i32_sub.o $(BUILD)/i32_tmont.o OBJINT32 = $(BUILD)/i32_add.o $(BUILD)/i32_bitlen.o $(BUILD)/i32_decmod.o $(BUILD)/i32_decode.o $(BUILD)/i32_decred.o $(BUILD)/i32_div32.o $(BUILD)/i32_encode.o $(BUILD)/i32_fmont.o $(BUILD)/i32_iszero.o $(BUILD)/i32_modpow.o $(BUILD)/i32_montmul.o $(BUILD)/i32_mulacc.o $(BUILD)/i32_muladd.o $(BUILD)/i32_ninv32.o $(BUILD)/i32_reduce.o $(BUILD)/i32_sub.o $(BUILD)/i32_tmont.o
@ -160,6 +160,8 @@ $(BUILD)/ec_g_secp384r1.o: src/ec/ec_g_secp384r1.c $(HEADERS)
$(BUILD)/ec_g_secp521r1.o: src/ec/ec_g_secp521r1.c $(HEADERS) $(BUILD)/ec_g_secp521r1.o: src/ec/ec_g_secp521r1.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_g_secp521r1.o src/ec/ec_g_secp521r1.c $(CC) $(CFLAGS) -c -o $(BUILD)/ec_g_secp521r1.o src/ec/ec_g_secp521r1.c
$(BUILD)/ec_p256_i15.o: src/ec/ec_p256_i15.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_p256_i15.o src/ec/ec_p256_i15.c
$(BUILD)/ec_prime_i31.o: src/ec/ec_prime_i31.c $(HEADERS) $(BUILD)/ec_prime_i31.o: src/ec/ec_prime_i31.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31.o src/ec/ec_prime_i31.c $(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31.o src/ec/ec_prime_i31.c

View file

@ -369,6 +369,16 @@ typedef struct {
*/ */
extern const br_ec_impl br_ec_prime_i31; extern const br_ec_impl br_ec_prime_i31;
/**
* \brief EC implementation "i15" for P-256.
*
* This implementation uses specialised code for curve secp256r1 (also
* known as NIST P-256), with Karatsuba decomposition, and fast modular
* reduction thanks to the field modulus special format. Only 32-bit
* multiplications are used (with 32-bit results, not 64-bit).
*/
extern const br_ec_impl br_ec_p256_i15;
/** /**
* \brief Convert a signature from "raw" to "asn1". * \brief Convert a signature from "raw" to "asn1".
* *

View file

@ -60,6 +60,25 @@
#define BR_CT_MUL31 1 #define BR_CT_MUL31 1
*/ */
/*
* When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held
* in 32-bit words) use an alternate implementation which is slower and
* larger than the normal multiplication, but should ensure
* constant-time multiplications on most/all architectures where the
* basic multiplication is not constant-time.
#define BR_CT_MUL15 1
*/
/*
* When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign
* extension) are performed with a sequence of operations which is bigger
* and slower than a simple right shift on a signed value. This avoids
* relying on an implementation-defined behaviour. However, most if not
* all C compilers use sign extension for right shifts on signed values,
* so this alternate macro is disabled by default.
#define BR_NO_ARITH_SHIFT 1
*/
/* /*
* When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
* to automatically obtain quality randomness for seedings its internal * to automatically obtain quality randomness for seedings its internal

1006
src/ec/ec_p256_i15.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -549,6 +549,43 @@ MAX(uint32_t x, uint32_t y)
#endif #endif
/*
* Multiply two words together; each word may contain up to 15 bits of
* data. If BR_CT_MUL15 is non-zero, then the macro will contain some
* extra operations that help in making the operation constant-time on
* some platforms, where the basic 32-bit multiplication is not
* constant-time.
*/
#if BR_CT_MUL15
#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \
* ((uint32_t)(x) | (uint32_t)0x80000000) \
& (uint32_t)0x3FFFFFFF)
#else
#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y))
#endif
/*
* Arithmetic right shift (sign bit is copied). What happens when
* right-shifting a negative value is _implementation-defined_, so it
* does not trigger undefined behaviour, but it is still up to each
* compiler to define (and document) what it does. Most/all compilers
* will do an arithmetic shift, the sign bit being used to fill the
* holes; this is a native operation on the underlying CPU, and it would
* make little sense for the compiler to do otherwise. GCC explicitly
* documents that it follows that convention.
*
* Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an
* alternate version will be used, that does not rely on such
* implementation-defined behaviour. Unfortunately, it is also slower
* and yields bigger code, which is why it is deactivated by default.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/* /*
* Constant-time division. The dividend hi:lo is divided by the * Constant-time division. The dividend hi:lo is divided by the
* divisor d; the quotient is returned and the remainder is written * divisor d; the quotient is returned and the remainder is written

View file

@ -47,9 +47,9 @@ hextobin(unsigned char *dst, const char *src)
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
c -= '0'; c -= '0';
} else if (c >= 'A' && c <= 'F') { } else if (c >= 'A' && c <= 'F') {
c -= ('A' - 10); \ c -= ('A' - 10);
} else if (c >= 'a' && c <= 'f') { } else if (c >= 'a' && c <= 'f') {
c -= ('a' - 10); \ c -= ('a' - 10);
} else { } else {
continue; continue;
} }
@ -4822,6 +4822,13 @@ test_EC_prime_i31(void)
| (uint32_t)1 << BR_EC_secp521r1); | (uint32_t)1 << BR_EC_secp521r1);
} }
static void
test_EC_p256_i15(void)
{
test_EC_KAT("EC_p256_i15", &br_ec_p256_i15,
(uint32_t)1 << BR_EC_secp256r1);
}
static const unsigned char EC_P256_PUB_POINT[] = { static const unsigned char EC_P256_PUB_POINT[] = {
0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D, 0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D,
0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D, 0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D,
@ -5342,6 +5349,7 @@ static const struct {
STU(GHASH_ctmul32), STU(GHASH_ctmul32),
STU(GHASH_ctmul64), STU(GHASH_ctmul64),
STU(EC_prime_i31), STU(EC_prime_i31),
STU(EC_p256_i15),
/* STU(EC_prime_i32), */ /* STU(EC_prime_i32), */
STU(ECDSA_i31), STU(ECDSA_i31),
{ 0, 0 } { 0, 0 }

View file

@ -613,6 +613,12 @@ test_speed_ec_inner(const char *name,
} }
} }
static void
test_speed_ec_p256_i15(void)
{
test_speed_ec_inner("EC i15 P-256", &br_ec_p256_i15, &br_secp256r1);
}
static void static void
test_speed_ec_prime_i31(void) test_speed_ec_prime_i31(void)
{ {
@ -1130,6 +1136,7 @@ static const struct {
STU(rsa_i31), STU(rsa_i31),
STU(rsa_i32), STU(rsa_i32),
STU(ec_p256_i15),
STU(ec_prime_i31), STU(ec_prime_i31),
STU(ecdsa_i31), STU(ecdsa_i31),