Added support for new secp224r1 curve. Added test to verify uECC_compress() and uECC_decompress() functions.

This commit is contained in:
Evgeni Margolis
2015-06-28 15:02:45 -07:00
parent 8674d479d3
commit ac89ddca67
5 changed files with 400 additions and 31 deletions
+1
View File
@@ -1,5 +1,6 @@
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC(N) uECC_CONCAT(DEC_, N)
+1
View File
@@ -1,5 +1,6 @@
#define DEC_20 19
#define DEC_24 23
#define DEC_28 27
#define DEC_32 31
#define DEC(N) uECC_CONCAT(DEC_, N)
+85
View File
@@ -0,0 +1,85 @@
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
#include "uECC.h"
#include <stdio.h>
#include <string.h>
#ifndef uECC_TEST_NUMBER_OF_ITERATIONS
#define uECC_TEST_NUMBER_OF_ITERATIONS 256
#endif
#if LPC11XX
#include "/Projects/lpc11xx/peripherals/uart.h"
#include "/Projects/lpc11xx/peripherals/time.h"
static uint64_t g_rand = 88172645463325252ull;
int fake_rng(uint8_t *dest, unsigned size) {
while(size) {
g_rand ^= (g_rand << 13);
g_rand ^= (g_rand >> 7);
g_rand ^= (g_rand << 17);
unsigned amount = (size > 8 ? 8 : size);
memcpy(dest, &g_rand, amount);
dest += amount;
size -= amount;
}
return 1;
}
#endif
void vli_print(char *str, uint8_t *vli, unsigned int size) {
printf("%s ", str);
while (size) {
printf("%02X ", (unsigned)vli[size - 1]);
--size;
}
printf("\n");
}
int main() {
#if LPC11XX
uartInit(BAUD_115200);
initTime();
uECC_set_rng(&fake_rng);
#endif
uint8_t public[uECC_BYTES * 2];
uint8_t private[uECC_BYTES];
uint8_t compressed_point[uECC_BYTES + 1];
uint8_t decompressed_point[uECC_BYTES * 2];
int i;
printf("Testing compression and decompression of %d random EC points\n", uECC_TEST_NUMBER_OF_ITERATIONS);
for (i = 0; i < uECC_TEST_NUMBER_OF_ITERATIONS; ++i) {
printf(".");
#if !LPC11XX
fflush(stdout);
#endif
/* Generate arbitrary EC point (public) on Curve */
if (!uECC_make_key(public, private)) {
printf("uECC_make_key() failed\n");
continue;
}
/* compress and decompress point */
uECC_compress(public, compressed_point);
uECC_decompress(compressed_point, decompressed_point);
if (memcmp(public, decompressed_point, 2 * uECC_BYTES) != 0) {
printf("Original and decompressed points are not identical!\n");
vli_print("Original point = ", public, 2 * uECC_BYTES);
vli_print("Compressed point = ", compressed_point, uECC_BYTES + 1);
vli_print("Decompressed point = ", decompressed_point, 2 * uECC_BYTES);
}
}
printf("\n");
return 0;
}
+311 -31
View File
@@ -30,7 +30,7 @@
#endif
#endif
#if (uECC_CURVE == uECC_secp160r1) && (uECC_WORD_SIZE == 8)
#if (uECC_CURVE == uECC_secp160r1 || uECC_CURVE == uECC_secp224r1) && (uECC_WORD_SIZE == 8)
#undef uECC_WORD_SIZE
#define uECC_WORD_SIZE 4
#if (uECC_PLATFORM == uECC_x86_64)
@@ -89,11 +89,13 @@ typedef int8_t cmpresult_t;
#define uECC_WORDS_2 24
#define uECC_WORDS_3 32
#define uECC_WORDS_4 32
#define uECC_WORDS_5 28
#define uECC_N_WORDS_1 21
#define uECC_N_WORDS_2 24
#define uECC_N_WORDS_3 32
#define uECC_N_WORDS_4 32
#define uECC_N_WORDS_5 28
#define Curve_P_1 {0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
@@ -109,6 +111,10 @@ typedef int8_t cmpresult_t;
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
#define Curve_P_5 {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF}
#define Curve_B_1 {0x45, 0xFA, 0x65, 0xC5, 0xAD, 0xD4, 0xD4, 0x81, \
0x9F, 0xF8, 0xAC, 0x65, 0x8B, 0x7A, 0xBD, 0x54, \
@@ -124,6 +130,10 @@ typedef int8_t cmpresult_t;
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define Curve_B_5 {0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27, \
0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50, \
0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C, \
0x85, 0x0A, 0x05, 0xB4}
#define Curve_G_1 { \
{0x82, 0xFC, 0xCB, 0x13, 0xB9, 0x8B, 0xC3, 0x68, \
@@ -161,6 +171,16 @@ typedef int8_t cmpresult_t;
0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D, \
0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48}}
#define Curve_G_5 { \
{0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34, \
0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A, \
0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B, \
0xBD, 0x0C, 0x0E, 0xB7}, \
{0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44, \
0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD, \
0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5, \
0x88, 0x63, 0x37, 0xBD}}
#define Curve_N_1 {0x57, 0x22, 0x75, 0xCA, 0xD3, 0xAE, 0x27, 0xF9, \
0xC8, 0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x01}
@@ -175,6 +195,10 @@ typedef int8_t cmpresult_t;
0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA, \
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
#define Curve_N_5 {0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13, \
0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF}
#elif (uECC_WORD_SIZE == 4)
@@ -194,11 +218,13 @@ typedef int cmpresult_t;
#define uECC_WORDS_2 6
#define uECC_WORDS_3 8
#define uECC_WORDS_4 8
#define uECC_WORDS_5 7
#define uECC_N_WORDS_1 6
#define uECC_N_WORDS_2 6
#define uECC_N_WORDS_3 8
#define uECC_N_WORDS_4 8
#define uECC_N_WORDS_5 7
#define Curve_P_1 {0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_P_2 {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
@@ -206,6 +232,8 @@ typedef int cmpresult_t;
0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF}
#define Curve_P_4 {0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_P_5 {0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_B_1 {0xC565FA45, 0x81D4D4AD, 0x65ACF89F, 0x54BD7A8B, 0x1C97BEFC}
#define Curve_B_2 {0xC146B9B1, 0xFEB8DEEC, 0x72243049, 0x0FA7E9AB, 0xE59C80E7, 0x64210519}
@@ -213,6 +241,8 @@ typedef int cmpresult_t;
0x769886BC, 0xB3EBBD55, 0xAA3A93E7, 0x5AC635D8}
#define Curve_B_4 {0x00000007, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000}
#define Curve_B_5 {0x2355FFB4, 0x270B3943, 0xD7BFD8BA, 0x5044B0B7, \
0xF5413256, 0x0C04B3AB, 0xB4050A85}
#define Curve_G_1 { \
{0x13CBFC82, 0x68C38BB9, 0x46646989, 0x8EF57328, 0x4A96B568}, \
@@ -234,12 +264,20 @@ typedef int cmpresult_t;
{0xFB10D4B8, 0x9C47D08F, 0xA6855419, 0xFD17B448, \
0x0E1108A8, 0x5DA4FBFC, 0x26A3C465, 0x483ADA77}}
#define Curve_G_5 { \
{0x115C1D21, 0x343280D6, 0x56C21122, 0x4A03C1D3, \
0x321390B9, 0x6BB4BF7F, 0xB70E0CBD}, \
{0x85007E34, 0x44D58199, 0x5A074764, 0xCD4375A0, \
0x4C22DFE6, 0xB5F723FB, 0xBD376388}}
#define Curve_N_1 {0xCA752257, 0xF927AED3, 0x0001F4C8, 0x00000000, 0x00000000, 0x00000001}
#define Curve_N_2 {0xB4D22831, 0x146BC9B1, 0x99DEF836, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_N_3 {0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, \
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF}
#define Curve_N_4 {0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, \
0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#define Curve_N_5 {0x5C5C2A3D, 0x13DD2945, 0xE0B8F03E, 0xFFFF16A2, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
#elif (uECC_WORD_SIZE == 8)
@@ -261,11 +299,13 @@ typedef int cmpresult_t;
#define uECC_WORDS_2 3
#define uECC_WORDS_3 4
#define uECC_WORDS_4 4
#define uECC_WORDS_5 4
#define uECC_N_WORDS_1 3
#define uECC_N_WORDS_2 3
#define uECC_N_WORDS_3 4
#define uECC_N_WORDS_4 4
#define uECC_N_WORDS_5 4
#define Curve_P_1 {0xFFFFFFFF7FFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull}
#define Curve_P_2 {0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFEull, 0xFFFFFFFFFFFFFFFFull}
@@ -273,6 +313,8 @@ typedef int cmpresult_t;
0x0000000000000000ull, 0xFFFFFFFF00000001ull}
#define Curve_P_4 {0xFFFFFFFEFFFFFC2Full, 0xFFFFFFFFFFFFFFFFull, \
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull}
#define Curve_P_5 {0x0000000000000001ull, 0xFFFFFFFF00000000ull, \
0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull}
#define Curve_B_1 {0x81D4D4ADC565FA45ull, 0x54BD7A8B65ACF89Full, 0x000000001C97BEFCull}
#define Curve_B_2 {0xFEB8DEECC146B9B1ull, 0x0FA7E9AB72243049ull, 0x64210519E59C80E7ull}
@@ -280,6 +322,8 @@ typedef int cmpresult_t;
0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull}
#define Curve_B_4 {0x0000000000000007ull, 0x0000000000000000ull, \
0x0000000000000000ull, 0x0000000000000000ull}
#define Curve_B_5 {0x270B39432355FFB4ull, 0x5044B0B7D7BFD8BAull, \
0x0C04B3ABF5413256ull, 0x00000000B4050A85ull}
#define Curve_G_1 { \
{0x68C38BB913CBFC82ull, 0x8EF5732846646989ull, 0x000000004A96B568ull}, \
@@ -297,12 +341,18 @@ typedef int cmpresult_t;
{0x59F2815B16F81798ull, 0x029BFCDB2DCE28D9ull, 0x55A06295CE870B07ull, 0x79BE667EF9DCBBACull}, \
{0x9C47D08FFB10D4B8ull, 0xFD17B448A6855419ull, 0x5DA4FBFC0E1108A8ull, 0x483ADA7726A3C465ull}}
#define Curve_G_5 { \
{0x343280D6115C1D21ull, 0x4A03C1D356C21122ull, 0x6BB4BF7F321390B9ull, 0x00000000B70E0CBDull}, \
{0x44D5819985007E34ull, 0xCD4375A05A074764ull, 0xB5F723FB4C22DFE6ull, 0x00000000BD376388ull}}
#define Curve_N_1 {0xF927AED3CA752257ull, 0x000000000001F4C8ull, 0x0000000100000000ull}
#define Curve_N_2 {0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull, 0xFFFFFFFFFFFFFFFFull}
#define Curve_N_3 {0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull, \
0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull}
#define Curve_N_4 {0xBFD25E8CD0364141ull, 0xBAAEDCE6AF48A03Bull, \
0xFFFFFFFFFFFFFFFEull, 0xFFFFFFFFFFFFFFFFull}
#define Curve_N_5 {0x13DD29455C5C2A3Dull, 0xFFFF16A2E0B8F03Eull, \
0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull}
#endif /* (uECC_WORD_SIZE == 8) */
@@ -319,37 +369,37 @@ static const uECC_word_t curve_b[uECC_WORDS] = uECC_CONCAT(Curve_B_, uECC_CURVE)
static const EccPoint curve_G = uECC_CONCAT(Curve_G_, uECC_CURVE);
static const uECC_word_t curve_n[uECC_N_WORDS] = uECC_CONCAT(Curve_N_, uECC_CURVE);
static void vli_clear(uECC_word_t *p_vli);
static uECC_word_t vli_isZero(const uECC_word_t *p_vli);
static uECC_word_t vli_testBit(const uECC_word_t *p_vli, bitcount_t p_bit);
static bitcount_t vli_numBits(const uECC_word_t *p_vli, wordcount_t p_maxWords);
static void vli_set(uECC_word_t *p_dest, const uECC_word_t *p_src);
static cmpresult_t vli_cmp(const uECC_word_t *p_left, const uECC_word_t *p_right);
static cmpresult_t vli_equal(const uECC_word_t *p_left, const uECC_word_t *p_right);
static void vli_rshift1(uECC_word_t *p_vli);
static uECC_word_t vli_add(uECC_word_t *p_result,
const uECC_word_t *p_left,
const uECC_word_t *p_right);
static uECC_word_t vli_sub(uECC_word_t *p_result,
const uECC_word_t *p_left,
const uECC_word_t *p_right);
static void vli_mult(uECC_word_t *p_result, const uECC_word_t *p_left, const uECC_word_t *p_right);
static void vli_modAdd(uECC_word_t *p_result,
const uECC_word_t *p_left,
const uECC_word_t *p_right,
const uECC_word_t *p_mod);
static void vli_modSub(uECC_word_t *p_result,
const uECC_word_t *p_left,
const uECC_word_t *p_right,
const uECC_word_t *p_mod);
static void vli_mmod_fast(uECC_word_t *RESTRICT p_result, uECC_word_t *RESTRICT p_product);
static void vli_modMult_fast(uECC_word_t *p_result,
const uECC_word_t *p_left,
const uECC_word_t *p_right);
static void vli_modInv(uECC_word_t *p_result, const uECC_word_t *p_input, const uECC_word_t *p_mod);
static void vli_clear(uECC_word_t *vli);
static uECC_word_t vli_isZero(const uECC_word_t *vli);
static uECC_word_t vli_testBit(const uECC_word_t *vli, bitcount_t bit);
static bitcount_t vli_numBits(const uECC_word_t *vli, wordcount_t max_words);
static void vli_set(uECC_word_t *dest, const uECC_word_t *src);
static cmpresult_t vli_cmp(const uECC_word_t *left, const uECC_word_t *right);
static cmpresult_t vli_equal(const uECC_word_t *left, const uECC_word_t *right);
static void vli_rshift1(uECC_word_t *vli);
static uECC_word_t vli_add(uECC_word_t *result,
const uECC_word_t *left,
const uECC_word_t *right);
static uECC_word_t vli_sub(uECC_word_t *result,
const uECC_word_t *left,
const uECC_word_t *right);
static void vli_mult(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right);
static void vli_modAdd(uECC_word_t *result,
const uECC_word_t *left,
const uECC_word_t *right,
const uECC_word_t *mod);
static void vli_modSub(uECC_word_t *result,
const uECC_word_t *left,
const uECC_word_t *right,
const uECC_word_t *mod);
static void vli_mmod_fast(uECC_word_t *RESTRICT result, uECC_word_t *RESTRICT product);
static void vli_modMult_fast(uECC_word_t *result,
const uECC_word_t *left,
const uECC_word_t *right);
static void vli_modInv(uECC_word_t *result, const uECC_word_t *input, const uECC_word_t *mod);
#if uECC_SQUARE_FUNC
static void vli_square(uECC_word_t *p_result, const uECC_word_t *p_left);
static void vli_modSquare_fast(uECC_word_t *p_result, const uECC_word_t *p_left);
static void vli_square(uECC_word_t *result, const uECC_word_t *left);
static void vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left);
#endif
#if (defined(_WIN32) || defined(_WIN64))
@@ -1273,6 +1323,118 @@ static void omega_mult(uint64_t * RESTRICT result, const uint64_t * RESTRICT rig
}
#endif /* uECC_WORD_SIZE */
#elif uECC_CURVE == uECC_secp224r1
/* Computes result = product % curve_p
from http://www.nsa.gov/ia/_files/nist-routines.pdf */
#if uECC_WORD_SIZE == 1
void vli_mmod_fast(uint8_t *RESTRICT result, uint8_t *RESTRICT product) {
uint8_t tmp[uECC_WORDS];
int8_t carry;
/* t */
vli_set(result, product);
/* s1 */
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43];
carry = vli_add(result, result, tmp);
/* s2 */
tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
carry += vli_add(result, result, tmp);
/* d1 */
tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31];
tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35];
tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39];
tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43];
tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47];
tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51];
tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
carry -= vli_sub(result, result, tmp);
/* d2 */
tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
carry -= vli_sub(result, result, tmp);
if (carry < 0) {
do {
carry += vli_add(result, result, curve_p);
} while (carry < 0);
} else {
while (carry || vli_cmp(curve_p, result) != 1) {
carry -= vli_sub(result, result, curve_p);
}
}
}
#elif uECC_WORD_SIZE == 4
void vli_mmod_fast(uint32_t *RESTRICT result, uint32_t *RESTRICT product)
{
uint32_t tmp[uECC_WORDS];
int carry;
/* t */
vli_set(result, product);
/* s1 */
tmp[0] = tmp[1] = tmp[2] = 0;
tmp[3] = product[7];
tmp[4] = product[8];
tmp[5] = product[9];
tmp[6] = product[10];
carry = vli_add(result, result, tmp);
/* s2 */
tmp[3] = product[11];
tmp[4] = product[12];
tmp[5] = product[13];
tmp[6] = 0;
carry += vli_add(result, result, tmp);
/* d1 */
tmp[0] = product[7];
tmp[1] = product[8];
tmp[2] = product[9];
tmp[3] = product[10];
tmp[4] = product[11];
tmp[5] = product[12];
tmp[6] = product[13];
carry -= vli_sub(result, result, tmp);
/* d2 */
tmp[0] = product[11];
tmp[1] = product[12];
tmp[2] = product[13];
tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0;
carry -= vli_sub(result, result, tmp);
if (carry < 0) {
do {
carry += vli_add(result, result, curve_p);
} while (carry < 0);
} else {
while (carry || vli_cmp(curve_p, result) != 1) {
carry -= vli_sub(result, result, curve_p);
}
}
}
#endif /* uECC_WORD_SIZE */
#endif /* uECC_CURVE */
#endif /* !asm_mmod_fast */
@@ -1650,6 +1812,123 @@ static int EccPoint_compute_public_key(EccPoint *result, uECC_word_t *private) {
return 1;
}
#if uECC_CURVE == uECC_secp224r1
/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void mod_sqrt_secp224r1_rs(uECC_word_t *d1,
uECC_word_t *e1,
uECC_word_t *f1,
const uECC_word_t *d0,
const uECC_word_t *e0,
const uECC_word_t *f0) {
uECC_word_t t[uECC_WORDS];
vli_modSquare_fast(t, d0); /* t <-- d0 ^ 2 */
vli_modMult_fast(e1, d0, e0); /* e1 <-- d0 * e0 */
vli_modAdd(d1, t, f0, curve_p); /* d1 <-- t + f0 */
vli_modAdd(e1, e1, e1, curve_p); /* e1 <-- e1 + e1 */
vli_modMult_fast(f1, t, f0); /* f1 <-- t * f0 */
vli_modAdd(f1, f1, f1, curve_p); /* f1 <-- f1 + f1 */
vli_modAdd(f1, f1, f1, curve_p); /* f1 <-- f1 + f1 */
}
/* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void mod_sqrt_secp224r1_rss(uECC_word_t *d1,
uECC_word_t *e1,
uECC_word_t *f1,
const uECC_word_t *d0,
const uECC_word_t *e0,
const uECC_word_t *f0,
const bitcount_t j) {
bitcount_t i;
vli_set(d1, d0); /* d1 <-- d0 */
vli_set(e1, e0); /* e1 <-- e0 */
vli_set(f1, f0); /* f1 <-- f0 */
for (i = 1; i <= j; i++) {
mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */
}
}
/* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void mod_sqrt_secp224r1_rm(uECC_word_t *d2,
uECC_word_t *e2,
uECC_word_t *f2,
const uECC_word_t *c,
const uECC_word_t *d0,
const uECC_word_t *e0,
const uECC_word_t *d1,
const uECC_word_t *e1) {
uECC_word_t t1[uECC_WORDS];
uECC_word_t t2[uECC_WORDS];
vli_modMult_fast(t1, e0, e1); /* t1 <-- e0 * e1 */
vli_modMult_fast(t1, t1, c); /* t1 <-- t1 * c */
vli_modSub_fast(t1, curve_p, t1); /* t1 <-- p - t1 */
vli_modMult_fast(t2, d0, d1); /* t2 <-- d0 * d1 */
vli_modAdd(t2, t2, t1, curve_p); /* t2 <-- t2 + t1 */
vli_modMult_fast(t1, d0, e1); /* t1 <-- d0 * e1 */
vli_modMult_fast(e2, d1, e0); /* e2 <-- d1 * e0 */
vli_modAdd(e2, e2, t1, curve_p); /* e2 <-- e2 + t1 */
vli_modSquare_fast(f2, e2); /* f2 <-- e2^2 */
vli_modMult_fast(f2, f2, c); /* f2 <-- f2 * c */
vli_modSub_fast(f2, curve_p, f2); /* f2 <-- p - f2 */
vli_set(d2, t2); /* d2 <-- t2 */
}
/* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void mod_sqrt_secp224r1_rp(uECC_word_t *d1,
uECC_word_t *e1,
uECC_word_t *f1,
const uECC_word_t *c,
const uECC_word_t *r) {
wordcount_t i;
wordcount_t pow2i = 1;
uECC_word_t d0[uECC_WORDS];
uECC_word_t e0[uECC_WORDS] = {1}; /* e0 <-- 1 */
uECC_word_t f0[uECC_WORDS];
vli_set(d0, r); /* d0 <-- r */
vli_modSub_fast(f0, curve_p, c); /* f0 <-- p - c */
for (i = 0; i <= 6; i++) {
mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */
mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */
vli_set(d0, d1); /* d0 <-- d1 */
vli_set(e0, e1); /* e0 <-- e1 */
vli_set(f0, f1); /* f0 <-- f1 */
pow2i *= 2;
}
}
/* Compute a = sqrt(a) (mod curve_p). */
/* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
static void mod_sqrt(uECC_word_t *a) {
bitcount_t i;
uECC_word_t e1[uECC_WORDS];
uECC_word_t f1[uECC_WORDS];
uECC_word_t d0[uECC_WORDS];
uECC_word_t e0[uECC_WORDS];
uECC_word_t f0[uECC_WORDS];
uECC_word_t d1[uECC_WORDS];
// s = a; using constant instead of random value
mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */
mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
for (i = 1; i <= 95; i++) {
vli_set(d0, d1); /* d0 <-- d1 */
vli_set(e0, e1); /* e0 <-- e1 */
vli_set(f0, f1); /* f0 <-- f1 */
mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
if (vli_isZero(d1)) { /* if d1 == 0 */
break;
}
}
vli_modInv(f1, e0, curve_p); /* f1 <-- 1 / e0 */
vli_modMult_fast(a, d0, f1); /* a <-- d0 / e0 */
}
#else /* uECC_CURVE */
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt(uECC_word_t *a) {
bitcount_t i;
@@ -1667,6 +1946,7 @@ static void mod_sqrt(uECC_word_t *a) {
}
vli_set(a, l_result);
}
#endif /* uECC_CURVE */
#if uECC_WORD_SIZE == 1
+2
View File
@@ -37,6 +37,7 @@ uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */
#define uECC_secp192r1 2
#define uECC_secp256r1 3
#define uECC_secp256k1 4
#define uECC_secp224r1 5
#ifndef uECC_CURVE
#define uECC_CURVE uECC_secp160r1
#endif
@@ -55,6 +56,7 @@ faster by about 8% but increases the code size. */
#define uECC_size_2 24 /* secp192r1 */
#define uECC_size_3 32 /* secp256r1 */
#define uECC_size_4 32 /* secp256k1 */
#define uECC_size_5 28 /* secp224r1 */
#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)