mirror of
https://github.com/kmackay/micro-ecc.git
synced 2026-06-05 21:14:51 +00:00
Use 'uECC_' prefix for everything to avoid conflicts with other libraries. (Fix for #1).
This commit is contained in:
+25
-25
@@ -2,7 +2,7 @@
|
||||
#define DEC_24 23
|
||||
#define DEC_32 31
|
||||
|
||||
#define DEC(N) ECC_CONCAT(DEC_, N)
|
||||
#define DEC(N) uECC_CONCAT(DEC_, N)
|
||||
|
||||
#define REPEAT_1(stuff) stuff
|
||||
#define REPEAT_2(stuff) REPEAT_1(stuff) stuff
|
||||
@@ -37,17 +37,17 @@
|
||||
#define REPEAT_31(stuff) REPEAT_30(stuff) stuff
|
||||
#define REPEAT_32(stuff) REPEAT_31(stuff) stuff
|
||||
|
||||
#define REPEAT(N, stuff) ECC_CONCAT(REPEAT_, N)(stuff)
|
||||
#define REPEAT(N, stuff) uECC_CONCAT(REPEAT_, N)(stuff)
|
||||
|
||||
#define STR2(thing) #thing
|
||||
#define STR(thing) STR2(thing)
|
||||
|
||||
#if (ECC_ASM == ecc_asm_fast)
|
||||
#if (uECC_ASM == uECC_asm_fast)
|
||||
|
||||
static void vli_clear(uint8_t *p_vli)
|
||||
{
|
||||
__asm__ volatile (
|
||||
REPEAT(ECC_BYTES, "st %a[ptr]+, r1 \n\t")
|
||||
REPEAT(uECC_BYTES, "st %a[ptr]+, r1 \n\t")
|
||||
|
||||
: [ptr] "+e" (p_vli)
|
||||
:
|
||||
@@ -59,7 +59,7 @@ static void vli_clear(uint8_t *p_vli)
|
||||
static void vli_set(uint8_t *p_dest, const uint8_t *p_src)
|
||||
{
|
||||
__asm__ volatile (
|
||||
REPEAT(ECC_BYTES, "ld r0, %a[sptr]+ \n\t"
|
||||
REPEAT(uECC_BYTES, "ld r0, %a[sptr]+ \n\t"
|
||||
"st %a[dptr]+, r0 \n\t")
|
||||
: [dptr] "+e" (p_dest), [sptr] "+e" (p_src)
|
||||
:
|
||||
@@ -71,13 +71,13 @@ static void vli_set(uint8_t *p_dest, const uint8_t *p_src)
|
||||
static void vli_rshift1(uint8_t *p_vli)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"adiw r30, " STR(ECC_BYTES) " \n\t"
|
||||
"adiw r30, " STR(uECC_BYTES) " \n\t"
|
||||
"ld r0, -z \n\t" /* Load byte. */
|
||||
"lsr r0 \n\t" /* Shift. */
|
||||
"st z, r0 \n\t" /* Store the first result byte. */
|
||||
|
||||
/* Now we just do the remaining bytes with the carry bit (using ROR) */
|
||||
REPEAT(DEC(ECC_BYTES), "ld r0, -z \n\t"
|
||||
REPEAT(DEC(uECC_BYTES), "ld r0, -z \n\t"
|
||||
"ror r0 \n\t"
|
||||
"st z, r0 \n\t")
|
||||
|
||||
@@ -106,7 +106,7 @@ static uint8_t vli_add(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
"st z+, %[left] \n\t" /* Store the first result byte. */
|
||||
|
||||
/* Now we just do the remaining bytes with the carry bit (using ADC) */
|
||||
REPEAT(DEC(ECC_BYTES), "ld %[left], x+ \n\t"
|
||||
REPEAT(DEC(uECC_BYTES), "ld %[left], x+ \n\t"
|
||||
"ld %[right], y+ \n\t"
|
||||
"adc %[left], %[right] \n\t"
|
||||
"st z+, %[left] \n\t")
|
||||
@@ -143,7 +143,7 @@ static uint8_t vli_sub(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
"st z+, %[left] \n\t" /* Store the first result byte. */
|
||||
|
||||
/* Now we just do the remaining bytes with the carry bit (using SBC) */
|
||||
REPEAT(DEC(ECC_BYTES), "ld %[left], x+ \n\t"
|
||||
REPEAT(DEC(uECC_BYTES), "ld %[left], x+ \n\t"
|
||||
"ld %[right], y+ \n\t"
|
||||
"sbc %[left], %[right] \n\t"
|
||||
"st z+, %[left] \n\t")
|
||||
@@ -162,7 +162,7 @@ static uint8_t vli_sub(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
}
|
||||
#define asm_sub 1
|
||||
|
||||
#if ECC_CURVE == secp160r1
|
||||
#if uECC_CURVE == uECC_secp160r1
|
||||
__attribute((noinline))
|
||||
static void vli_mult(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
{
|
||||
@@ -2077,11 +2077,11 @@ static void vli_mult(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
);
|
||||
}
|
||||
#define asm_mult 1
|
||||
#endif /* ECC_CURVE == secp160r1 */
|
||||
#endif /* uECC_CURVE == uECC_secp160r1 */
|
||||
|
||||
#if ECC_SQUARE_FUNC
|
||||
#if uECC_SQUARE_FUNC
|
||||
|
||||
#if ECC_CURVE == secp160r1
|
||||
#if uECC_CURVE == uECC_secp160r1
|
||||
static void vli_square(uint8_t *p_result, uint8_t *p_left)
|
||||
{
|
||||
__asm__ volatile (
|
||||
@@ -3245,8 +3245,8 @@ static void vli_square(uint8_t *p_result, uint8_t *p_left)
|
||||
);
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* ECC_CURVE == secp160r1 */
|
||||
#endif /* ECC_SQUARE_FUNC */
|
||||
#endif /* uECC_CURVE == uECC_secp160r1 */
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
static void vli_modSub_fast(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
{
|
||||
@@ -3261,7 +3261,7 @@ static void vli_modSub_fast(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right
|
||||
"st z+, r18 \n\t" /* Store the first result word. */
|
||||
|
||||
/* Now we just do the remaining words with the carry bit (using SBC) */
|
||||
REPEAT(DEC(ECC_BYTES), "ld r18, x+ \n\t"
|
||||
REPEAT(DEC(uECC_BYTES), "ld r18, x+ \n\t"
|
||||
"ld r19, y+ \n\t"
|
||||
"sbc r18, r19 \n\t"
|
||||
"st z+, r18 \n\t")
|
||||
@@ -3270,7 +3270,7 @@ static void vli_modSub_fast(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right
|
||||
"rjmp done \n\t" /* otherwise we are done */
|
||||
"1: \n\t"
|
||||
|
||||
"sbiw r30, " STR(ECC_BYTES) " \n\t" /* make z point at p_result again */
|
||||
"sbiw r30, " STR(uECC_BYTES) " \n\t" /* make z point at p_result again */
|
||||
"ldi r28, lo8(curve_p) \n\t" /* make y point at curve_p */
|
||||
"ldi r29, hi8(curve_p) \n\t"
|
||||
|
||||
@@ -3279,7 +3279,7 @@ static void vli_modSub_fast(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right
|
||||
"ld r19, y+ \n\t"
|
||||
"add r18, r19 \n\t"
|
||||
"st z+, r18 \n\t"
|
||||
REPEAT(DEC(ECC_BYTES), "ld r18, z \n\t"
|
||||
REPEAT(DEC(uECC_BYTES), "ld r18, z \n\t"
|
||||
"ld r19, y+ \n\t"
|
||||
"adc r18, r19 \n\t"
|
||||
"st z+, r18 \n\t")
|
||||
@@ -3295,7 +3295,7 @@ static void vli_modSub_fast(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right
|
||||
}
|
||||
#define asm_modSub_fast 1
|
||||
|
||||
#if ECC_CURVE == secp160r1
|
||||
#if uECC_CURVE == uECC_secp160r1
|
||||
static void vli_mmod_fast(uint8_t *RESTRICT p_result, uint8_t *RESTRICT p_product)
|
||||
{
|
||||
uint8_t l_carry = 0;
|
||||
@@ -3496,16 +3496,16 @@ static void vli_mmod_fast(uint8_t *RESTRICT p_result, uint8_t *RESTRICT p_produc
|
||||
}
|
||||
#define asm_mmod_fast 1
|
||||
|
||||
#endif /* ECC_CURVE == secp160r1 */
|
||||
#endif /* uECC_CURVE == uECC_secp160r1 */
|
||||
|
||||
#endif /* (ECC_ASM == ecc_asm_fast) */
|
||||
#endif /* (uECC_ASM == uECC_asm_fast) */
|
||||
|
||||
#if !asm_rshift1
|
||||
static void vli_rshift1(uint8_t *p_vli)
|
||||
{
|
||||
uint8_t i = ECC_BYTES;
|
||||
uint8_t i = uECC_BYTES;
|
||||
__asm__ volatile (
|
||||
"adiw r30, " STR(ECC_BYTES) " \n\t"
|
||||
"adiw r30, " STR(uECC_BYTES) " \n\t"
|
||||
"clc \n\t"
|
||||
|
||||
"1: \n\t"
|
||||
@@ -3526,7 +3526,7 @@ static void vli_rshift1(uint8_t *p_vli)
|
||||
#if !asm_add
|
||||
static uint8_t vli_add(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
{
|
||||
uint8_t i = ECC_BYTES;
|
||||
uint8_t i = uECC_BYTES;
|
||||
uint8_t l_carry = 0;
|
||||
uint8_t l_left;
|
||||
uint8_t l_right;
|
||||
@@ -3563,7 +3563,7 @@ static uint8_t vli_add(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
#if !asm_sub
|
||||
static uint8_t vli_sub(uint8_t *p_result, uint8_t *p_left, uint8_t *p_right)
|
||||
{
|
||||
uint8_t i = ECC_BYTES;
|
||||
uint8_t i = uECC_BYTES;
|
||||
uint8_t l_borrow = 0;
|
||||
uint8_t l_left;
|
||||
uint8_t l_right;
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
#ifndef _AVR_ECC_H_
|
||||
#define _AVR_ECC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Platform selection options.
|
||||
If ECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for ECC_PLATFORM are defined below: */
|
||||
#define ecc_arch_other 0
|
||||
#define ecc_x86 1
|
||||
#define ecc_x86_64 2
|
||||
#define ecc_arm 3
|
||||
#define ecc_arm_thumb 4
|
||||
#define ecc_avr 5
|
||||
|
||||
/* If desired, you can define ECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If ECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your platform. */
|
||||
|
||||
/* Inline assembly options.
|
||||
ecc_asm_none - Use standard C99 only.
|
||||
ecc_asm_small - Use GCC inline assembly for the target platform (if available), optimized for minimum size.
|
||||
ecc_asm_fast - Use GCC inline assembly optimized for maximum speed. */
|
||||
#define ecc_asm_none 0
|
||||
#define ecc_asm_small 1
|
||||
#define ecc_asm_fast 2
|
||||
#ifndef ECC_ASM
|
||||
#define ECC_ASM ecc_asm_fast
|
||||
#endif
|
||||
|
||||
/* Curve selection options. */
|
||||
#define secp160r1 1
|
||||
#define secp192r1 2
|
||||
#define secp256r1 3
|
||||
#ifndef ECC_CURVE
|
||||
#define ECC_CURVE secp160r1
|
||||
#endif
|
||||
|
||||
/* 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. This will make things faster by about 8% but increases the code size. */
|
||||
#define ECC_SQUARE_FUNC 1
|
||||
|
||||
|
||||
#define ECC_CONCAT1(a, b) a##b
|
||||
#define ECC_CONCAT(a, b) ECC_CONCAT1(a, b)
|
||||
|
||||
#define ecc_size_1 20 /* secp160r1 */
|
||||
#define ecc_size_2 24 /* secp192r1 */
|
||||
#define ecc_size_3 32 /* secp256r1 */
|
||||
|
||||
#define ECC_BYTES ECC_CONCAT(ecc_size_, ECC_CURVE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* RNG_Function type
|
||||
The RNG function should fill p_size random bytes into p_dest. It should return 1 if
|
||||
p_dest was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using ecc_set_rng()) before calling
|
||||
ecc_make_key() or ecdsa_sign().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define ECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*RNG_Function)(uint8_t *p_dest, unsigned p_size);
|
||||
|
||||
/* ecc_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before ecc_make_key() or ecdsa_sign() are used.
|
||||
|
||||
Inputs:
|
||||
p_rng - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void ecc_set_rng(RNG_Function p_rng);
|
||||
|
||||
/* ecc_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
p_publicKey - Will be filled in with the public key.
|
||||
p_privateKey - Will be filled in with the private key.
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int ecc_make_key(uint8_t p_publicKey[ECC_BYTES*2], uint8_t p_privateKey[ECC_BYTES]);
|
||||
|
||||
/* ecdh_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key.
|
||||
Note: It is recommended that you hash the result of ecdh_shared_secret before using it for symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
p_publicKey - The public key of the remote party.
|
||||
p_privateKey - Your private key.
|
||||
|
||||
Outputs:
|
||||
p_secret - Will be filled in with the shared secret value.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES*2], const uint8_t p_privateKey[ECC_BYTES], uint8_t p_secret[ECC_BYTES]);
|
||||
|
||||
/* ecc_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
p_publicKey - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
p_compressed - Will be filled in with the compressed public key.
|
||||
*/
|
||||
void ecc_compress(uint8_t p_publicKey[ECC_BYTES*2], uint8_t p_compressed[ECC_BYTES+1]);
|
||||
|
||||
/* ecc_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
p_compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
p_publicKey - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void ecc_decompress(uint8_t p_compressed[ECC_BYTES+1], uint8_t p_publicKey[ECC_BYTES*2]);
|
||||
|
||||
/* 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.
|
||||
|
||||
Inputs:
|
||||
p_privateKey - Your private key.
|
||||
p_hash - The message hash to sign.
|
||||
|
||||
Outputs:
|
||||
p_signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_BYTES], uint8_t p_signature[ECC_BYTES*2]);
|
||||
|
||||
/* 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.
|
||||
p_signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES*2], const uint8_t p_hash[ECC_BYTES], const uint8_t p_signature[ECC_BYTES*2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _AVR_ECC_H_ */
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <j0g.h>
|
||||
#include <js0n.h>
|
||||
|
||||
#include <lwm.h>
|
||||
|
||||
#include <bitlash.h>
|
||||
|
||||
#include <GS.h>
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <Scout.h>
|
||||
#include <Shell.h>
|
||||
|
||||
|
||||
#include <ecc.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
static int RNG(uint8_t *p_dest, unsigned p_size)
|
||||
{
|
||||
while(p_size) {
|
||||
long v = random();
|
||||
unsigned l_amount = min(p_size, sizeof(long));
|
||||
memcpy(p_dest, &v, l_amount);
|
||||
p_size -= l_amount;
|
||||
p_dest += l_amount;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void p(int i) {
|
||||
Serial.println(i);
|
||||
}
|
||||
|
||||
void px(uint8_t *v)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<ECC_BYTES; ++i)
|
||||
{
|
||||
Serial.print(v[i]); Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Scout.setup();
|
||||
uint8_t l_private1[ECC_BYTES];
|
||||
uint8_t l_private2[ECC_BYTES];
|
||||
|
||||
uint8_t l_public1[ECC_BYTES * 2];
|
||||
uint8_t l_public2[ECC_BYTES * 2];
|
||||
|
||||
uint8_t l_secret1[ECC_BYTES];
|
||||
uint8_t l_secret2[ECC_BYTES];
|
||||
|
||||
Serial.print("Testing ecc\n");
|
||||
|
||||
ecc_set_rng(&RNG);
|
||||
|
||||
for(;;) {
|
||||
unsigned long a = millis();
|
||||
ecc_make_key(l_public1, l_private1);
|
||||
unsigned long b = millis();
|
||||
|
||||
Serial.print("Made key 1 in "); Serial.println(b-a);
|
||||
a = millis();
|
||||
ecc_make_key(l_public2, l_private2);
|
||||
b = millis();
|
||||
Serial.print("Made key 2 in "); Serial.println(b-a);
|
||||
|
||||
a = millis();
|
||||
int r = ecdh_shared_secret(l_public2, l_private1, l_secret1);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 1 in "); Serial.println(b-a);
|
||||
if(!r)
|
||||
{
|
||||
Serial.print("shared_secret() failed (1)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a = millis();
|
||||
r = ecdh_shared_secret(l_public1, l_private2, l_secret2);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 2 in "); Serial.println(b-a);
|
||||
if(!r)
|
||||
{
|
||||
Serial.print("shared_secret() failed (2)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(memcmp(l_secret1, l_secret2, sizeof(l_secret1)) != 0)
|
||||
{
|
||||
Serial.print("Shared secrets are not identical!\n");
|
||||
/*printf("Shared secret 1 = ");
|
||||
vli_print(l_secret1, ECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Shared secret 2 = ");
|
||||
vli_print(l_secret2, ECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 1 = ");
|
||||
vli_print(l_private1, ECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 2 = ");
|
||||
vli_print(l_private2, ECC_BYTES);
|
||||
printf("\n");*/
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Shared secrets are identical\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
|
||||
}
|
||||
+18
-16
@@ -1,3 +1,5 @@
|
||||
#include <uECC.h>
|
||||
|
||||
#include <j0g.h>
|
||||
#include <js0n.h>
|
||||
|
||||
@@ -13,7 +15,7 @@
|
||||
#include <Shell.h>
|
||||
|
||||
|
||||
#include <ecc.h>
|
||||
#include <uECC.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -33,32 +35,32 @@ static int RNG(uint8_t *p_dest, unsigned p_size)
|
||||
|
||||
void setup() {
|
||||
Scout.setup();
|
||||
uint8_t l_private1[ECC_BYTES];
|
||||
uint8_t l_private2[ECC_BYTES];
|
||||
uint8_t l_private1[uECC_BYTES];
|
||||
uint8_t l_private2[uECC_BYTES];
|
||||
|
||||
uint8_t l_public1[ECC_BYTES * 2];
|
||||
uint8_t l_public2[ECC_BYTES * 2];
|
||||
uint8_t l_public1[uECC_BYTES * 2];
|
||||
uint8_t l_public2[uECC_BYTES * 2];
|
||||
|
||||
uint8_t l_secret1[ECC_BYTES];
|
||||
uint8_t l_secret2[ECC_BYTES];
|
||||
uint8_t l_secret1[uECC_BYTES];
|
||||
uint8_t l_secret2[uECC_BYTES];
|
||||
|
||||
Serial.print("Testing ecc\n");
|
||||
|
||||
ecc_set_rng(&RNG);
|
||||
uECC_set_rng(&RNG);
|
||||
|
||||
for(;;) {
|
||||
unsigned long a = millis();
|
||||
ecc_make_key(l_public1, l_private1);
|
||||
uECC_make_key(l_public1, l_private1);
|
||||
unsigned long b = millis();
|
||||
|
||||
Serial.print("Made key 1 in "); Serial.println(b-a);
|
||||
a = millis();
|
||||
ecc_make_key(l_public2, l_private2);
|
||||
uECC_make_key(l_public2, l_private2);
|
||||
b = millis();
|
||||
Serial.print("Made key 2 in "); Serial.println(b-a);
|
||||
|
||||
a = millis();
|
||||
int r = ecdh_shared_secret(l_public2, l_private1, l_secret1);
|
||||
int r = uECC_shared_secret(l_public2, l_private1, l_secret1);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 1 in "); Serial.println(b-a);
|
||||
if(!r)
|
||||
@@ -68,7 +70,7 @@ void setup() {
|
||||
}
|
||||
|
||||
a = millis();
|
||||
r = ecdh_shared_secret(l_public1, l_private2, l_secret2);
|
||||
r = uECC_shared_secret(l_public1, l_private2, l_secret2);
|
||||
b = millis();
|
||||
Serial.print("Shared secret 2 in "); Serial.println(b-a);
|
||||
if(!r)
|
||||
@@ -81,16 +83,16 @@ void setup() {
|
||||
{
|
||||
Serial.print("Shared secrets are not identical!\n");
|
||||
/*printf("Shared secret 1 = ");
|
||||
vli_print(l_secret1, ECC_BYTES);
|
||||
vli_print(l_secret1, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Shared secret 2 = ");
|
||||
vli_print(l_secret2, ECC_BYTES);
|
||||
vli_print(l_secret2, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 1 = ");
|
||||
vli_print(l_private1, ECC_BYTES);
|
||||
vli_print(l_private1, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 2 = ");
|
||||
vli_print(l_private2, ECC_BYTES);
|
||||
vli_print(l_private2, uECC_BYTES);
|
||||
printf("\n");*/
|
||||
}
|
||||
else
|
||||
|
||||
+15
-15
@@ -1,4 +1,4 @@
|
||||
#include "ecc.h"
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -16,14 +16,14 @@ int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
uint8_t l_private1[ECC_BYTES];
|
||||
uint8_t l_private2[ECC_BYTES];
|
||||
uint8_t l_private1[uECC_BYTES];
|
||||
uint8_t l_private2[uECC_BYTES];
|
||||
|
||||
uint8_t l_public1[ECC_BYTES * 2];
|
||||
uint8_t l_public2[ECC_BYTES * 2];
|
||||
uint8_t l_public1[uECC_BYTES * 2];
|
||||
uint8_t l_public2[uECC_BYTES * 2];
|
||||
|
||||
uint8_t l_secret1[ECC_BYTES];
|
||||
uint8_t l_secret2[ECC_BYTES];
|
||||
uint8_t l_secret1[uECC_BYTES];
|
||||
uint8_t l_secret2[uECC_BYTES];
|
||||
|
||||
printf("Testing 256 random private key pairs\n");
|
||||
|
||||
@@ -32,16 +32,16 @@ int main()
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
ecc_make_key(l_public1, l_private1);
|
||||
ecc_make_key(l_public2, l_private2);
|
||||
uECC_make_key(l_public1, l_private1);
|
||||
uECC_make_key(l_public2, l_private2);
|
||||
|
||||
if(!ecdh_shared_secret(l_public2, l_private1, l_secret1))
|
||||
if(!uECC_shared_secret(l_public2, l_private1, l_secret1))
|
||||
{
|
||||
printf("shared_secret() failed (1)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!ecdh_shared_secret(l_public1, l_private2, l_secret2))
|
||||
if(!uECC_shared_secret(l_public1, l_private2, l_secret2))
|
||||
{
|
||||
printf("shared_secret() failed (2)\n");
|
||||
return 1;
|
||||
@@ -51,16 +51,16 @@ int main()
|
||||
{
|
||||
printf("Shared secrets are not identical!\n");
|
||||
printf("Shared secret 1 = ");
|
||||
vli_print(l_secret1, ECC_BYTES);
|
||||
vli_print(l_secret1, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Shared secret 2 = ");
|
||||
vli_print(l_secret2, ECC_BYTES);
|
||||
vli_print(l_secret2, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 1 = ");
|
||||
vli_print(l_private1, ECC_BYTES);
|
||||
vli_print(l_private1, uECC_BYTES);
|
||||
printf("\n");
|
||||
printf("Private key 2 = ");
|
||||
vli_print(l_private2, ECC_BYTES);
|
||||
vli_print(l_private2, uECC_BYTES);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,16 +1,16 @@
|
||||
#include "ecc.h"
|
||||
#include "uECC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t l_public[ECC_BYTES*2];
|
||||
uint8_t l_private[ECC_BYTES];
|
||||
uint8_t l_public[uECC_BYTES*2];
|
||||
uint8_t l_private[uECC_BYTES];
|
||||
|
||||
uint8_t l_hash[ECC_BYTES];
|
||||
uint8_t l_hash[uECC_BYTES];
|
||||
|
||||
uint8_t l_sig[ECC_BYTES*2];
|
||||
uint8_t l_sig[uECC_BYTES*2];
|
||||
|
||||
int i;
|
||||
|
||||
@@ -21,18 +21,18 @@ int main()
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
ecc_make_key(l_public, l_private);
|
||||
memcpy(l_hash, l_public, ECC_BYTES);
|
||||
uECC_make_key(l_public, l_private);
|
||||
memcpy(l_hash, l_public, uECC_BYTES);
|
||||
|
||||
if(!ecdsa_sign(l_private, l_hash, l_sig))
|
||||
if(!uECC_sign(l_private, l_hash, l_sig))
|
||||
{
|
||||
printf("ecdsa_sign() failed\n");
|
||||
printf("uECC_sign() failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!ecdsa_verify(l_public, l_hash, l_sig))
|
||||
if(!uECC_verify(l_public, l_hash, l_sig))
|
||||
{
|
||||
printf("ecdsa_verify() failed\n");
|
||||
printf("uECC_verify() failed\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
+371
-371
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
#ifndef _MICRO_ECC_H_
|
||||
#define _MICRO_ECC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_avr 5
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your platform. */
|
||||
|
||||
/* Inline assembly options.
|
||||
uECC_asm_none - Use standard C99 only.
|
||||
uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for minimum size.
|
||||
uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */
|
||||
#define uECC_asm_none 0
|
||||
#define uECC_asm_small 1
|
||||
#define uECC_asm_fast 2
|
||||
#ifndef uECC_ASM
|
||||
#define uECC_ASM uECC_asm_fast
|
||||
#endif
|
||||
|
||||
/* Curve selection options. */
|
||||
#define uECC_secp160r1 1
|
||||
#define uECC_secp192r1 2
|
||||
#define uECC_secp256r1 3
|
||||
#ifndef uECC_CURVE
|
||||
#define uECC_CURVE uECC_secp256r1
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be used for (scalar) squaring
|
||||
instead of the generic multiplication function. This will make things faster by about 8% but increases the code size. */
|
||||
#define uECC_SQUARE_FUNC 1
|
||||
|
||||
#define uECC_CONCAT1(a, b) a##b
|
||||
#define uECC_CONCAT(a, b) uECC_CONCAT1(a, b)
|
||||
|
||||
#define uECC_size_1 20 /* secp160r1 */
|
||||
#define uECC_size_2 24 /* secp192r1 */
|
||||
#define uECC_size_3 32 /* secp256r1 */
|
||||
|
||||
#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill p_size random bytes into p_dest. It should return 1 if
|
||||
p_dest was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
|
||||
uECC_make_key() or uECC_sign().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *p_dest, unsigned p_size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before uECC_make_key() or uECC_sign() are used.
|
||||
|
||||
Inputs:
|
||||
p_rng - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function p_rng);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
p_publicKey - Will be filled in with the public key.
|
||||
p_privateKey - Will be filled in with the private key.
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_make_key(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_privateKey[uECC_BYTES]);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key.
|
||||
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
p_publicKey - The public key of the remote party.
|
||||
p_privateKey - Your private key.
|
||||
|
||||
Outputs:
|
||||
p_secret - Will be filled in with the shared secret value.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_privateKey[uECC_BYTES], uint8_t p_secret[uECC_BYTES]);
|
||||
|
||||
/* uECC_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
p_publicKey - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
p_compressed - Will be filled in with the compressed public key.
|
||||
*/
|
||||
void uECC_compress(uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_compressed[uECC_BYTES+1]);
|
||||
|
||||
/* uECC_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
p_compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
p_publicKey - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void uECC_decompress(uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicKey[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_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.
|
||||
|
||||
Inputs:
|
||||
p_privateKey - Your private key.
|
||||
p_hash - The message hash to sign.
|
||||
|
||||
Outputs:
|
||||
p_signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign(const uint8_t p_privateKey[uECC_BYTES], const uint8_t p_hash[uECC_BYTES], uint8_t p_signature[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_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.
|
||||
p_signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uECC_BYTES], const uint8_t p_signature[uECC_BYTES*2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MICRO_ECC_H_ */
|
||||
Reference in New Issue
Block a user