Merge remote-tracking branch 'origin/upstream/master' into HEAD Bug: 86669 Change-Id: I987ae6564601ab7ae399d7a1c5f85ce436f3254c
diff --git a/README.md b/README.md index fd31d1c..111321b 100644 --- a/README.md +++ b/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/sec1-v2.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.
diff --git a/asm_avr.inc b/asm_avr.inc index 05f2aed..c14bf55 100644 --- a/asm_avr.inc +++ b/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,7 +886,7 @@ "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" (num_words), @@ -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/emk_project.py b/emk_project.py index 940fadc..957dd79 100644 --- a/emk_project.py +++ b/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/examples/ecc_test/ecc_test.ino b/examples/ecc_test/ecc_test.ino index c3c8900..64a0be5 100644 --- a/examples/ecc_test/ecc_test.ino +++ b/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/platform-specific.inc b/platform-specific.inc index b068a1c..c1b551d 100644 --- a/platform-specific.inc +++ b/platform-specific.inc
@@ -67,6 +67,7 @@ #define default_RNG_defined 1 #elif defined(__Fuchsia__) + #include <sys/types.h> #include <unistd.h> #include <zircon/syscalls.h> @@ -77,6 +78,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/test/ecdsa_test_vectors.c b/test/ecdsa_test_vectors.c new file mode 100644 index 0000000..1e902b2 --- /dev/null +++ b/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/test/public_key_test_vectors.c b/test/public_key_test_vectors.c new file mode 100644 index 0000000..a0afba8 --- /dev/null +++ b/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/uECC.c b/uECC.c index daa144a..a3d502c 100644 --- a/uECC.c +++ b/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] = 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/uECC.h b/uECC.h index 43a19d6..dcbdbfa 100644 --- a/uECC.h +++ b/uECC.h
@@ -38,12 +38,12 @@ #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 +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 @@ -166,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.