Changing which curves are supported… secp160r1 is annoying.

This commit is contained in:
Ken MacKay
2013-05-23 09:25:35 -07:00
parent 4bf9500d11
commit 90d985d57d
4 changed files with 103 additions and 428 deletions
+98 -295
View File
@@ -8,15 +8,12 @@ typedef unsigned int uint;
#define CONCAT(a, b) CONCAT1(a, b)
#define Curve_P_4 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD}
#define Curve_P_5 {0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_P_6 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_P_7 {0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_P_8 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF}
#define Curve_A_4 {0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD}
#define Curve_B_4 {0x2CEE5ED3, 0xD824993C, 0x1079F43D, 0xE87579C1}
#define Curve_A_5 {0x7FFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_B_5 {0xC565FA45, 0x81D4D4AD, 0x65ACF89F, 0x54BD7A8B, 0x1C97BEFC}
#define Curve_A_6 {0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_B_6 {0xC146B9B1, 0xFEB8DEEC, 0x72243049, 0x0FA7E9AB, 0xE59C80E7, 0x64210519}
#define Curve_A_7 {0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
@@ -27,10 +24,6 @@ typedef unsigned int uint;
#define Curve_G_4 { \
{0xA52C5B86, 0x0C28607C, 0x8B899B2D, 0x161FF752}, \
{0xDDED7A83, 0xC02DA292, 0x5BAFEB13, 0xCF5AC839}}
#define Curve_G_5 { \
{0x13CBFC82, 0x68C38BB9, 0x46646989, 0x8EF57328, 0x4A96B568}, \
{0x7AC5FB32, 0x04235137, 0x59DCC912, 0x3168947D, 0x23A62855}}
#define Curve_G_6 { \
{0x82FF1012, 0xF4FF0AFD, 0x43A18800, 0x7CBF20EB, 0xB03090F6, 0x188DA80E}, \
@@ -45,24 +38,15 @@ typedef unsigned int uint;
{0x37BF51F5, 0xCBB64068, 0x6B315ECE, 0x2BCE3357, 0x7C0F9E16, 0x8EE7EB4A, 0xFE1A7F9B, 0x4FE342E2}}
#define Curve_N_4 {0x9038A115, 0x75A30D1B, 0x00000000, 0xFFFFFFFE}
#define Curve_N_5 {0xCA752257, 0xF927AED3, 0x0001F4C8, 0x00000000, 0x00000000, 0x00000001}
#define Curve_N_6 {0xB4D22831, 0x146BC9B1, 0x99DEF836, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_N_7 {0x5C5C2A3D, 0x13DD2945, 0xE0B8F03E, 0xFFFF16A2, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_N_8 {0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#if (ECC_CURVE == secp160r1)
#define NUM_N_DIGITS 6
#else
#define NUM_N_DIGITS NUM_ECC_DIGITS
#endif
static uint32_t curve_p[NUM_ECC_DIGITS] = CONCAT(Curve_P_, ECC_CURVE);
static uint32_t curve_a[NUM_ECC_DIGITS] = CONCAT(Curve_A_, ECC_CURVE);
static uint32_t curve_b[NUM_ECC_DIGITS] = CONCAT(Curve_B_, ECC_CURVE);
static EccPoint curve_G = CONCAT(Curve_G_, ECC_CURVE);
static uint32_t curve_n[NUM_N_DIGITS] = CONCAT(Curve_N_, ECC_CURVE);
static void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, uint p_size, uint32_t *p_mod, uint p_modSize);
static uint32_t curve_n[NUM_ECC_DIGITS] = CONCAT(Curve_N_, ECC_CURVE);
static void vli_clear(uint32_t *p_vli, uint p_size)
{
@@ -341,44 +325,6 @@ static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
}
}
#elif ECC_CURVE == secp160r1
/* Computes p_result = p_product % curve_p.
See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
{
uint32_t l_tmp[NUM_ECC_DIGITS];
int l_carry;
vli_set(p_result, p_product, NUM_ECC_DIGITS);
l_tmp[0] = (p_product[5] & 0x7FFFFFFF) | (p_product[5] << 31);
l_tmp[1] = (p_product[5] >> 1) | (p_product[6] << 31);
l_tmp[2] = (p_product[6] >> 1) | (p_product[7] << 31);
l_tmp[3] = (p_product[7] >> 1) | (p_product[8] << 31);
l_tmp[4] = (p_product[8] >> 1) | (p_product[9] << 31);
l_carry = vli_add(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
l_tmp[0] = (p_product[9] >> 1) | (p_product[5] & 0x80000000);
l_tmp[1] = p_product[6];
l_tmp[2] = p_product[7];
l_tmp[3] = p_product[8];
l_tmp[4] = p_product[9];
l_carry += vli_add(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
l_tmp[0] = ((p_product[9] & 0x00000002) << 30);
l_tmp[1] = (p_product[9] >> 2);
l_tmp[2] = 0;
l_tmp[3] = 0;
l_tmp[4] = 0;
l_carry += vli_add(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
while(l_carry || vli_cmp(curve_p, p_result, NUM_ECC_DIGITS) != 1)
{
l_carry -= vli_sub(p_result, p_result, curve_p, NUM_ECC_DIGITS);
}
}
#elif ECC_CURVE == secp192r1
/* Computes p_result = p_product % curve_p.
@@ -411,55 +357,6 @@ static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
}
}
#elif ECC_CURVE == secp224r1
/* Computes p_result = p_product % curve_p.
See http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
{
uint32_t l_tmp[NUM_ECC_DIGITS];
int l_carry;
vli_set(p_result, p_product, NUM_ECC_DIGITS);
l_tmp[0] = l_tmp[1] = l_tmp[2] = 0;
l_tmp[3] = p_product[7];
l_tmp[4] = p_product[8];
l_tmp[5] = p_product[9];
l_tmp[6] = p_product[10];
l_carry = vli_add(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
l_tmp[3] = p_product[11];
l_tmp[4] = p_product[12];
l_tmp[5] = p_product[13];
l_tmp[6] = 0;
l_carry += vli_add(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
vli_set(l_tmp, &p_product[7]);
l_carry -= vli_sub(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
l_tmp[0] = p_product[11];
l_tmp[1] = p_product[12];
l_tmp[2] = p_product[13];
l_tmp[3] = l_tmp[4] = l_tmp[5] = l_tmp[6] = 0;
l_carry -= vli_sub(p_result, p_result, l_tmp, NUM_ECC_DIGITS);
if(l_carry < 0)
{
do
{
l_carry += vli_add(p_result, p_result, curve_p, NUM_ECC_DIGITS);
} while(l_carry < 0);
}
else
{
while(l_carry || vli_cmp(curve_p, p_result, NUM_ECC_DIGITS) != 1)
{
l_carry -= vli_sub(p_result, p_result, curve_p, NUM_ECC_DIGITS);
}
}
}
#elif ECC_CURVE == secp256r1
/* Computes p_result = p_product % curve_p
@@ -568,6 +465,39 @@ static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
}
}
#elif ECC_CURVE == secp384r1
static void omega_mult(uint32_t *p_result, uint32_t *p_right)
{
/* Multiply by (2^128 + 2^96 - 2^32 + 1). */
vli_set(p_result, p_right, NUM_ECC_DIGITS); /* 1 */
p_result[2 + NUM_ECC_DIGITS] -= vli_sub(p_result + 1, p_result + 1, p_right, NUM_ECC_DIGITS); /* -2^32 + 1 */
p_result[4 + NUM_ECC_DIGITS] = vli_add(p_result + 3, p_result + 3, p_right, NUM_ECC_DIGITS); /* 2^96 - 2^32 + 1 */
// TODO
}
/* Computes p_result = p_product % curve_p
see PDF "Comparing Elliptic Curve Cryptography and RSA on 8-bit CPUs"
section "Curve-Specific Optimizations" */
static void vli_mmod_fast(uint32_t *p_result, uint32_t *p_product)
{
uint32_t l_tmp[2*NUM_ECC_DIGITS];
while (!vli_zero(p_product + NUM_ECC_DIGITS)) /* While c1 != 0 */
{
vli_clear(l_tmp, 2*NUM_ECC_DIGITS);
omega_mult(l_tmp, p_product + NUM_ECC_DIGITS); /* tmp = w * c1 */
vli_clear(p_product + NUM_ECC_DIGITS, NUM_ECC_DIGITS); /* p = c0 */
vli_add(p_product, l_tmp, p_product, NUM_ECC_DIGITS + 5); /* (c1, c0) = w * c1 + c0 */
}
while (vli_cmp(l_tmp1, curve_p, NUM_ECC_DIGITS) > 0)
{
vli_sub(l_tmp1, l_tmp1, curve_p, NUM_ECC_DIGITS);
}
vli_set(p_result, l_tmp1, NUM_ECC_DIGITS);
}
#endif
/* Computes p_result = (p_left * p_right) % curve_p. */
@@ -634,17 +564,18 @@ static void vli_modSquare_fast(uint32_t *p_result, uint32_t *p_left)
#endif /* ECC_SQUARE_FUNC */
#define EVEN(vli) (!(vli[0] & 1))
/* Computes p_result = (p_left / p_right) % p_mod. All VLIs are the same size.
/* Computes p_result = (1 / p_input) % p_mod. All VLIs are the same size.
See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf */
static void vli_modDiv(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, uint32_t *p_mod, uint p_size)
static void vli_modInv(uint32_t *p_result, uint32_t *p_input, uint32_t *p_mod, uint p_size)
{
uint32_t a[p_size], b[p_size], u[p_size], v[p_size];
uint32_t l_carry;
vli_set(a, p_right, p_size);
vli_set(a, p_input, p_size);
vli_set(b, p_mod, p_size);
vli_set(u, p_left, p_size);
vli_clear(u, p_size);
u[0] = 1;
vli_clear(v, p_size);
int l_cmpResult;
@@ -720,17 +651,6 @@ static void vli_modDiv(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
vli_set(p_result, u, p_size);
}
/* Computes p_result = (1 / p_input) % p_mod. All VLIs are the same size. */
static void vli_modInv(uint32_t *p_result, uint32_t *p_input, uint32_t *p_mod, uint p_size)
{
uint32_t n[p_size];
vli_clear(n, p_size);
n[0] = 1;
vli_modDiv(p_result, n, p_input, p_mod, p_size);
}
/* ------ Point operations ------ */
/* Clears a point (set it to the point at infinity). */
@@ -875,14 +795,14 @@ static void EccPoint_add_mixed(EccPoint *P3, uint32_t *Z3, EccPoint *P1, uint32_
/* Computes p_result = p_point * p_scalar. p_result must not be the same as p_point.
Uses modified Jacobian coordinates to reduce divisions, and NAF to reduce point adds. */
static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_scalar, uint p_size)
static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_scalar)
{
uint32_t l_tmp[NUM_ECC_DIGITS];
uint32_t Z1[NUM_ECC_DIGITS];
uint32_t l_plus[NUM_ECC_DIGITS];
uint32_t l_minus[NUM_ECC_DIGITS];
int l_numBits = vli_numBits(p_scalar, p_size);
int l_numBits = vli_numBits(p_scalar, NUM_ECC_DIGITS);
uint l_carry;
int i;
@@ -950,12 +870,12 @@ static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_sca
/* Computes p_result = p_point * p_scalar. p_result must not be the same as p_point.
Uses modified Jacobian coordinates to reduce divisions. */
static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_scalar, uint p_size)
static void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint32_t *p_scalar)
{
uint32_t l_tmp[NUM_ECC_DIGITS];
uint32_t Z1[NUM_ECC_DIGITS];
uint l_numBits = vli_numBits(p_scalar, p_size);
uint l_numBits = vli_numBits(p_scalar, NUM_ECC_DIGITS);
int i;
vli_clear(Z1, NUM_ECC_DIGITS);
@@ -984,7 +904,7 @@ int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey,
{
EccPoint l_product;
EccPoint_mult(&l_product, p_publicKey, p_privateKey, NUM_ECC_DIGITS);
EccPoint_mult(&l_product, p_publicKey, p_privateKey);
if(EccPoint_isZero(&l_product))
{
return 0;
@@ -1012,7 +932,7 @@ int ecdh_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS],
return 0; /* The private key cannot be 0 (mod p). */
}
EccPoint_mult(p_publicKey, &curve_G, p_privateKey, NUM_ECC_DIGITS);
EccPoint_mult(p_publicKey, &curve_G, p_privateKey);
return 1;
}
@@ -1049,184 +969,68 @@ int ecc_valid_public_key(EccPoint *p_publicKey)
/* -------- ECDSA code -------- */
/* Computes p_result = p_left % p_mod */
/* Size of p_result == size of p_mod == p_modSize */
static void vli_mod(uint32_t *p_result, uint32_t *p_left, uint p_leftSize, uint32_t *p_mod, uint p_modSize)
/* Computes p_result = (p_left * p_right) % p_mod. */
static void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, uint32_t *p_mod)
{
uint l_modBits = vli_numBits(p_mod, p_modSize);
uint32_t l_product[2 * NUM_ECC_DIGITS];
uint32_t l_modMultiple[2 * NUM_ECC_DIGITS];
uint l_productBits;
uint l_modBits = vli_numBits(p_mod, NUM_ECC_DIGITS);
uint i;
if(l_modBits == 0)
{ /* Divide by 0. */
return;
}
uint l_leftDigits = vli_numDigits(p_left, p_leftSize);
uint l_leftBits = vli_numBits(p_left, l_leftDigits);
vli_mult(l_product, p_left, p_right, NUM_ECC_DIGITS);
l_productBits = vli_numBits(l_product, 2 * NUM_ECC_DIGITS);
if(l_leftBits < l_modBits)
{ /* p_left < p_mod, so p_result = p_left. */
vli_set(p_result, p_left, p_modSize); /* Use p_modSize because that is the size of p_result. */
if(l_productBits < l_modBits)
{ /* l_product < p_mod. */
vli_set(p_result, l_product, NUM_ECC_DIGITS);
return;
}
/* Shift p_mod by (l_leftBits - l_modBits). This multiplies p_mod by the largest
power of two possible while still resulting in a number less than p_left. */
uint32_t l_multiple[l_leftDigits];
memset(l_multiple, 0, l_leftDigits * sizeof(uint32_t));
uint l_digitShift = (l_leftBits - l_modBits) / 32;
uint l_bitShift = (l_leftBits - l_modBits) % 32;
vli_set(l_multiple + l_digitShift, p_mod, p_modSize);
for(i=0; i<2 * NUM_ECC_DIGITS; ++i)
{
l_modMultiple[i] = 0;
}
uint l_digitShift = (l_productBits - l_modBits) / 32;
uint l_bitShift = (l_productBits - l_modBits) % 32;
if(l_bitShift)
{
vli_lshift(l_multiple, l_multiple, l_bitShift, l_leftDigits);
l_modMultiple[l_digitShift + NUM_ECC_DIGITS] = vli_lshift(l_modMultiple + l_digitShift, p_mod, l_bitShift, NUM_ECC_DIGITS);
}
/* Copy left side into remainder. */
uint32_t l_remainder[l_leftDigits];
vli_set(l_remainder, p_left, l_leftDigits);
/* Copy right side into divisor of same size (so we can compare). */
uint32_t l_divisor[l_leftDigits];
memset(l_divisor, 0, l_leftDigits * sizeof(uint32_t));
vli_set(l_divisor, p_mod, p_modSize);
/* Subtract all multiples of l_divisor (= p_mod) to get the remainder. */
while(vli_cmp(l_multiple, l_divisor, l_leftDigits) >= 0)
else
{
if(vli_cmp(l_multiple, l_remainder, l_leftDigits) <= 0)
{
vli_sub(l_remainder, l_remainder, l_multiple, l_leftDigits);
}
vli_rshift1(l_multiple, l_leftDigits);
vli_set(l_modMultiple + l_digitShift, p_mod, NUM_ECC_DIGITS);
}
vli_set(p_result, l_remainder, p_modSize);
/* Subtract all multiples of p_mod to get the remainder. */
while(l_productBits > NUM_ECC_DIGITS * 32 || vli_cmp(l_modMultiple, p_mod, NUM_ECC_DIGITS) >= 0)
{
if(vli_cmp(l_modMultiple, l_product, 2 * NUM_ECC_DIGITS) <= 0)
{
vli_sub(l_product, l_product, l_modMultiple, 2 * NUM_ECC_DIGITS);
}
vli_rshift1(l_modMultiple, 2 * NUM_ECC_DIGITS);
--l_productBits;
}
vli_set(p_result, l_product, NUM_ECC_DIGITS);
}
/* Computes p_result = (p_left * p_right) % p_mod. */
static void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, uint p_size, uint32_t *p_mod, uint p_modSize)
{
uint32_t l_product[2 * p_size];
vli_mult(l_product, p_left, p_right, p_size);
vli_mod(p_result, l_product, 2 * p_size, p_mod, p_modSize);
}
static uint max_uint(uint a, uint b)
static uint max(uint a, uint b)
{
return (a > b ? a : b);
}
/* We separate the code for secp160r1 out because NUM_ECC_DIGITS is not large enough to hold n for that curve. */
#if (ECC_CURVE == secp160r1)
int ecdsa_sign(uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS], uint32_t p_hash[NUM_ECC_DIGITS],
uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS])
{
uint32_t k[NUM_N_DIGITS], s1[NUM_N_DIGITS], e[NUM_N_DIGITS];
EccPoint l_tmp;
if(vli_isZero(p_random, NUM_ECC_DIGITS))
{ /* The random number must not be 0. */
return 0;
}
/* tmp = k * G */
EccPoint_mult(&l_tmp, &curve_G, p_random, NUM_ECC_DIGITS);
/* r = x1 (mod n) */
vli_set(r, l_tmp.x, NUM_ECC_DIGITS);
if(vli_isZero(r, NUM_ECC_DIGITS))
{ /* If r == 0, fail (need a different random number). */
return 0;
}
vli_set(k, p_random, NUM_ECC_DIGITS);
k[5] = 0;
vli_set(e, p_hash, NUM_ECC_DIGITS);
e[5] = 0;
vli_modMult(s1, r, p_privateKey, NUM_ECC_DIGITS, curve_n, NUM_N_DIGITS); /* s1 = r*d */
vli_modAdd(s1, e, s1, curve_n, NUM_N_DIGITS); /* s1 = e + r*d */
vli_modDiv(s1, s1, k, curve_n, NUM_N_DIGITS); /* s1 = (e + r*d) / k */
if(vli_numDigits(s1, NUM_N_DIGITS) > NUM_ECC_DIGITS)
{ /* s is too big to fit in the result buffer (should be very rare). */
return 0;
}
vli_set(s, s1, NUM_ECC_DIGITS);
return 1;
}
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])
{
uint32_t w[NUM_N_DIGITS], u1[NUM_N_DIGITS], u2[NUM_N_DIGITS];
uint32_t Z[NUM_ECC_DIGITS];
EccPoint l_result, l_sum;
if(vli_isZero(r, NUM_ECC_DIGITS) || vli_isZero(s, NUM_ECC_DIGITS))
{ /* r, s must not be 0. */
return 0;
}
/* Calculate u1 and u2. */
vli_set(w, s, NUM_ECC_DIGITS);
w[NUM_ECC_DIGITS] = 0;
vli_modInv(w, w, curve_n, NUM_N_DIGITS); /* w = s^-1 */
vli_set(u1, p_hash, NUM_ECC_DIGITS);
u1[NUM_ECC_DIGITS] = 0;
vli_modMult(u1, u1, w, NUM_N_DIGITS, curve_n, NUM_N_DIGITS); /* u1 = e*w */
vli_set(u2, r, NUM_ECC_DIGITS);
u2[NUM_ECC_DIGITS] = 0;
vli_modMult(u2, u2, w, NUM_N_DIGITS, curve_n, NUM_N_DIGITS); /* u2 = r*w */
/* Calculate l_sum = G + Q. */
vli_clear(Z, NUM_ECC_DIGITS);
Z[0] = 1;
EccPoint_add_mixed(&l_sum, Z, p_publicKey, Z, &curve_G);
vli_modInv(Z, Z, curve_p, NUM_ECC_DIGITS); /* Z1 = 1/Z */
vli_modSquare_fast(w, Z); /* w = 1/Z^2 */
vli_modMult_fast(l_sum.x, l_sum.x, w); /* x = x/Z^2 */
vli_modMult_fast(w, Z, w); /* tmp = 1/Z^3 */
vli_modMult_fast(l_sum.y, l_sum.y, w); /* y = y/Z^3 */
/* Use Shamir's trick to calculate u1*G + u2*Q */
uint l_numBits = max_uint(vli_numBits(u1, NUM_N_DIGITS), vli_numBits(u2, NUM_N_DIGITS));
vli_clear(Z, NUM_ECC_DIGITS);
EccPoint_clear(&l_result);
EccPoint *l_points[4] = {NULL, &curve_G, p_publicKey, &l_sum};
int i;
for(i = l_numBits - 1; i >= 0; --i)
{
EccPoint_double_projective(&l_result, Z, &l_result, Z);
int l_index = (!!vli_testBit(u1, i)) | ((!!vli_testBit(u2, i)) << 1);
EccPoint *l_point = l_points[l_index];
if(l_point)
{
EccPoint_add_mixed(&l_result, Z, &l_result, Z, l_point);
}
}
vli_modInv(Z, Z, curve_p, NUM_ECC_DIGITS); /* Z = 1/Z */
vli_modSquare_fast(Z, Z); /* Z = 1/Z^2 */
vli_modMult_fast(l_result.x, l_result.x, Z); /* x = x/Z^2 */
/* Accept only if v == r. */
return (vli_cmp(l_result.x, r, NUM_ECC_DIGITS) == 0);
}
#else /* (ECC_CURVE == secp160r1) */
int ecdsa_sign(uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS], uint32_t p_hash[NUM_ECC_DIGITS],
uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS])
{
uint32_t k[NUM_ECC_DIGITS];
EccPoint l_tmp;
EccPoint p;
if(vli_isZero(p_random, NUM_ECC_DIGITS))
{ /* The random number must not be 0. */
@@ -1234,35 +1038,36 @@ int ecdsa_sign(uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_
}
vli_set(k, p_random, NUM_ECC_DIGITS);
if(vli_cmp(curve_n, k, NUM_N_DIGITS) != 1)
if(vli_cmp(curve_n, k, NUM_ECC_DIGITS) != 1)
{
vli_sub(k, k, curve_n, NUM_N_DIGITS);
vli_sub(k, k, curve_n, NUM_ECC_DIGITS);
}
/* tmp = k * G */
EccPoint_mult(&l_tmp, &curve_G, k, NUM_ECC_DIGITS);
EccPoint_mult(&p, &curve_G, k);
/* r = x1 (mod n) */
vli_set(r, l_tmp.x, NUM_ECC_DIGITS);
if(vli_cmp(curve_n, r, NUM_N_DIGITS) != 1)
vli_set(r, p.x, NUM_ECC_DIGITS);
if(vli_cmp(curve_n, r, NUM_ECC_DIGITS) != 1)
{
vli_sub(r, r, curve_n, NUM_N_DIGITS);
vli_sub(r, r, curve_n, NUM_ECC_DIGITS);
}
if(vli_isZero(r, NUM_ECC_DIGITS))
{ /* If r == 0, fail (need a different random number). */
return 0;
}
vli_modMult(s, r, p_privateKey, NUM_ECC_DIGITS, curve_n, NUM_N_DIGITS); /* s1 = r*d */
vli_modAdd(s, p_hash, s, curve_n, NUM_N_DIGITS); /* s1 = e + r*d */
vli_modDiv(s, s, k, curve_n, NUM_N_DIGITS); /* s1 = (e + r*d) / k */
vli_modMult(s, r, p_privateKey, curve_n); /* s = r*d */
vli_modAdd(s, p_hash, s, curve_n, NUM_ECC_DIGITS); /* s = e + r*d */
vli_modInv(k, k, curve_n, NUM_ECC_DIGITS); /* k = 1 / k */
vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */
return 1;
}
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])
{
uint32_t u1[NUM_N_DIGITS], u2[NUM_N_DIGITS];
uint32_t u1[NUM_ECC_DIGITS], u2[NUM_ECC_DIGITS];
uint32_t Z[NUM_ECC_DIGITS];
EccPoint l_result, l_sum;
@@ -1271,15 +1076,15 @@ int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_
return 0;
}
if(vli_cmp(curve_n, r, NUM_N_DIGITS) != 1 || vli_cmp(curve_n, s, NUM_N_DIGITS) != 1)
if(vli_cmp(curve_n, r, NUM_ECC_DIGITS) != 1 || vli_cmp(curve_n, s, NUM_ECC_DIGITS) != 1)
{ /* r, s must be < n. */
return 0;
}
/* Calculate u1 and u2. */
vli_modInv(Z, s, curve_n, NUM_N_DIGITS); /* Z = s^-1 */
vli_modMult(u1, p_hash, Z, NUM_ECC_DIGITS, curve_n, NUM_N_DIGITS); /* u1 = e/s */
vli_modMult(u2, r, Z, NUM_ECC_DIGITS, curve_n, NUM_N_DIGITS); /* u2 = r/s */
vli_modInv(Z, s, curve_n, NUM_ECC_DIGITS); /* Z = s^-1 */
vli_modMult(u1, p_hash, Z, curve_n); /* u1 = e/s */
vli_modMult(u2, r, Z, curve_n); /* u2 = r/s */
/* Calculate l_sum = G + Q. */
vli_clear(Z, NUM_ECC_DIGITS);
@@ -1294,7 +1099,7 @@ int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_
vli_modMult_fast(l_sum.y, l_sum.y, l_result.x); /* y = y/Z^3 */
/* Use Shamir's trick to calculate u1*G + u2*Q */
uint l_numBits = max_uint(vli_numBits(u1, NUM_N_DIGITS), vli_numBits(u2, NUM_N_DIGITS));
uint l_numBits = max(vli_numBits(u1, NUM_ECC_DIGITS), vli_numBits(u2, NUM_ECC_DIGITS));
vli_clear(Z, NUM_ECC_DIGITS);
EccPoint_clear(&l_result);
@@ -1317,13 +1122,11 @@ int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_
vli_modMult_fast(l_result.x, l_result.x, Z); /* x = x/Z^2 */
/* v = x1 (mod n) */
if(vli_cmp(curve_n, l_result.x, NUM_N_DIGITS) != 1)
if(vli_cmp(curve_n, l_result.x, NUM_ECC_DIGITS) != 1)
{
vli_sub(l_result.x, l_result.x, curve_n, NUM_N_DIGITS);
vli_sub(l_result.x, l_result.x, curve_n, NUM_ECC_DIGITS);
}
/* Accept only if v == r. */
return (vli_cmp(l_result.x, r, NUM_ECC_DIGITS) == 0);
}
#endif
+5 -6
View File
@@ -10,21 +10,20 @@ ECC_USE_NAF - If enabled, this will convert the private key to a non-adjacent fo
Improves speed by about 10%.
ECC_SOFT_MULT64 - For platforms that do not have instructions to allow a fast 64x64 bit multiply (eg Cortex-M0), this option
enables code to do 64x64 bit multiplies faster than libgcc does. Improves speed by about 6% on Cortex-M0
(with 32-cycle multiply instruction). Do not enable on platforms with a fast 64x64 bit multiply.
(with 32-cycle multiply instruction). Do not enable on platforms that have a fast 64x64 bit multiply.
*/
#define ECC_SQUARE_FUNC 1
#define ECC_USE_NAF 1
#define ECC_SQUARE_FUNC 0
#define ECC_USE_NAF 0
#define ECC_SOFT_MULT64 1
#define ECC_CURVE secp192r1
#define secp128r1 4
#define secp160r1 5
#define secp192r1 6
#define secp224r1 7
#define secp256r1 8
#define secp384r1 12
#if (ECC_CURVE != secp128r1 && ECC_CURVE != secp160r1 && ECC_CURVE != secp192r1 && ECC_CURVE != secp224r1 && ECC_CURVE != secp256r1)
#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
-55
View File
@@ -1,55 +0,0 @@
#include "ecdh.h"
#if (ECC_CURVE == secp160r1)
#include <string.h>
#include <stdio.h>
void vli_print(uint32_t *p_vli, unsigned int p_size)
{
while(p_size)
{
printf("%08X ", (unsigned)p_vli[p_size - 1]);
--p_size;
}
}
/* Test data from http://www.secg.org/collateral/gec2.pdf page 2
Requires that ECC_CURVE be set to secp160r1. */
int main()
{
uint32_t l_privateKey[NUM_ECC_DIGITS] = {0xB2A4E982, 0x72CB6D57, 0xB0733079, 0x3CE144E6, 0xAA374FFC};
EccPoint l_publicKey = {
{0x51419DC0, 0x3C032062, 0x0E75A24A, 0xECC406ED, 0x51B4496F},
{0x1756AA6C, 0x4F381CCC, 0x68D79389, 0x73A514B4, 0xC28DCB4B}
};
uint32_t l_random[NUM_ECC_DIGITS] = {0xdecd52da, 0x2ac5d528, 0xb9185c8b, 0x681a3f28, 0x7b012db7};
uint32_t l_hash[NUM_ECC_DIGITS] = {0x9cd0d89d, 0x7850c26c, 0xba3e2571, 0x4706816a, 0xa9993e36};
uint32_t r[NUM_ECC_DIGITS];
uint32_t s[NUM_ECC_DIGITS];
if(!ecdsa_sign(l_privateKey, l_random, l_hash, r, s))
{
printf("ecdsa_sign() failed\n");
}
printf("r: ");
vli_print(r, NUM_ECC_DIGITS);
printf("\n");
printf("s: ");
vli_print(s, NUM_ECC_DIGITS);
printf("\n");
if(!ecdsa_verify(&l_publicKey, l_hash, r, s))
{
printf("ecdsa_verify() failed\n");
}
return 0;
}
#endif
-72
View File
@@ -1,72 +0,0 @@
#include "ecdh.h"
#if (ECC_CURVE == secp160r1)
#include <string.h>
#include <stdio.h>
void vli_print(uint32_t *p_vli, unsigned int p_size)
{
while(p_size)
{
printf("%08X ", (unsigned)p_vli[p_size - 1]);
--p_size;
}
}
/* Test data from http://www.secg.org/collateral/gec2.pdf page 44
Requires that ECC_CURVE be set to secp160r1. */
int main()
{
uint32_t l_expectedSecret[NUM_ECC_DIGITS] = {0x347BB40A, 0x8E6AF594, 0x6E1B74AC, 0x3FFA87A9, 0xCA7C0F8C};
uint32_t l_privateKey1[NUM_ECC_DIGITS] = {0xB2A4E982, 0x72CB6D57, 0xB0733079, 0x3CE144E6, 0xAA374FFC};
uint32_t l_privateKey2[NUM_ECC_DIGITS] = {0x2B460866, 0xE74F277E, 0x15101C66, 0x2A17AD4B, 0x45FB58A9};
EccPoint l_publicKey1 = {
{0x51419DC0, 0x3C032062, 0x0E75A24A, 0xECC406ED, 0x51B4496F},
{0x1756AA6C, 0x4F381CCC, 0x68D79389, 0x73A514B4, 0xC28DCB4B}
};
EccPoint l_publicKey2 = {
{0x07C6E5BC, 0x0F63D567, 0x328739D9, 0x9C0369C2, 0x49B41E0E},
{0x0E9C8F83, 0x111C3EDC, 0x6D232A03, 0x67015ED9, 0x26E008B5}
};
uint32_t l_shared1[NUM_ECC_DIGITS];
uint32_t l_shared2[NUM_ECC_DIGITS];
if(!ecdh_shared_secret(l_shared1, &l_publicKey1, l_privateKey2))
{
printf("shared_secret() failed (1)\n");
return 1;
}
if(!ecdh_shared_secret(l_shared2, &l_publicKey2, l_privateKey1))
{
printf("shared_secret() failed (2)\n");
return 1;
}
if(memcmp(l_shared1, l_shared2, sizeof(l_shared1)) != 0)
{
printf("Shared secrets are not identical!\n");
}
else if(memcmp(l_shared1, l_expectedSecret, sizeof(l_shared1)) != 0)
{
printf("Shared secret is not the expected value!\n");
}
else
{
printf("Everything worked as expected.\n");
}
printf("Shared secret 1 = ");
vli_print(l_shared1, NUM_ECC_DIGITS);
printf("\n");
printf("Shared secret 2 = ");
vli_print(l_shared2, NUM_ECC_DIGITS);
printf("\n");
return 0;
}
#endif