Renamed files, added more function documentation comments, did new performance testing.

This commit is contained in:
Ken MacKay
2013-05-28 23:51:12 -07:00
parent 38c1caca3b
commit 8c5fc3146d
8 changed files with 179 additions and 137 deletions
+20 -57
View File
@@ -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
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)
+3 -1
View File
@@ -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 <stdio.h>
void vli_print(uint32_t *p_vli)
+17 -17
View File
@@ -1,4 +1,4 @@
#include "ecdh.h"
#include "ecc.h"
#include <string.h>
@@ -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. */
+132
View File
@@ -0,0 +1,132 @@
#ifndef _MICRO_ECC_H_
#define _MICRO_ECC_H_
#include <stdint.h>
/* 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_ */
-55
View File
@@ -1,55 +0,0 @@
#ifndef _MICRO_ECDH_H_
#define _MICRO_ECDH_H_
#include <stdint.h>
/* 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_ */
+2 -2
View File
@@ -1,4 +1,4 @@
#include "ecdh.h"
#include "ecc.h"
#include <stdio.h>
#include <string.h>
@@ -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));
+2 -2
View File
@@ -1,4 +1,4 @@
#include "ecdh.h"
#include "ecc.h"
#include <stdio.h>
#include <string.h>
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
for(i=0; i<l_num; ++i)
{
getRandomBytes((char *)l_private[i], NUM_ECC_DIGITS * sizeof(uint32_t));
ecdh_make_key(&l_public[i], l_private[i], l_private[i]);
ecc_make_key(&l_public[i], l_private[i], l_private[i]);
}
printf("uint32_t l_private[%u][NUM_ECC_DIGITS] = {\n", l_num);
+3 -3
View File
@@ -1,4 +1,4 @@
#include "ecdh.h"
#include "ecc.h"
#include <stdio.h>
#include <string.h>
@@ -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))
{