Use 'uECC_' prefix for everything to avoid conflicts with other libraries. (Fix for #1).

This commit is contained in:
Ken MacKay
2014-04-14 22:09:57 -07:00
parent 8fd5fca278
commit 6044e911ae
8 changed files with 727 additions and 607 deletions
+25 -25
View File
@@ -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;
-169
View File
@@ -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_ */
+120
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+167
View File
@@ -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_ */