New implementation of Curve25519 (using multiplications of words of 15 bits or so, should be much faster on Cortex M0).

This commit is contained in:
Thomas Pornin 2017-01-15 16:49:58 +01:00
parent 2f9c953af4
commit 693d2a0085
6 changed files with 1574 additions and 7 deletions

View file

@ -47,7 +47,7 @@ TESTX509 = testx509
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
OBJEC = $(BUILD)/ec_c25519_i15.o $(BUILD)/ec_curve25519.o $(BUILD)/ec_p256_m15.o $(BUILD)/ec_prime_i15.o $(BUILD)/ec_prime_i31.o $(BUILD)/ec_secp256r1.o $(BUILD)/ec_secp384r1.o $(BUILD)/ec_secp521r1.o $(BUILD)/ecdsa_atr.o $(BUILD)/ecdsa_i15_bits.o $(BUILD)/ecdsa_i15_sign_asn1.o $(BUILD)/ecdsa_i15_sign_raw.o $(BUILD)/ecdsa_i15_vrfy_asn1.o $(BUILD)/ecdsa_i15_vrfy_raw.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_c25519_i15.o $(BUILD)/ec_c25519_m15.o $(BUILD)/ec_curve25519.o $(BUILD)/ec_p256_m15.o $(BUILD)/ec_prime_i15.o $(BUILD)/ec_prime_i31.o $(BUILD)/ec_secp256r1.o $(BUILD)/ec_secp384r1.o $(BUILD)/ec_secp521r1.o $(BUILD)/ecdsa_atr.o $(BUILD)/ecdsa_i15_bits.o $(BUILD)/ecdsa_i15_sign_asn1.o $(BUILD)/ecdsa_i15_sign_raw.o $(BUILD)/ecdsa_i15_vrfy_asn1.o $(BUILD)/ecdsa_i15_vrfy_raw.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
# $(BUILD)/ec_prime_i31_secp256r1.o $(BUILD)/ec_prime_i31_secp384r1.o $(BUILD)/ec_prime_i31_secp521r1.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
OBJINT15 = $(BUILD)/i15_core.o $(BUILD)/i15_ext1.o $(BUILD)/i15_ext2.o
@ -165,6 +165,9 @@ $(BUILD)/ec_g_secp521r1.o: src/ec/ec_g_secp521r1.c $(HEADERS)
$(BUILD)/ec_c25519_i15.o: src/ec/ec_c25519_i15.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_c25519_i15.o src/ec/ec_c25519_i15.c
$(BUILD)/ec_c25519_m15.o: src/ec/ec_c25519_m15.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_c25519_m15.o src/ec/ec_c25519_m15.c
$(BUILD)/ec_curve25519.o: src/ec/ec_curve25519.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_curve25519.o src/ec/ec_curve25519.c

View file

@ -410,12 +410,12 @@ extern const br_ec_impl br_ec_prime_i31;
extern const br_ec_impl br_ec_prime_i15;
/**
* \brief EC implementation "i15" for P-256.
* \brief EC implementation "m15" 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).
* known as NIST P-256), with optional 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_m15;
@ -428,6 +428,14 @@ extern const br_ec_impl br_ec_p256_m15;
*/
extern const br_ec_impl br_ec_c25519_i15;
/**
* \brief EC implementation "m15" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 15 bits. The `muladd()` method is not implemented.
*/
extern const br_ec_impl br_ec_c25519_m15;
/**
* \brief Convert a signature from "raw" to "asn1".
*

View file

@ -46,6 +46,27 @@ static const uint16_t C255_R2[] = {
0x0000
};
/* obsolete
#include <stdio.h>
#include <stdlib.h>
static void
print_int_mont(const char *name, const uint16_t *x)
{
uint16_t y[18];
unsigned char tmp[32];
size_t u;
printf("%s = ", name);
memcpy(y, x, sizeof y);
br_i15_from_monty(y, C255_P, P0I);
br_i15_encode(tmp, sizeof tmp, y);
for (u = 0; u < sizeof tmp; u ++) {
printf("%02X", tmp[u]);
}
printf("\n");
}
*/
static const uint16_t C255_A24[] = {
0x0110,
0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@ -194,6 +215,10 @@ api_mul(unsigned char *G, size_t Glen,
k[31] &= 0x7F;
k[31] |= 0x40;
/* obsolete
print_int_mont("x1", x1);
*/
swap = 0;
for (i = 254; i >= 0; i --) {
uint32_t kt;
@ -204,6 +229,13 @@ api_mul(unsigned char *G, size_t Glen,
cswap(z2, z3, swap);
swap = kt;
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
c255_add(a, x2, z2);
c255_mul(aa, a, a);
c255_sub(b, x2, z2);
@ -213,6 +245,19 @@ api_mul(unsigned char *G, size_t Glen,
c255_sub(d, x3, z3);
c255_mul(da, d, a);
c255_mul(cb, c, b);
/* obsolete
print_int_mont("a ", a);
print_int_mont("aa", aa);
print_int_mont("b ", b);
print_int_mont("bb", bb);
print_int_mont("e ", e);
print_int_mont("c ", c);
print_int_mont("d ", d);
print_int_mont("da", da);
print_int_mont("cb", cb);
*/
c255_add(x3, da, cb);
c255_mul(x3, x3, x3);
c255_sub(z3, da, cb);
@ -222,6 +267,13 @@ api_mul(unsigned char *G, size_t Glen,
c255_mul(z2, C255_A24, e);
c255_add(z2, z2, aa);
c255_mul(z2, e, z2);
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
}
cswap(x2, x3, swap);
cswap(z2, z3, swap);

1451
src/ec/ec_c25519_m15.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -4935,13 +4935,13 @@ const struct {
static void
test_EC_c25519(const char *name, const br_ec_impl *iec)
{
unsigned char bu[32], bk[32], br[32];
size_t v;
int i;
printf("Test %s: ", name);
fflush(stdout);
for (v = 0; C25519_KAT[v].scalar; v ++) {
unsigned char bu[32], bk[32], br[32];
hextobin(bk, C25519_KAT[v].scalar);
hextobin(bu, C25519_KAT[v].u_in);
hextobin(br, C25519_KAT[v].u_out);
@ -4956,6 +4956,44 @@ test_EC_c25519(const char *name, const br_ec_impl *iec)
printf(".");
fflush(stdout);
}
printf(" ");
fflush(stdout);
memset(bu, 0, sizeof bu);
bu[0] = 0x09;
memcpy(bk, bu, sizeof bu);
for (i = 1; i <= 1000; i ++) {
if (!iec->mul(bu, sizeof bu, bk, sizeof bk, BR_EC_curve25519)) {
fprintf(stderr, "Curve25519 multiplication failed"
" (iter=%d)\n", i);
exit(EXIT_FAILURE);
}
for (v = 0; v < sizeof bu; v ++) {
unsigned t;
t = bu[v];
bu[v] = bk[v];
bk[v] = t;
}
if (i == 1 || i == 1000) {
const char *sref;
sref = (i == 1)
? "422C8E7A6227D7BCA1350B3E2BB7279F7897B87BB6854B783C60E80311AE3079"
: "684CF59BA83309552800EF566F2F4D3C1C3887C49360E3875F2EB94D99532C51";
hextobin(br, sref);
if (memcmp(bk, br, sizeof bk) != 0) {
fprintf(stderr,
"Curve25519 failed KAT (iter=%d)\n", i);
exit(EXIT_FAILURE);
}
}
if (i % 100 == 0) {
printf(".");
fflush(stdout);
}
}
printf(" done.\n");
fflush(stdout);
}
@ -4966,6 +5004,12 @@ test_EC_c25519_i15(void)
test_EC_c25519("EC_c25519_i15", &br_ec_c25519_i15);
}
static void
test_EC_c25519_m15(void)
{
test_EC_c25519("EC_c25519_m15", &br_ec_c25519_m15);
}
static const unsigned char EC_P256_PUB_POINT[] = {
0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D,
0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D,
@ -5513,6 +5557,7 @@ static const struct {
STU(EC_p256_m15),
/* STU(EC_prime_i32), */
STU(EC_c25519_i15),
STU(EC_c25519_m15),
STU(ECDSA_i15),
STU(ECDSA_i31),
{ 0, 0 }

View file

@ -714,6 +714,13 @@ test_speed_ec_c25519_i15(void)
&br_ec_c25519_i15, &br_curve25519);
}
static void
test_speed_ec_c25519_m15(void)
{
test_speed_ec_inner("EC m15 C25519",
&br_ec_c25519_m15, &br_curve25519);
}
static void
test_speed_ecdsa_inner(const char *name,
const br_ec_impl *impl, const br_ec_curve_def *cd,
@ -1256,6 +1263,7 @@ static const struct {
STU(ec_prime_i15),
STU(ec_prime_i31),
STU(ec_c25519_i15),
STU(ec_c25519_m15),
STU(ecdsa_p256_m15),
STU(ecdsa_i15),
STU(ecdsa_i31),