diff --git a/armtest/results.txt b/armtest/results.txt index 1e151de..054f62e 100644 --- a/armtest/results.txt +++ b/armtest/results.txt @@ -1,65 +1,28 @@ LPC1114 at 48MHz (ARM Cortex-M0, 32-cycle 32x32 bit multiply) 128 bits -All off: avg time = 169 ms -size = 1962 (including aeabi_lmul) - -ECC_SOFT_MULT64 enabled: avg time = 164 ms -size = 1942 (does not include aeabi_lmul) - -ECC_USE_NAF enabled: avg time = 147 ms -size = 2258 - -ECC_SQUARE_FUNC enabled: avg time = 137 ms -size = 2538 - -160 bits -All off: avg time = 269 ms -size = 1864 (including aeabi_lmul) - -ECC_SOFT_MULT64 enabled: avg time = 255 ms -size = 1842 (does not include aeabi_lmul) - -ECC_USE_NAF enabled: avg time = 224 ms -size = 2158 - -ECC_SQUARE_FUNC enabled: avg time = 205 ms -size = 2434 +asm on (#define ECC_ASM ecc_asm_thumb) (no lmul required) +ECC_SQUARE_FUNC + ECC_USE_NAF: 75.9 (size = 2316 + 16) +no opt: 85.5 (size = 1892 + 16) 192 bits -All off: avg time = 439 ms -size = 1808 (including aeabi_lmul) +asm off +ECC_SQUARE_FUNC + ECC_USE_NAF: 337.2 (size = 2276 + 112 (lmul) + 24) +ECC_SQUARE_FUNC only: 393.0 (size = 2016 + 112 (lmul) + 24) +ECC_USE_NAF only: 369.5 (size = 2072 + 112 (lmul) + 24) +no opt: 431.9 (size = 1812 + 112 (lmul) + 24) -ECC_SOFT_MULT64 enabled: avg time = 414 ms -size = 1786 (does not include aeabi_lmul) - -ECC_USE_NAF enabled: avg time = 364 ms -size = 2102 - -ECC_SQUARE_FUNC enabled: avg time = 325 ms -size = 2378 - -224 bits -All off: avg time = 674 ms -size = 1866 (including aeabi_lmul) - -ECC_SOFT_MULT64 enabled: avg time = 649 ms -size = 1842 (does not include aeabi_lmul) - -ECC_USE_NAF enabled: avg time = 571 ms -size = 2158 - -ECC_SQUARE_FUNC enabled: avg time = 500 ms -size = 2438 +asm on (#define ECC_ASM ecc_asm_thumb) (no lmul required) +ECC_SQUARE_FUNC + ECC_USE_NAF: 147.7 (size = 2156 + 24) +ECC_SQUARE_FUNC only: 172.6 (size = 1896 + 24) +ECC_USE_NAF only: 158.2 (size = 2008 + 24) +no opt: 183.9 (size = 1748 + 24) 256 bits -All off: avg time = 1092 ms -size = 2128 (including aeabi_lmul) +asm on (#define ECC_ASM ecc_asm_thumb) (no lmul required) +ECC_SQUARE_FUNC + ECC_USE_NAF: 385.8 (size = 2484 + 32) +no opt: 473.6 (size = 2072 + 32) -ECC_SOFT_MULT64 enabled: avg time = 1058 ms -size = 2110 (does not include aeabi_lmul) - -ECC_USE_NAF enabled: avg time = 916 ms -size = 2426 - -ECC_SQUARE_FUNC enabled: avg time = 810 ms -size = 2718 \ No newline at end of file +384 bits +asm on (#define ECC_ASM ecc_asm_thumb) (no lmul required) +ECC_SQUARE_FUNC + ECC_USE_NAF: 1128.2 (size = 2196 + 48) +no opt: 1405.8 (size = 1784 + 48) \ No newline at end of file diff --git a/armtest/test.c b/armtest/test.c index 6d2125f..436ad73 100644 --- a/armtest/test.c +++ b/armtest/test.c @@ -1,4 +1,4 @@ -#include "ecdh.h" + #if TARGET_LPC11XX #include "peripherals/uart.h" @@ -20,6 +20,8 @@ uint64_t getTimeMs(void) #endif +#include "ecc.h" + #include void vli_print(uint32_t *p_vli) diff --git a/ecdh.c b/ecc.c similarity index 99% rename from ecdh.c rename to ecc.c index eed8b5a..023a709 100644 --- a/ecdh.c +++ b/ecc.c @@ -1,4 +1,4 @@ -#include "ecdh.h" +#include "ecc.h" #include @@ -1283,22 +1283,7 @@ static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_sca #endif /* ECC_USE_NAF */ -int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS]) -{ - EccPoint l_product; - - EccPoint_mult(&l_product, p_publicKey, p_privateKey); - if(EccPoint_isZero(&l_product)) - { - return 0; - } - - vli_set(p_secret, l_product.x); - - return 1; -} - -int ecdh_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]) +int ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]) { /* Make sure the private key is in the range [1, n-1]. For the supported curves, n is always large enough that we only need to subtract once at most. */ @@ -1349,6 +1334,21 @@ int ecc_valid_public_key(EccPoint *p_publicKey) return 1; } +int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS]) +{ + EccPoint l_product; + + EccPoint_mult(&l_product, p_publicKey, p_privateKey); + if(EccPoint_isZero(&l_product)) + { + return 0; + } + + vli_set(p_secret, l_product.x); + + return 1; +} + /* -------- ECDSA code -------- */ /* Computes p_result = (p_left * p_right) % p_mod. */ diff --git a/ecc.h b/ecc.h new file mode 100644 index 0000000..22a91a7 --- /dev/null +++ b/ecc.h @@ -0,0 +1,132 @@ +#ifndef _MICRO_ECC_H_ +#define _MICRO_ECC_H_ + +#include + +/* Optimization settings. Define as 1 to enable an optimization, 0 to disable it. +ECC_SQUARE_FUNC - If enabled, this will cause a specific function to be used for (scalar) squaring instead of the generic + multiplication function. Improves speed by about 8% . +ECC_USE_NAF - If enabled, this will convert the private key to a non-adjacent form before point multiplication. + Improves speed by about 14%. +*/ +#define ECC_SQUARE_FUNC 1 +#define ECC_USE_NAF 1 + +/* Inline assembly options. +Inline assembly (gcc format) is provided for selected operations for Thumb and Thumb2/ARM. +Improves speed by about 57% on Cortex-M0. + +Note: You must choose the appropriate option for your target architecture, or compilation will fail +with strange assembler messages. +*/ +#define ecc_asm_none 0 +#define ecc_asm_thumb 1 /* ARM Thumb assembly (including Cortex-M0) */ +#define ecc_asm_thumb2 2 /* ARM Thumb-2 assembly (eg Cortex-M3) */ +#define ecc_asm_arm 3 /* Regular ARM assembly */ +#ifndef ECC_ASM + #define ECC_ASM ecc_asm_none +#endif + +/* Curve selection options. */ +#define secp128r1 4 +#define secp192r1 6 +#define secp256r1 8 +#define secp384r1 12 +#ifndef ECC_CURVE + #define ECC_CURVE secp192r1 +#endif + +#if (ECC_CURVE != secp128r1 && ECC_CURVE != secp192r1 && ECC_CURVE != secp256r1 && ECC_CURVE != secp384r1) + #error "Must define ECC_CURVE to one of the available curves" +#endif + +#define NUM_ECC_DIGITS ECC_CURVE + +typedef struct EccPoint +{ + uint32_t x[NUM_ECC_DIGITS]; + uint32_t y[NUM_ECC_DIGITS]; +} EccPoint; + +/* ecc_make_key() function. +Create a public/private key pair. + +You must use a new nonpredictable random number to generate each new key pair. + +Outputs: + p_publicKey - Will be filled in with the point representing the public key. + p_privateKey - Will be filled in with the private key. + +Inputs: + p_random - The random number to use to generate the key pair. + +Returns 1 if the key pair was generated successfully, 0 if an error occurred. If 0 is returned, +try again with a different random number. +*/ +int ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]); + +/* ecc_valid_public_key() function. +Determine whether or not a given point is on the chosen elliptic curve (ie, is a valid public key). + +Inputs: + p_publicKey - The point to check. + +Returns 1 if the given point is valid, 0 if it is invalid. +*/ +int ecc_valid_public_key(EccPoint *p_publicKey); + +/* ecdh_shared_secret() function. +Compute a shared secret given your secret key and someone else's public key. + +Outputs: + p_secret - Will be filled in with the shared secret value. + +Inputs: + p_publicKey - The public key of the remote party. + p_privateKey - Your private key. + +Returns 1 if the shared secret was computed successfully, 0 otherwise. + +Note: It is recommended that you hash the result of ecdh_shared_secret before using it for symmetric encryption or HMAC. +If you do not hash the shared secret, you must call ecc_valid_public_key() to verify that the remote side's public key is valid. +If this is not done, an attacker could create a public key that would cause your use of the shared secret to leak information +about your private key. */ +int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS]); + +/* ecdsa_sign() function. +Generate an ECDSA signature for a given hash value. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key and a random number. +You must use a new nonpredictable random number to generate each new signature. + +Outputs: + r, s - Will be filled in with the signature values. + +Inputs: + p_privateKey - Your private key. + p_random - The random number to use to generate the signature. + p_hash - The message hash to sign. + +Returns 1 if the signature generated successfully, 0 if an error occurred. If 0 is returned, +try again with a different random number. +*/ +int ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS], uint32_t p_privateKey[NUM_ECC_DIGITS], + uint32_t p_random[NUM_ECC_DIGITS], uint32_t p_hash[NUM_ECC_DIGITS]); + +/* ecdsa_verify() function. +Verify an ECDSA signature. + +Usage: Compute the hash of the signed data using the same hash as the signer and +pass it to this function along with the signer's public key and the signature values (r and s). + +Inputs: + p_publicKey - The signer's public key + p_hash - The hash of the signed data. + r, s - The signature values. + +Returns 1 if the signature is valid, 0 if it is invalid. +*/ +int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS]); + +#endif /* _MICRO_ECC_H_ */ diff --git a/ecdh.h b/ecdh.h deleted file mode 100644 index 1cb46a4..0000000 --- a/ecdh.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _MICRO_ECDH_H_ -#define _MICRO_ECDH_H_ - -#include - -/* Optimization settings. Define as 1 to enable an optimization, 0 to disable it. -ECC_SQUARE_FUNC - If enabled, this will cause a specific function to be used for (scalar) squaring instead of the generic - multiplication function. Improves speed by about 8% . -ECC_USE_NAF - If enabled, this will convert the private key to a non-adjacent form before point multiplication. - Improves speed by about 10%. -*/ -#define ECC_SQUARE_FUNC 1 -#define ECC_USE_NAF 1 - -#define ecc_asm_none 0 -#define ecc_asm_thumb 1 /* ARM Thumb assembly (including Cortex-M0) */ -#define ecc_asm_thumb2 2 /* ARM Thumb-2 assembly */ -#define ecc_asm_arm 3 /* Regular ARM assembly */ -#ifndef ECC_ASM - #define ECC_ASM ecc_asm_none -#endif - -#define secp128r1 4 -#define secp192r1 6 -#define secp256r1 8 -#define secp384r1 12 -#ifndef ECC_CURVE - #define ECC_CURVE secp192r1 -#endif - -#if (ECC_CURVE != secp128r1 && ECC_CURVE != secp192r1 && ECC_CURVE != secp256r1 && ECC_CURVE != secp384r1) - #error "Must define ECC_CURVE to one of the available curves" -#endif - -#define NUM_ECC_DIGITS ECC_CURVE - -typedef struct EccPoint -{ - uint32_t x[NUM_ECC_DIGITS]; - uint32_t y[NUM_ECC_DIGITS]; -} EccPoint; - -/* Note: It is recommended that you hash the result of ecdh_shared_secret before using it for symmetric encryption or HMAC. -If you do not hash the shared secret, you must call ecc_valid_public_key() to verify that the remote side's public key is valid. -If this is not done, an attacker could create a public key that would cause your use of the shared secret to leak information -about your private key. */ -int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS]); -int ecdh_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]); -int ecc_valid_public_key(EccPoint *p_publicKey); - -int ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS], uint32_t p_privateKey[NUM_ECC_DIGITS], - uint32_t p_random[NUM_ECC_DIGITS], uint32_t p_hash[NUM_ECC_DIGITS]); -int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS]); - -#endif /* _MICRO_ECDH_H_ */ diff --git a/test/check_dsa.c b/test/check_dsa.c index 6a12c98..9f248dd 100644 --- a/test/check_dsa.c +++ b/test/check_dsa.c @@ -1,4 +1,4 @@ -#include "ecdh.h" +#include "ecc.h" #include #include @@ -54,7 +54,7 @@ int main() fflush(stdout); getRandomBytes((char *)l_private, NUM_ECC_DIGITS * sizeof(uint32_t)); - ecdh_make_key(&l_public, l_private, l_private); + ecc_make_key(&l_public, l_private, l_private); getRandomBytes((char *)l_hash, NUM_ECC_DIGITS * sizeof(uint32_t)); getRandomBytes((char *)l_random, NUM_ECC_DIGITS * sizeof(uint32_t)); diff --git a/test/makekeys.c b/test/makekeys.c index d7c40eb..0f9838f 100644 --- a/test/makekeys.c +++ b/test/makekeys.c @@ -1,4 +1,4 @@ -#include "ecdh.h" +#include "ecc.h" #include #include @@ -51,7 +51,7 @@ int main(int argc, char **argv) for(i=0; i #include @@ -54,8 +54,8 @@ int main() getRandomBytes((char *)l_secret1, NUM_ECC_DIGITS * sizeof(uint32_t)); getRandomBytes((char *)l_secret2, NUM_ECC_DIGITS * sizeof(uint32_t)); - ecdh_make_key(&l_Q1, l_secret1, l_secret1); - ecdh_make_key(&l_Q2, l_secret2, l_secret2); + ecc_make_key(&l_Q1, l_secret1, l_secret1); + ecc_make_key(&l_Q2, l_secret2, l_secret2); if(!ecdh_shared_secret(l_shared1, &l_Q1, l_secret2)) {