Merge pull request #464 from h2o/kazuho/update-uecc
update micro-ecc
diff --git a/deps/micro-ecc/README.md b/deps/micro-ecc/README.md
index 01926e3..111321b 100644
--- a/deps/micro-ecc/README.md
+++ b/deps/micro-ecc/README.md
@@ -19,7 +19,7 @@
Usage Notes
-----------
### Point Representation ###
-Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
+Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
Private keys are represented in the standard format.
@@ -27,7 +27,7 @@
I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
-For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
+For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
See uECC.h for documentation for each function.
diff --git a/deps/micro-ecc/asm_arm.inc b/deps/micro-ecc/asm_arm.inc
index 688fdc7..e3c8cb1 100644
--- a/deps/micro-ecc/asm_arm.inc
+++ b/deps/micro-ecc/asm_arm.inc
@@ -620,7 +620,7 @@
"str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
"pop {%[r0]} \n\t" /* pop result off the stack */
- ".syntax divided \n\t"
+ RESUME_SYNTAX
: [r3] "+l" (num_words), [r4] "=&l" (r4),
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
: [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
@@ -805,7 +805,7 @@
"str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
"pop {%[r0]} \n\t" /* pop result off the stack */
- ".syntax divided \n\t"
+ RESUME_SYNTAX
: [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
: [r0] "l" (result), [r1] "l" (left)
diff --git a/deps/micro-ecc/asm_avr.inc b/deps/micro-ecc/asm_avr.inc
index c988040..c14bf55 100644
--- a/deps/micro-ecc/asm_avr.inc
+++ b/deps/micro-ecc/asm_avr.inc
@@ -37,12 +37,12 @@
"sbc r31, __zero_reg__ \n\t"
IJMP
#endif
-
+
REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t")
"1: \n\t"
: "+x" (v)
: [num] "r" (num_words)
- :
+ :
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
"r30", "r31", "cc"
#endif
@@ -60,16 +60,16 @@
"sbc r31, __zero_reg__ \n\t"
IJMP
#endif
-
+
REPEAT(uECC_MAX_WORDS,
"ld r0, y+ \n\t"
"st x+, r0 \n\t")
"1: \n\t"
: "+x" (d), "+y" (src)
: [num] "r" ((uint8_t)(num_words * 2))
- : "r0",
+ : "r0"
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
- "r30", "r31", "cc"
+ , "r30", "r31", "cc"
#endif
);
}
@@ -84,7 +84,7 @@
"sub r30, %[jump] \n\t"
"sbc r31, __zero_reg__ \n\t"
#endif
-
+
"add r26, %[num] \n\t"
"adc r27, __zero_reg__ \n\t"
"ld r0, -x \n\t"
@@ -93,7 +93,7 @@
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
IJMP
#endif
-
+
REPEAT(DEC(uECC_MAX_WORDS),
"ld r0, -x \n\t"
"ror r0 \n\t"
@@ -137,15 +137,15 @@
"sub r30, %[num] \n\t"
"sbc r31, __zero_reg__ \n\t"
#endif
-
+
"clc \n\t"
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
IJMP
REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE)
#endif
-
+
REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST)
-
+
"mov %[clb], __zero_reg__ \n\t"
"adc %[clb], %[clb] \n\t" /* Store carry bit. */
@@ -184,15 +184,15 @@
"sub r30, %[num] \n\t"
"sbc r31, __zero_reg__ \n\t"
#endif
-
+
"clc \n\t"
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
IJMP
REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE)
#endif
-
+
REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST)
-
+
"mov %[clb], __zero_reg__ \n\t"
"adc %[clb], %[clb] \n\t" /* Store carry bit. */
@@ -216,7 +216,7 @@
wordcount_t num_words) {
/* num_words should already be in r18. */
register wordcount_t r18 __asm__("r18") = num_words;
-
+
__asm__ volatile (
"push r18 \n\t"
#if (uECC_MIN_WORDS == 20)
@@ -268,7 +268,7 @@
wordcount_t num_words) {
/* num_words should already be in r20. */
register wordcount_t r20 __asm__("r20") = num_words;
-
+
__asm__ volatile (
"push r20 \n\t"
#if (uECC_MIN_WORDS == 20)
@@ -329,7 +329,7 @@
"out __SP_H__, r31 \n\t"
"out __SREG__, r0 \n\t"
"out __SP_L__, r30 \n\t"
-
+
"adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes
(+ 1 since z initially points below the stack) */
"adiw r26, 40 \n\t" /* end of product */
@@ -384,10 +384,10 @@
"ld r18, z \n\t"
"adc r18, r1 \n\t"
"st z+, r18 \n\t"
-
+
"sbiw r30, 24 \n\t" /* move z back to point at tmp */
"sbiw r26, 40 \n\t" /* move x back to point at product */
-
+
/* add low bytes of tmp to product, storing in result */
"ld r18, z+ \n\t"
"ld r19, x+ \n\t"
@@ -403,13 +403,13 @@
z is 20 bytes into tmp */
"sbiw r28, 20 \n\t" /* move y back to point at result */
"adiw r30, 4 \n\t" /* move z to point to the end of tmp */
-
+
/* do omega_mult again with the 4 relevant bytes */
/* z points to the end of tmp, x points to the end of product */
"ld r18, -z \n\t" /* Load word. */
"lsr r18 \n\t" /* Shift. */
"st -x, r18 \n\t" /* Store the first result word. */
-
+
"ld r18, -z \n\t"
"ror r18 \n\t"
"st -x, r18 \n\t"
@@ -419,11 +419,11 @@
"ld r18, -z \n\t"
"ror r18 \n\t"
"st -x, r18 \n\t"
-
+
"eor r18, r18 \n\t" /* r18 = 0 */
"ror r18 \n\t" /* get last bit */
"st -x, r18 \n\t" /* store it */
-
+
"sbiw r26, 3 \n\t" /* move x back to point at beginning */
/* now we add a copy of the 4 bytes */
"ld r18, z+ \n\t"
@@ -432,29 +432,29 @@
"st x+, r18 \n\t"
"ld r18, z+ \n\t"
"st x+, r18 \n\t"
-
+
"ld r18, z+ \n\t"
"ld r19, x \n\t"
"add r18, r19 \n\t"
"st x+, r18 \n\t"
-
+
/* Propagate over the remaining bytes */
"ld r18, x \n\t"
"adc r18, r1 \n\t"
"st x+, r18 \n\t"
-
+
"ld r18, x \n\t"
"adc r18, r1 \n\t"
"st x+, r18 \n\t"
-
+
"ld r18, x \n\t"
"adc r18, r1 \n\t"
"st x+, r18 \n\t"
-
+
"ld r18, x \n\t"
"adc r18, r1 \n\t"
"st x+, r18 \n\t"
-
+
/* now z points to the end of tmp, x points to the end of product
(y still points at result) */
"sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */
@@ -468,23 +468,23 @@
"ld r19, y \n\t"
"adc r18, r19 \n\t"
"st y+, r18 \n\t")
-
+
/* Done adding, now propagate carry bit */
REPEAT(12,
"ld r18, y \n\t"
"adc r18, __zero_reg__ \n\t"
"st y+, r18 \n\t")
-
+
"adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
"sbiw r28, 20 \n\t" /* move y back to point at result */
-
+
"sbiw r30, 1 \n\t" /* fix stack pointer */
"in r0, __SREG__ \n\t"
"cli \n\t"
"out __SP_H__, r31 \n\t"
"out __SREG__, r0 \n\t"
"out __SP_L__, r30 \n\t"
-
+
: "+x" (product), [carry] "+r" (carry)
: "y" (result)
: "r0", "r18", "r19", "r30", "r31", "cc"
@@ -517,7 +517,7 @@
"out __SP_H__, r31 \n\t"
"out __SREG__, r0 \n\t"
"out __SP_L__, r30 \n\t"
-
+
"adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */
"adiw r26, 32 \n\t" /* product + uECC_WORDS */
"ldi r25, 0x03 \n\t"
@@ -526,12 +526,12 @@
"ld r19, x+ \n\t"
"ld r20, x+ \n\t"
"ld r21, x+ \n\t"
-
+
"mul r24, r18 \n\t"
"st z+, r0 \n\t"
"mov r22, r1 \n\t"
"ldi r23, 0 \n\t"
-
+
"mul r24, r19 \n\t"
"add r22, r0 \n\t"
"adc r23, r1 \n\t" /* can't overflow */
@@ -540,7 +540,7 @@
"adc r23, r1 \n\t" /* can't overflow */
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"mul r24, r20 \n\t"
"add r23, r0 \n\t"
"adc r22, r1 \n\t"
@@ -549,7 +549,7 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"mul r24, r21 \n\t"
"add r22, r0 \n\t"
"adc r23, r1 \n\t"
@@ -558,7 +558,7 @@
"adc r23, r1 \n\t"
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
/* now we start adding the 2^32 part as well */
"add r23, r18 \n\t" // 28
"adc r22, r22 \n\t"
@@ -571,7 +571,7 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r19 \n\t" // 27
"adc r23, r23 \n\t"
"ld r19, x+ \n\t"
@@ -583,7 +583,7 @@
"adc r23, r1 \n\t"
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
REPEAT(6, // 26 - 3
"add r23, r20 \n\t"
"adc r22, r22 \n\t"
@@ -596,7 +596,7 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r21 \n\t"
"adc r23, r23 \n\t"
"ld r21, x+ \n\t"
@@ -608,7 +608,7 @@
"adc r23, r1 \n\t"
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"add r23, r18 \n\t"
"adc r22, r22 \n\t"
"ld r18, x+ \n\t"
@@ -620,7 +620,7 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r19 \n\t"
"adc r23, r23 \n\t"
"ld r19, x+ \n\t"
@@ -644,7 +644,7 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r21 \n\t" // 1
"adc r23, r23 \n\t"
"ld r21, x+ \n\t"
@@ -656,7 +656,7 @@
"adc r23, r1 \n\t"
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
/* Now finish the carries etc */
"add r23, r18 \n\t"
"adc r22, r22 \n\t"
@@ -665,27 +665,27 @@
"adc r22, r1 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r19 \n\t"
"adc r23, r23 \n\t"
"st z+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"add r23, r20 \n\t"
"adc r22, r22 \n\t"
"st z+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r21 \n\t"
"adc r23, r23 \n\t"
"st z+, r22 \n\t"
"st z+, r23 \n\t"
"eor r1, r1 \n\t" /* make r1 be 0 again */
-
+
"sbiw r30, 37 \n\t" /* move z back to point at tmp */
"subi r26, 64 \n\t" /* move x back to point at product */
"sbc r27, __zero_reg__ \n\t"
-
+
/* add low bytes of tmp to product, storing in result */
"ld r18, z+ \n\t"
"ld r19, x+ \n\t"
@@ -696,7 +696,7 @@
"ld r19, x+ \n\t"
"adc r18, r19 \n\t"
"st y+, r18 \n\t")
-
+
"adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
/* at this point x is at the end of product, y is at the end of result,
z is 32 bytes into tmp */
@@ -710,12 +710,12 @@
"ld r19, z+ \n\t"
"ld r20, z+ \n\t"
"ld r21, z+ \n\t"
-
+
"mul r24, r18 \n\t"
"st x+, r0 \n\t"
"mov r22, r1 \n\t"
"ldi r23, 0 \n\t"
-
+
"mul r24, r19 \n\t"
"add r22, r0 \n\t"
"adc r23, r1 \n\t" /* can't overflow */
@@ -724,7 +724,7 @@
"adc r23, r1 \n\t" /* can't overflow */
"st x+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"mul r24, r20 \n\t"
"add r23, r0 \n\t"
"adc r22, r1 \n\t"
@@ -733,7 +733,7 @@
"adc r22, r1 \n\t"
"st x+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"mul r24, r21 \n\t"
"add r22, r0 \n\t"
"adc r23, r1 \n\t"
@@ -742,7 +742,7 @@
"adc r23, r1 \n\t"
"st x+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"add r23, r18 \n\t"
"adc r22, r22 \n\t"
"ld r18, z+ \n\t"
@@ -754,7 +754,7 @@
"adc r22, r1 \n\t"
"st x+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
/* Now finish the carries etc */
"add r22, r19 \n\t"
"adc r23, r23 \n\t"
@@ -763,23 +763,23 @@
"adc r23, r1 \n\t"
"st x+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"add r23, r20 \n\t"
"adc r22, r22 \n\t"
"st x+, r23 \n\t"
"ldi r23, 0 \n\t"
-
+
"add r22, r21 \n\t"
"adc r23, r23 \n\t"
"st x+, r22 \n\t"
"ldi r22, 0 \n\t"
-
+
"add r23, r18 \n\t"
"adc r22, r22 \n\t"
"st x+, r23 \n\t"
"st x+, r22 \n\t"
"eor r1, r1 \n\t" /* make r1 be 0 again */
-
+
/* now z points to the end of tmp, x points to the end of product
(y still points at result) */
"sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */
@@ -793,28 +793,28 @@
"ld r19, y \n\t"
"adc r18, r19 \n\t"
"st y+, r18 \n\t")
-
+
/* Done adding, now propagate carry bit */
REPEAT(22,
"ld r18, y \n\t"
"adc r18, __zero_reg__ \n\t"
"st y+, r18 \n\t")
-
+
"adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
"sbiw r28, 32 \n\t" /* move y back to point at result */
-
+
"sbiw r30, 1 \n\t" /* fix stack pointer */
"in r0, __SREG__ \n\t"
"cli \n\t"
"out __SP_H__, r31 \n\t"
"out __SREG__, r0 \n\t"
"out __SP_L__, r30 \n\t"
-
+
: "+x" (product), [carry] "+r" (carry)
: "y" (result)
: "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc"
);
-
+
if (carry > 0) {
--carry;
uECC_vli_sub(result, result, curve_secp256k1.p, 32);
@@ -845,7 +845,7 @@
__asm__ volatile (
"clc \n\t"
-
+
"1: \n\t"
"ld %[left], x+ \n\t" /* Load left byte. */
"ld %[right], y+ \n\t" /* Load right byte. */
@@ -853,12 +853,12 @@
"st z+, %[left] \n\t" /* Store the result. */
"dec %[i] \n\t"
"brne 1b \n\t"
-
+
"adc %[carry], %[carry] \n\t" /* Store carry bit. */
: "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words),
[carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
- :
+ :
: "cc"
);
return carry;
@@ -878,7 +878,7 @@
__asm__ volatile (
"clc \n\t"
-
+
"1: \n\t"
"ld %[left], x+ \n\t" /* Load left byte. */
"ld %[right], y+ \n\t" /* Load right byte. */
@@ -886,10 +886,10 @@
"st z+, %[left] \n\t" /* Store the result. */
"dec %[i] \n\t"
"brne 1b \n\t"
-
+
"adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */
- : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i),
+ : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words),
[borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
:
: "cc"
@@ -911,86 +911,86 @@
uint8_t r2 = 0;
uint8_t zero = 0;
uint8_t k, i;
-
+
__asm__ volatile (
"ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */
-
+
"1: \n\t"
"ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
-
+
"add r28, %[k] \n\t" /* pre-add right ptr */
"adc r29, %[zero] \n\t"
-
+
"2: \n\t"
"ld r0, x+ \n\t"
"ld r1, -y \n\t"
"mul r0, r1 \n\t"
-
+
"add %[r0], r0 \n\t"
"adc %[r1], r1 \n\t"
"adc %[r2], %[zero] \n\t"
-
+
"inc %[i] \n\t"
"cp %[i], %[k] \n\t"
"brlo 2b \n\t" /* loop if i < k */
-
+
"sub r26, %[k] \n\t" /* fix up left ptr */
"sbc r27, %[zero] \n\t"
-
+
"st z+, %[r0] \n\t" /* Store the result. */
"mov %[r0], %[r1] \n\t"
"mov %[r1], %[r2] \n\t"
"mov %[r2], %[zero] \n\t"
-
+
"inc %[k] \n\t"
"cp %[k], %[num] \n\t"
"brlo 1b \n\t" /* loop if k < num_words */
-
+
/* second half */
"mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */
"add r28, %[num] \n\t" /* move right ptr to point at the end of right */
"adc r29, %[zero] \n\t"
-
+
"1: \n\t"
"ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
-
+
"2: \n\t"
"ld r0, x+ \n\t"
"ld r1, -y \n\t"
"mul r0, r1 \n\t"
-
+
"add %[r0], r0 \n\t"
"adc %[r1], r1 \n\t"
"adc %[r2], %[zero] \n\t"
-
+
"inc %[i] \n\t"
"cp %[i], %[k] \n\t"
"brlo 2b \n\t" /* loop if i < k */
-
+
"add r28, %[k] \n\t" /* fix up right ptr */
"adc r29, %[zero] \n\t"
-
+
"st z+, %[r0] \n\t" /* Store the result. */
"mov %[r0], %[r1] \n\t"
"mov %[r1], %[r2] \n\t"
"mov %[r2], %[zero] \n\t"
-
+
"dec %[k] \n\t"
"sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time
we start 1 higher) */
"sbc r27, %[zero] \n\t"
-
+
"cp %[k], %[zero] \n\t"
"brne 1b \n\t" /* loop if k > 0 */
-
+
"st z+, %[r0] \n\t" /* Store last result byte. */
"eor r1, r1 \n\t" /* fix r1 to be 0 again */
-
+
: "+z" (result), "+x" (left), "+y" (right),
[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2),
[zero] "+r" (zero), [num] "+r" (num_words),
[k] "=&r" (k), [i] "=&r" (i)
- :
+ :
: "r0", "cc"
);
}
@@ -1007,18 +1007,18 @@
uint8_t r2 = 0;
uint8_t zero = 0;
uint8_t k;
-
+
__asm__ volatile (
"ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */
-
+
"1: \n\t"
-
+
"movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */
"movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */
"cp %[k], %[num] \n\t"
"brlo 2f \n\t"
"breq 2f \n\t"
-
+
/* when k > num_words, we start from (k - num_words) on the 'left' ptr */
"add r26, %[k] \n\t"
"adc r27, %[zero] \n\t"
@@ -1027,11 +1027,11 @@
"add r30, %[num] \n\t" /* move right ptr to point at the end */
"adc r31, %[zero] \n\t"
"rjmp 3f \n\t"
-
+
"2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */
"add r30, %[k] \n\t" /* pre-add 'right' ptr */
"adc r31, %[zero] \n\t"
-
+
"3: \n\t"
"ld r0, x+ \n\t"
"cp r26, r30 \n\t" /* if left == right here, then we are done after this mult
@@ -1039,7 +1039,7 @@
"breq 4f \n\t"
"ld r1, -z \n\t"
"mul r0, r1 \n\t"
-
+
/* add twice since it costs the same as doubling */
"add %[r0], r0 \n\t"
"adc %[r1], r1 \n\t"
@@ -1047,18 +1047,18 @@
"add %[r0], r0 \n\t"
"adc %[r1], r1 \n\t"
"adc %[r2], %[zero] \n\t"
-
+
"cpse r26, r30 \n\t" /* if left == right here, then we are done */
"rjmp 3b \n\t"
"rjmp 5f \n\t" /* skip code for non-doubled mult */
-
+
"4: \n\t"
"ld r1, -z \n\t"
"mul r0, r1 \n\t"
"add %[r0], r0 \n\t"
"adc %[r1], r1 \n\t"
"adc %[r2], %[zero] \n\t"
-
+
"5: \n\t"
"movw r30, %[result] \n\t" /* make z point to result */
"st z+, %[r0] \n\t" /* Store the result. */
@@ -1066,15 +1066,15 @@
"mov %[r0], %[r1] \n\t"
"mov %[r1], %[r2] \n\t"
"mov %[r2], %[zero] \n\t"
-
+
"inc %[k] \n\t"
"cp %[k], %[max] \n\t"
"brlo 1b \n\t" /* loop if k < num_words * 2 */
-
+
"movw r30, %[result] \n\t" /* make z point to result */
"st z+, %[r0] \n\t" /* Store last result byte. */
"eor r1, r1 \n\t" /* fix r1 to be 0 again */
-
+
: [result] "+r" (r),
[r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero),
[k] "=&a" (k)
diff --git a/deps/micro-ecc/emk_project.py b/deps/micro-ecc/emk_project.py
index 940fadc..957dd79 100644
--- a/deps/micro-ecc/emk_project.py
+++ b/deps/micro-ecc/emk_project.py
@@ -12,6 +12,11 @@
c_link_flags = []
cxx_link_flags = ["-fno-rtti", "-fno-exceptions"]
+if "root" in emk.options:
+ root = emk.options["root"]
+else:
+ root = "/"
+
def setup_build_dir():
build_arch = None
if "arch" in emk.options:
@@ -54,9 +59,9 @@
global c
global link
- c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-")
+ c.compiler = c.GccCompiler(root + "Projects/avr-tools/bin/avr-")
c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"]
- link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-")
+ link.linker = link.GccLinker(root + "Projects/avr-tools/bin/avr-")
link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"]
link.strip = True
@@ -66,30 +71,30 @@
global asm
global utils
- asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-")
- c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-")
- link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-")
+ asm.assembler = asm.GccAssembler(root + "cross/arm_cortex/bin/arm-none-eabi-")
+ c.compiler = c.GccCompiler(root + "cross/arm_cortex/bin/arm-none-eabi-")
+ link.linker = link.GccLinker(root + "cross/arm_cortex/bin/arm-none-eabi-")
c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"])
c.defines["LPC11XX"] = 1
-
+
link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"])
- link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"])
+ link.local_flags.extend(["-Tflash.lds", "-L" + root + "Projects/lpc11xx/core", root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"])
link.local_syslibs += ["gcc"]
- link.depdirs += ["/Projects/lpc11xx/stdlib"]
+ link.depdirs += [root + "Projects/lpc11xx/stdlib"]
def do_objcopy(produces, requires):
- utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0])
+ utils.call(root + "cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0])
def handle_exe(path):
- emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o")
+ emk.depend(path, root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o")
emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True)
emk.autobuild(path + ".bin")
link.exe_funcs.append(handle_exe)
link.strip = True
-
- emk.recurse("/Projects/lpc11xx/core")
+
+ emk.recurse(root + "Projects/lpc11xx/core")
def setup_linux_rpi():
global c
@@ -97,7 +102,7 @@
c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
-
+
c.flags.extend(["-fomit-frame-pointer"])
setup_build_dir()
diff --git a/deps/micro-ecc/test/ecc_test/ecc_test.ino b/deps/micro-ecc/examples/ecc_test/ecc_test.ino
similarity index 98%
rename from deps/micro-ecc/test/ecc_test/ecc_test.ino
rename to deps/micro-ecc/examples/ecc_test/ecc_test.ino
index c3c8900..64a0be5 100644
--- a/deps/micro-ecc/test/ecc_test/ecc_test.ino
+++ b/deps/micro-ecc/examples/ecc_test/ecc_test.ino
@@ -1,7 +1,5 @@
#include <uECC.h>
-extern "C" {
-
static int RNG(uint8_t *dest, unsigned size) {
// Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of
// random noise). This can take a long time to generate random data if the result of analogRead(0)
@@ -29,8 +27,6 @@
return 1;
}
-} // extern "C"
-
void setup() {
Serial.begin(115200);
Serial.print("Testing ecc\n");
@@ -82,4 +78,3 @@
Serial.print("Shared secrets are identical\n");
}
}
-
diff --git a/deps/micro-ecc/library.properties b/deps/micro-ecc/library.properties
new file mode 100644
index 0000000..390bdc8
--- /dev/null
+++ b/deps/micro-ecc/library.properties
@@ -0,0 +1,9 @@
+name=micro-ecc
+version=1.0.0
+author=Kenneth MacKay
+maintainer=Kenneth MacKay
+sentence=uECC
+paragraph=A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
+category=Other
+url=https://github.com/kmackay/micro-ecc
+architectures=*
diff --git a/deps/micro-ecc/platform-specific.inc b/deps/micro-ecc/platform-specific.inc
index 1bb595a..7e0373f 100644
--- a/deps/micro-ecc/platform-specific.inc
+++ b/deps/micro-ecc/platform-specific.inc
@@ -8,6 +8,10 @@
#if (defined(_WIN32) || defined(_WIN64))
/* Windows */
+// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function
+#pragma comment(lib, "crypt32.lib")
+#pragma comment(lib, "advapi32.lib")
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
@@ -62,6 +66,29 @@
}
#define default_RNG_defined 1
+#elif defined(RIOT_VERSION)
+
+#include <random.h>
+
+static int default_RNG(uint8_t *dest, unsigned size) {
+ random_bytes(dest, size);
+ return 1;
+}
+#define default_RNG_defined 1
+
+#elif defined(NRF52_SERIES)
+
+#include "app_error.h"
+#include "nrf_crypto_rng.h"
+
+static int default_RNG(uint8_t *dest, unsigned size)
+{
+ // make sure to call nrf_crypto_init and nrf_crypto_rng_init first
+ ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size);
+ return (ret_code == NRF_SUCCESS) ? 1 : 0;
+}
+#define default_RNG_defined 1
+
#endif /* platform */
#endif /* _UECC_PLATFORM_SPECIFIC_H_ */
diff --git a/deps/micro-ecc/test/ecdsa_test_vectors.c b/deps/micro-ecc/test/ecdsa_test_vectors.c
new file mode 100644
index 0000000..1e902b2
--- /dev/null
+++ b/deps/micro-ecc/test/ecdsa_test_vectors.c
@@ -0,0 +1,128 @@
+/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ const char* private_key;
+ const char* public_key;
+ const char* k;
+ const char* hash;
+ const char* r;
+ const char* s;
+} Test;
+
+Test secp256k1_tests[] = {
+ {
+ "ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f",
+ "779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcde94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f",
+ "49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a",
+ "4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a",
+ "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795",
+ "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e"
+ },
+};
+
+extern int uECC_sign_with_k(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uint8_t *k,
+ uint8_t *signature,
+ uECC_Curve curve);
+
+
+void vli_print(uint8_t *vli, unsigned int size) {
+ for(unsigned i=0; i<size; ++i) {
+ printf("%02X ", (unsigned)vli[i]);
+ }
+ printf("\n");
+}
+
+void strtobytes(const char* str, uint8_t* bytes, int count) {
+ for (int c = 0; c < count; ++c) {
+ if (sscanf(str, "%2hhx", &bytes[c]) != 1) {
+ printf("Failed to read string to bytes");
+ exit(1);
+ }
+ str += 2;
+ }
+}
+
+int run(Test* tests, int num_tests, uECC_Curve curve) {
+ uint8_t private[32] = {0};
+ uint8_t public[64] = {0};
+ uint8_t k[32] = {0};
+ uint8_t hash[32] = {0};
+ uint8_t r[32] = {0};
+ uint8_t s[32] = {0};
+
+ uint8_t signature[64] = {0};
+
+ int result;
+ int i;
+ int private_key_size;
+ int public_key_size;
+ int all_success = 1;
+
+ private_key_size = uECC_curve_private_key_size(curve);
+ public_key_size = uECC_curve_public_key_size(curve);
+
+ for (i = 0; i < num_tests; ++i) {
+ strtobytes(tests[i].private_key, private, private_key_size);
+ strtobytes(tests[i].public_key, public, public_key_size);
+ strtobytes(tests[i].k, k, private_key_size);
+ strtobytes(tests[i].hash, hash, private_key_size);
+ strtobytes(tests[i].r, r, private_key_size);
+ strtobytes(tests[i].s, s, private_key_size);
+
+ result = uECC_sign_with_k(private, hash, private_key_size, k, signature, curve);
+ if (!result) {
+ all_success = 0;
+ printf(" Sign failed for test %d\n", i);
+ }
+ if (result) {
+ if (memcmp(signature, r, private_key_size) != 0) {
+ all_success = 0;
+ printf(" Got incorrect r for test %d\n", i);
+ printf(" Expected: ");
+ vli_print(r, private_key_size);
+ printf(" Calculated: ");
+ vli_print(signature, private_key_size);
+ }
+ if (memcmp(signature + private_key_size, s, private_key_size) != 0) {
+ all_success = 0;
+ printf(" Got incorrect s for test %d\n", i);
+ printf(" Expected: ");
+ vli_print(s, private_key_size);
+ printf(" Calculated: ");
+ vli_print(signature + private_key_size, private_key_size);
+ }
+
+ result = uECC_verify(public, hash, private_key_size, signature, curve);
+ if (!result) {
+ printf(" Verify failed for test %d\n", i);
+ }
+ }
+ }
+
+ return all_success;
+}
+
+#define RUN_TESTS(curve) \
+ printf(#curve ":\n"); \
+ if (run(curve##_tests, sizeof(curve##_tests) / sizeof(curve##_tests[0]), uECC_##curve()) ) { \
+ printf(" All passed\n"); \
+ } else { \
+ printf(" Failed\n"); \
+ }
+
+int main() {
+#if uECC_SUPPORTS_secp256k1
+ RUN_TESTS(secp256k1)
+#endif
+
+ return 0;
+}
diff --git a/deps/micro-ecc/test/public_key_test_vectors.c b/deps/micro-ecc/test/public_key_test_vectors.c
new file mode 100644
index 0000000..a0afba8
--- /dev/null
+++ b/deps/micro-ecc/test/public_key_test_vectors.c
@@ -0,0 +1,338 @@
+/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+ const char* k;
+ const char* Q;
+ int success;
+} Test;
+
+Test secp160r1_tests[] = {
+ /* Note, I couldn't find any test vectors for secp160r1 online, so these are just
+ generated on my desktop using uECC. */
+ {
+ "000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "000000000000000000000000000000000000000001",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "000000000000000000000000000000000000000002",
+ "02F997F33C5ED04C55D3EDF8675D3E92E8F46686F083A323482993E9440E817E21CFB7737DF8797B",
+ 1
+ },
+ {
+ "000000000000000000000000000000000000000003",
+ "7B76FF541EF363F2DF13DE1650BD48DAA958BC59C915CA790D8C8877B55BE0079D12854FFE9F6F5A",
+ 1
+ },
+ { /* n - 4 */
+ "0100000000000000000001F4C8F927AED3CA752253",
+ "B4041D8683BE99F0AFE01C307B1AD4C100CF2A88C0CD35127BE0F73FF99F338B350B5A42864112F7",
+ 1
+ },
+ { /* n - 3 */
+ "0100000000000000000001F4C8F927AED3CA752254",
+ "7B76FF541EF363F2DF13DE1650BD48DAA958BC5936EA3586F27377884AA41FF862ED7AAF816090A5",
+ 1
+ },
+ { /* n - 2 */
+ "0100000000000000000001F4C8F927AED3CA752255",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ { /* n - 1 */
+ "0100000000000000000001F4C8F927AED3CA752256",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ { /* n */
+ "0100000000000000000001F4C8F927AED3CA752257",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+};
+
+
+Test secp192r1_tests[] = {
+ {
+ "000000000000000000000000000000000000000000000000",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "000000000000000000000000000000000000000000000001",
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
+ 0
+ },
+ {
+ "000000000000000000000000000000000000000000000002",
+ "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB",
+ 1
+ },
+ {
+ "000000000000000000000000000000000000000000000003",
+ "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD",
+ 1
+ },
+ { /* n - 4 */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282D",
+ "35433907297CC378B0015703374729D7A4FE46647084E4BA5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD",
+ 1
+ },
+ { /* n - 3 */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282E",
+ "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02",
+ 1
+ },
+ { /* n - 2 */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282F",
+ "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54",
+ 0
+ },
+ { /* n - 1 */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE",
+ 0
+ },
+ { /* n */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+};
+
+Test secp224r1_tests[] = {
+ {
+ "00000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "00000000000000000000000000000000000000000000000000000001",
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
+ 0
+ },
+ {
+ "00000000000000000000000000000000000000000000000000000002",
+ "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA61C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB",
+ 1
+ },
+ {
+ "00000000000000000000000000000000000000000000000000000003",
+ "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925",
+ 1
+ },
+ { /* n - 4 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A39",
+ "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38",
+ 1
+ },
+ { /* n - 3 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3A",
+ "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D045C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC",
+ 1
+ },
+ { /* n - 2 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3B",
+ "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746",
+ 0
+ },
+ { /* n - 1 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C",
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D2142C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD",
+ 0
+ },
+ { /* n */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+};
+
+Test secp256r1_tests[] = {
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000001",
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ 0
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000002",
+ "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC4766997807775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1",
+ 1
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000003",
+ "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032",
+ 1
+ },
+ { /* n - 4 */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D",
+ "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B0308521F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739",
+ 1
+ },
+ { /* n - 3 */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E",
+ "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD",
+ 1
+ },
+ { /* n - 2 */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F",
+ "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E",
+ 0
+ },
+ { /* n - 1 */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550",
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A",
+ 0
+ },
+ { /* n */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+};
+
+Test secp256k1_tests[] = {
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000001",
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ 0
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000002",
+ "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE51AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A",
+ 1
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000003",
+ "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672",
+ 1
+ },
+ { /* n - 4 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413D",
+ "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D",
+ 1
+ },
+ { /* n - 3 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413E",
+ "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD",
+ 1
+ },
+ { /* n - 2 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F",
+ "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705",
+ 0
+ },
+ { /* n - 1 */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140",
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777",
+ 0
+ },
+ { /* n */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ 0
+ },
+};
+
+
+void vli_print(uint8_t *vli, unsigned int size) {
+ for(unsigned i=0; i<size; ++i) {
+ printf("%02X ", (unsigned)vli[i]);
+ }
+ printf("\n");
+}
+
+void strtobytes(const char* str, uint8_t* bytes, int count) {
+ for (int c = 0; c < count; ++c) {
+ if (sscanf(str, "%2hhx", &bytes[c]) != 1) {
+ printf("Failed to read string to bytes");
+ exit(1);
+ }
+ str += 2;
+ }
+}
+
+int run(Test* tests, int num_tests, uECC_Curve curve) {
+ uint8_t private[32] = {0};
+ uint8_t public[64] = {0};
+ uint8_t expected[64] = {0};
+ int result;
+ int i;
+ int private_key_size;
+ int public_key_size;
+ int all_success = 1;
+
+ private_key_size = uECC_curve_private_key_size(curve);
+ public_key_size = uECC_curve_public_key_size(curve);
+
+ for (i = 0; i < num_tests; ++i) {
+ strtobytes(tests[i].k, private, private_key_size);
+ result = uECC_compute_public_key(private, public, curve);
+ if (result != tests[i].success) {
+ all_success = 0;
+ printf(" Got unexpected result from test %d: %d\n", i, result);
+ }
+ if (result) {
+ strtobytes(tests[i].Q, expected, public_key_size);
+ if (memcmp(public, expected, public_key_size) != 0) {
+ all_success = 0;
+ printf(" Got incorrect public key for test %d\n", i);
+ printf(" Expected: ");
+ vli_print(expected, public_key_size);
+ printf(" Calculated: ");
+ vli_print(public, public_key_size);
+ }
+ }
+ }
+
+ return all_success;
+}
+
+#define RUN_TESTS(curve) \
+ printf(#curve ":\n"); \
+ if (run(curve##_tests, sizeof(curve##_tests) / sizeof(curve##_tests[0]), uECC_##curve()) ) { \
+ printf(" All passed\n"); \
+ } else { \
+ printf(" Failed\n"); \
+ }
+
+int main() {
+#if uECC_SUPPORTS_secp160r1
+ RUN_TESTS(secp160r1)
+#endif
+#if uECC_SUPPORTS_secp192r1
+ RUN_TESTS(secp192r1)
+#endif
+#if uECC_SUPPORTS_secp224r1
+ RUN_TESTS(secp224r1)
+#endif
+#if uECC_SUPPORTS_secp256r1
+ RUN_TESTS(secp256r1)
+#endif
+#if uECC_SUPPORTS_secp256k1
+ RUN_TESTS(secp256k1)
+#endif
+
+ return 0;
+}
diff --git a/deps/micro-ecc/uECC.c b/deps/micro-ecc/uECC.c
index 461f713..a3224dd 100644
--- a/deps/micro-ecc/uECC.c
+++ b/deps/micro-ecc/uECC.c
@@ -13,73 +13,78 @@
#define uECC_VLI_API static
#endif
-#define CONCATX(a, ...) a ## __VA_ARGS__
-#define CONCAT(a, ...) CONCATX(a, __VA_ARGS__)
+#if (uECC_PLATFORM == uECC_avr) || \
+ (uECC_PLATFORM == uECC_arm) || \
+ (uECC_PLATFORM == uECC_arm_thumb) || \
+ (uECC_PLATFORM == uECC_arm_thumb2)
+ #define CONCATX(a, ...) a ## __VA_ARGS__
+ #define CONCAT(a, ...) CONCATX(a, __VA_ARGS__)
-#define STRX(a) #a
-#define STR(a) STRX(a)
+ #define STRX(a) #a
+ #define STR(a) STRX(a)
-#define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
-#define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
-#define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
-#define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
-#define EVAL4(...) __VA_ARGS__
+ #define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
+ #define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
+ #define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
+ #define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
+ #define EVAL4(...) __VA_ARGS__
-#define DEC_1 0
-#define DEC_2 1
-#define DEC_3 2
-#define DEC_4 3
-#define DEC_5 4
-#define DEC_6 5
-#define DEC_7 6
-#define DEC_8 7
-#define DEC_9 8
-#define DEC_10 9
-#define DEC_11 10
-#define DEC_12 11
-#define DEC_13 12
-#define DEC_14 13
-#define DEC_15 14
-#define DEC_16 15
-#define DEC_17 16
-#define DEC_18 17
-#define DEC_19 18
-#define DEC_20 19
-#define DEC_21 20
-#define DEC_22 21
-#define DEC_23 22
-#define DEC_24 23
-#define DEC_25 24
-#define DEC_26 25
-#define DEC_27 26
-#define DEC_28 27
-#define DEC_29 28
-#define DEC_30 29
-#define DEC_31 30
-#define DEC_32 31
+ #define DEC_1 0
+ #define DEC_2 1
+ #define DEC_3 2
+ #define DEC_4 3
+ #define DEC_5 4
+ #define DEC_6 5
+ #define DEC_7 6
+ #define DEC_8 7
+ #define DEC_9 8
+ #define DEC_10 9
+ #define DEC_11 10
+ #define DEC_12 11
+ #define DEC_13 12
+ #define DEC_14 13
+ #define DEC_15 14
+ #define DEC_16 15
+ #define DEC_17 16
+ #define DEC_18 17
+ #define DEC_19 18
+ #define DEC_20 19
+ #define DEC_21 20
+ #define DEC_22 21
+ #define DEC_23 22
+ #define DEC_24 23
+ #define DEC_25 24
+ #define DEC_26 25
+ #define DEC_27 26
+ #define DEC_28 27
+ #define DEC_29 28
+ #define DEC_30 29
+ #define DEC_31 30
+ #define DEC_32 31
-#define DEC(N) CONCAT(DEC_, N)
+ #define DEC(N) CONCAT(DEC_, N)
-#define SECOND_ARG(_, val, ...) val
-#define SOME_CHECK_0 ~, 0
-#define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,)
-#define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N))
+ #define SECOND_ARG(_, val, ...) val
+ #define SOME_CHECK_0 ~, 0
+ #define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,)
+ #define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N))
-#define EMPTY(...)
-#define DEFER(...) __VA_ARGS__ EMPTY()
+ #define EMPTY(...)
+ #define DEFER(...) __VA_ARGS__ EMPTY()
-#define REPEAT_NAME_0() REPEAT_0
-#define REPEAT_NAME_SOME() REPEAT_SOME
-#define REPEAT_0(...)
-#define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff
-#define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff))
+ #define REPEAT_NAME_0() REPEAT_0
+ #define REPEAT_NAME_SOME() REPEAT_SOME
+ #define REPEAT_0(...)
+ #define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff
+ #define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff))
-#define REPEATM_NAME_0() REPEATM_0
-#define REPEATM_NAME_SOME() REPEATM_SOME
-#define REPEATM_0(...)
-#define REPEATM_SOME(N, macro) macro(N) \
- DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro)
-#define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro))
+ #define REPEATM_NAME_0() REPEATM_0
+ #define REPEATM_NAME_SOME() REPEATM_SOME
+ #define REPEATM_0(...)
+ #define REPEATM_SOME(N, macro) macro(N) \
+ DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro)
+ #define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro))
+#endif
#include "platform-specific.inc"
@@ -912,19 +917,54 @@
return carry;
}
+/* Generates a random integer in the range 0 < random < top.
+ Both random and top have num_words words. */
+uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
+ const uECC_word_t *top,
+ wordcount_t num_words) {
+ uECC_word_t mask = (uECC_word_t)-1;
+ uECC_word_t tries;
+ bitcount_t num_bits = uECC_vli_numBits(top, num_words);
+
+ if (!g_rng_function) {
+ return 0;
+ }
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
+ return 0;
+ }
+ random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
+ if (!uECC_vli_isZero(random, num_words) &&
+ uECC_vli_cmp(top, random, num_words) == 1) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key,
uECC_Curve curve) {
uECC_word_t tmp1[uECC_MAX_WORDS];
uECC_word_t tmp2[uECC_MAX_WORDS];
uECC_word_t *p2[2] = {tmp1, tmp2};
+ uECC_word_t *initial_Z = 0;
uECC_word_t carry;
/* Regularize the bitcount for the private key so that attackers cannot use a side channel
attack to learn the number of leading zeros. */
carry = regularize_k(private_key, tmp1, tmp2, curve);
- EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
+ /* If an RNG function was specified, try to get a random initial Z value to improve
+ protection against side-channel attacks. */
+ if (g_rng_function) {
+ if (!uECC_generate_random_int(p2[carry], curve->p, curve->num_words)) {
+ return 0;
+ }
+ initial_Z = p2[carry];
+ }
+ EccPoint_mult(result, curve->G, p2[!carry], initial_Z, curve->num_n_bits + 1, curve);
if (EccPoint_isZero(result, curve)) {
return 0;
@@ -954,7 +994,7 @@
uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
int num_bytes,
const uECC_word_t *native) {
- wordcount_t i;
+ int i;
for (i = 0; i < num_bytes; ++i) {
unsigned b = num_bytes - 1 - i;
bytes[i] = (uint8_t)(native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)));
@@ -964,7 +1004,7 @@
uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
const uint8_t *bytes,
int num_bytes) {
- wordcount_t i;
+ int i;
uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
for (i = 0; i < num_bytes; ++i) {
unsigned b = num_bytes - 1 - i;
@@ -975,32 +1015,6 @@
#endif /* uECC_WORD_SIZE */
-/* Generates a random integer in the range 0 < random < top.
- Both random and top have num_words words. */
-uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
- const uECC_word_t *top,
- wordcount_t num_words) {
- uECC_word_t mask = (uECC_word_t)-1;
- uECC_word_t tries;
- bitcount_t num_bits = uECC_vli_numBits(top, num_words);
-
- if (!g_rng_function) {
- return 0;
- }
-
- for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
- if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
- return 0;
- }
- random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
- if (!uECC_vli_isZero(random, num_words) &&
- uECC_vli_cmp(top, random, num_words) == 1) {
- return 1;
- }
- }
- return 0;
-}
-
int uECC_make_key(uint8_t *public_key,
uint8_t *private_key,
uECC_Curve curve) {
@@ -1115,7 +1129,7 @@
}
#endif /* uECC_SUPPORT_COMPRESSED_POINT */
-int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
+uECC_VLI_API int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
uECC_word_t tmp1[uECC_MAX_WORDS];
uECC_word_t tmp2[uECC_MAX_WORDS];
wordcount_t num_words = curve->num_words;
@@ -1210,7 +1224,7 @@
bcopy((uint8_t *) native, bits, bits_size);
#else
uECC_vli_bytesToNative(native, bits, bits_size);
-#endif
+#endif
if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
return;
}
@@ -1229,7 +1243,7 @@
}
}
-static int uECC_sign_with_k(const uint8_t *private_key,
+static int uECC_sign_with_k_internal(const uint8_t *private_key,
const uint8_t *message_hash,
unsigned hash_size,
uECC_word_t *k,
@@ -1239,6 +1253,7 @@
uECC_word_t tmp[uECC_MAX_WORDS];
uECC_word_t s[uECC_MAX_WORDS];
uECC_word_t *k2[2] = {tmp, s};
+ uECC_word_t *initial_Z = 0;
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
uECC_word_t *p = (uECC_word_t *)signature;
#else
@@ -1255,7 +1270,15 @@
}
carry = regularize_k(k, tmp, s, curve);
- EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+ /* If an RNG function was specified, try to get a random initial Z value to improve
+ protection against side-channel attacks. */
+ if (g_rng_function) {
+ if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) {
+ return 0;
+ }
+ initial_Z = k2[carry];
+ }
+ EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve);
if (uECC_vli_isZero(p, num_words)) {
return 0;
}
@@ -1299,10 +1322,22 @@
bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes);
#else
uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
-#endif
+#endif
return 1;
}
+/* For testing - sign with an explicitly specified k value */
+int uECC_sign_with_k(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uint8_t *k,
+ uint8_t *signature,
+ uECC_Curve curve) {
+ uECC_word_t k2[uECC_MAX_WORDS];
+ bits2int(k2, k, BITS_TO_BYTES(curve->num_n_bits), curve);
+ return uECC_sign_with_k_internal(private_key, message_hash, hash_size, k2, signature, curve);
+}
+
int uECC_sign(const uint8_t *private_key,
const uint8_t *message_hash,
unsigned hash_size,
@@ -1316,7 +1351,7 @@
return 0;
}
- if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) {
+ if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, k, signature, curve)) {
return 1;
}
}
@@ -1432,7 +1467,7 @@
mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
}
- if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) {
+ if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, T, signature, curve)) {
return 1;
}
@@ -1472,7 +1507,7 @@
uECC_word_t *_public = (uECC_word_t *)public_key;
#else
uECC_word_t _public[uECC_MAX_WORDS * 2];
-#endif
+#endif
uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
diff --git a/deps/micro-ecc/uECC.h b/deps/micro-ecc/uECC.h
index 9911763..dcbdbfa 100644
--- a/deps/micro-ecc/uECC.h
+++ b/deps/micro-ecc/uECC.h
@@ -38,13 +38,16 @@
#endif
/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native
-little-endian format for *all* arrays passed in and out of the public API. This includes public
-and private keys, shared secrets, signatures and message hashes.
+little-endian format for *all* arrays passed in and out of the public API. This includes public
+and private keys, shared secrets, signatures and message hashes.
Using this switch reduces the amount of call stack memory used by uECC, since less intermediate
-translations are required.
+translations are required.
Note that this will *only* work on native little-endian processors and it will treat the uint8_t
-arrays passed into the public API as word arrays, therefore requiring the provided byte arrays
-to be word aligned on architectures that do not support unaligned accesses. */
+arrays passed into the public API as word arrays, therefore requiring the provided byte arrays
+to be word aligned on architectures that do not support unaligned accesses.
+IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible
+with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use
+the same endianness. */
#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN
#define uECC_VLI_NATIVE_LITTLE_ENDIAN 0
#endif
@@ -163,7 +166,9 @@
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
/* uECC_shared_secret() function.
-Compute a shared secret given your secret key and someone else's public key.
+Compute a shared secret given your secret key and someone else's public key. If the public key
+is not from a trusted source and has not been previously verified, you should verify it first
+using uECC_valid_public_key().
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
symmetric encryption or HMAC.