mirror of
https://github.com/kmackay/micro-ecc.git
synced 2026-08-23 10:20:03 +00:00
Add fast ARM asm; cleaned up code. Added optimization setting. (#50)
This commit is contained in:
-2455
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,845 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_ASM_ARM_FAST_H_
|
||||
#define _UECC_ASM_ARM_FAST_H_
|
||||
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
#define uECC_MIN_WORDS 8
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 7
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 6
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 5
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb)
|
||||
#define REG_RW "+l"
|
||||
#define REG_WRITE "=l"
|
||||
#else
|
||||
#define REG_RW "+r"
|
||||
#define REG_WRITE "=r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define RESUME_SYNTAX
|
||||
#else
|
||||
#define RESUME_SYNTAX ".syntax divided \n\t"
|
||||
#endif
|
||||
|
||||
static uECC_word_t vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = ((uECC_MAX_WORDS - num_words) * 4 + 5) * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = ((uECC_MAX_WORDS - num_words) * 4 + 5) * 4;
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
"mov %[left], pc \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adds %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"bx %[jump] \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS >= 6)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS >= 7)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS >= 8)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[carry] REG_WRITE (carry), [left] REG_WRITE (left_word), [right] REG_WRITE (right_word),
|
||||
[jump] REG_RW (jump)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
|
||||
static uECC_word_t vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = ((uECC_MAX_WORDS - num_words) * 4 + 5) * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = ((uECC_MAX_WORDS - num_words) * 4 + 5) * 4;
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
"mov %[left], pc \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"subs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"bx %[jump] \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS >= 6)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS >= 7)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS >= 8)
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
#endif
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[carry] REG_WRITE (carry), [left] REG_WRITE (left_word), [right] REG_WRITE (right_word),
|
||||
[jump] REG_RW (jump)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
|
||||
(for some reason...) */
|
||||
}
|
||||
#define asm_sub 1
|
||||
|
||||
#define FAST_MULT_ASM_5_TO_6 \
|
||||
"cmp r3, #5 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r4 = left high, r5 = right high */ \
|
||||
"ldr r4, [r1] \n\t" \
|
||||
"ldr r5, [r2] \n\t" \
|
||||
\
|
||||
"sub r0, #20 \n\t" \
|
||||
"sub r1, #20 \n\t" \
|
||||
"sub r2, #20 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r9, r10, r4, r8 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r14, r6 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r10, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"str r14, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
/* skip past already-loaded (r4, r5) */ \
|
||||
"ldr r7, [r1], #8 \n\t" \
|
||||
"ldr r8, [r2], #8 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"umull r11, r12, r4, r5 \n\t" \
|
||||
"adds r11, r14 \n\t" \
|
||||
"adc r12, r9 \n\t" \
|
||||
"stmia r0!, {r11, r12} \n\t"
|
||||
|
||||
#define FAST_MULT_ASM_6_TO_7 \
|
||||
"cmp r3, #6 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r4 = left high, r5 = right high */ \
|
||||
"ldr r4, [r1] \n\t" \
|
||||
"ldr r5, [r2] \n\t" \
|
||||
\
|
||||
"sub r0, #24 \n\t" \
|
||||
"sub r1, #24 \n\t" \
|
||||
"sub r2, #24 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r9, r10, r4, r8 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r14, r6 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r10, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"str r14, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r14, r6 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
/* skip past already-loaded (r4, r5) */ \
|
||||
"ldr r7, [r1], #8 \n\t" \
|
||||
"ldr r8, [r2], #8 \n\t" \
|
||||
"mov r10, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"str r14, [r0], #4 \n\t" \
|
||||
\
|
||||
"umull r11, r12, r4, r5 \n\t" \
|
||||
"adds r11, r9 \n\t" \
|
||||
"adc r12, r10 \n\t" \
|
||||
"stmia r0!, {r11, r12} \n\t"
|
||||
|
||||
#define FAST_MULT_ASM_7_TO_8 \
|
||||
"cmp r3, #7 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r4 = left high, r5 = right high */ \
|
||||
"ldr r4, [r1] \n\t" \
|
||||
"ldr r5, [r2] \n\t" \
|
||||
\
|
||||
"sub r0, #28 \n\t" \
|
||||
"sub r1, #28 \n\t" \
|
||||
"sub r2, #28 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r9, r10, r4, r8 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r14, r6 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r10, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"str r14, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r10, r6 \n\t" \
|
||||
"adcs r14, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r9, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r10, r11 \n\t" \
|
||||
"adcs r14, r12 \n\t" \
|
||||
"adc r9, #0 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r14, r6 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
"ldr r7, [r1], #4 \n\t" \
|
||||
"ldr r8, [r2], #4 \n\t" \
|
||||
"mov r10, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r14, r11 \n\t" \
|
||||
"adcs r9, r12 \n\t" \
|
||||
"adc r10, #0 \n\t" \
|
||||
"str r14, [r0], #4 \n\t" \
|
||||
\
|
||||
"ldr r6, [r0] \n\t" \
|
||||
"adds r9, r6 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
/* skip past already-loaded (r4, r5) */ \
|
||||
"ldr r7, [r1], #8 \n\t" \
|
||||
"ldr r8, [r2], #8 \n\t" \
|
||||
"mov r14, #0 \n\t" \
|
||||
"umull r11, r12, r4, r8 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"umull r11, r12, r5, r7 \n\t" \
|
||||
"adds r9, r11 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adc r14, #0 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
\
|
||||
"umull r11, r12, r4, r5 \n\t" \
|
||||
"adds r11, r10 \n\t" \
|
||||
"adc r12, r14 \n\t" \
|
||||
"stmia r0!, {r11, r12} \n\t"
|
||||
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
static void vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"push {r3} \n\t"
|
||||
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_MULT_ASM_5
|
||||
"pop {r3} \n\t"
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_MULT_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_MULT_ASM_6
|
||||
"pop {r3} \n\t"
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_MULT_ASM_7
|
||||
"pop {r3} \n\t"
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_MULT_ASM_8
|
||||
"pop {r3} \n\t"
|
||||
#endif
|
||||
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
|
||||
#define FAST_SQUARE_ASM_5_TO_6 \
|
||||
"cmp r2, #5 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r3 = high */ \
|
||||
"ldr r3, [r1] \n\t" \
|
||||
\
|
||||
"sub r0, #20 \n\t" \
|
||||
"sub r1, #20 \n\t" \
|
||||
\
|
||||
/* Do off-center multiplication */ \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r4, r5, r3, r14 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r7, r6, r3, r14 \n\t" \
|
||||
"adds r5, r7 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r8, r7, r3, r14 \n\t" \
|
||||
"adcs r6, r8 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r9, r8, r3, r14 \n\t" \
|
||||
"adcs r7, r9 \n\t" \
|
||||
/* Skip already-loaded r3 */ \
|
||||
"ldr r14, [r1], #8 \n\t" \
|
||||
"umull r10, r9, r3, r14 \n\t" \
|
||||
"adcs r8, r10 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
\
|
||||
/* Multiply by 2 */ \
|
||||
"mov r10, #0 \n\t" \
|
||||
"adds r4, r4 \n\t" \
|
||||
"adcs r5, r5 \n\t" \
|
||||
"adcs r6, r6 \n\t" \
|
||||
"adcs r7, r7 \n\t" \
|
||||
"adcs r8, r8 \n\t" \
|
||||
"adcs r9, r9 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
\
|
||||
/* Add into previous */ \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adds r4, r14 \n\t" \
|
||||
"str r4, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r5, r14 \n\t" \
|
||||
"str r5, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r6, r14 \n\t" \
|
||||
"str r6, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r7, r14 \n\t" \
|
||||
"str r7, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r8, r14 \n\t" \
|
||||
"str r8, [r0], #4 \n\t" \
|
||||
"adcs r9, #0 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
\
|
||||
/* Perform center multiplication */ \
|
||||
"umull r4, r5, r3, r3 \n\t" \
|
||||
"adds r4, r9 \n\t" \
|
||||
"adc r5, r10 \n\t" \
|
||||
"stmia r0!, {r4, r5} \n\t"
|
||||
|
||||
#define FAST_SQUARE_ASM_6_TO_7 \
|
||||
"cmp r2, #6 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r3 = high */ \
|
||||
"ldr r3, [r1] \n\t" \
|
||||
\
|
||||
"sub r0, #24 \n\t" \
|
||||
"sub r1, #24 \n\t" \
|
||||
\
|
||||
/* Do off-center multiplication */ \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r4, r5, r3, r14 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r7, r6, r3, r14 \n\t" \
|
||||
"adds r5, r7 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r8, r7, r3, r14 \n\t" \
|
||||
"adcs r6, r8 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r9, r8, r3, r14 \n\t" \
|
||||
"adcs r7, r9 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r10, r9, r3, r14 \n\t" \
|
||||
"adcs r8, r10 \n\t" \
|
||||
/* Skip already-loaded r3 */ \
|
||||
"ldr r14, [r1], #8 \n\t" \
|
||||
"umull r11, r10, r3, r14 \n\t" \
|
||||
"adcs r9, r11 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
\
|
||||
/* Multiply by 2 */ \
|
||||
"mov r11, #0 \n\t" \
|
||||
"adds r4, r4 \n\t" \
|
||||
"adcs r5, r5 \n\t" \
|
||||
"adcs r6, r6 \n\t" \
|
||||
"adcs r7, r7 \n\t" \
|
||||
"adcs r8, r8 \n\t" \
|
||||
"adcs r9, r9 \n\t" \
|
||||
"adcs r10, r10 \n\t" \
|
||||
"adcs r11, #0 \n\t" \
|
||||
\
|
||||
/* Add into previous */ \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adds r4, r14 \n\t" \
|
||||
"str r4, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r5, r14 \n\t" \
|
||||
"str r5, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r6, r14 \n\t" \
|
||||
"str r6, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r7, r14 \n\t" \
|
||||
"str r7, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r8, r14 \n\t" \
|
||||
"str r8, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r9, r14 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
"adcs r10, #0 \n\t" \
|
||||
"adcs r11, #0 \n\t" \
|
||||
\
|
||||
/* Perform center multiplication */ \
|
||||
"umull r4, r5, r3, r3 \n\t" \
|
||||
"adds r4, r10 \n\t" \
|
||||
"adc r5, r11 \n\t" \
|
||||
"stmia r0!, {r4, r5} \n\t"
|
||||
|
||||
#define FAST_SQUARE_ASM_7_TO_8 \
|
||||
"cmp r2, #7 \n\t" \
|
||||
"beq 1f \n\t" \
|
||||
\
|
||||
/* r3 = high */ \
|
||||
"ldr r3, [r1] \n\t" \
|
||||
\
|
||||
"sub r0, #28 \n\t" \
|
||||
"sub r1, #28 \n\t" \
|
||||
\
|
||||
/* Do off-center multiplication */ \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r4, r5, r3, r14 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r7, r6, r3, r14 \n\t" \
|
||||
"adds r5, r7 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r8, r7, r3, r14 \n\t" \
|
||||
"adcs r6, r8 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r9, r8, r3, r14 \n\t" \
|
||||
"adcs r7, r9 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r10, r9, r3, r14 \n\t" \
|
||||
"adcs r8, r10 \n\t" \
|
||||
"ldr r14, [r1], #4 \n\t" \
|
||||
"umull r11, r10, r3, r14 \n\t" \
|
||||
"adcs r9, r11 \n\t" \
|
||||
/* Skip already-loaded r3 */ \
|
||||
"ldr r14, [r1], #8 \n\t" \
|
||||
"umull r12, r11, r3, r14 \n\t" \
|
||||
"adcs r10, r12 \n\t" \
|
||||
"adcs r11, #0 \n\t" \
|
||||
\
|
||||
/* Multiply by 2 */ \
|
||||
"mov r12, #0 \n\t" \
|
||||
"adds r4, r4 \n\t" \
|
||||
"adcs r5, r5 \n\t" \
|
||||
"adcs r6, r6 \n\t" \
|
||||
"adcs r7, r7 \n\t" \
|
||||
"adcs r8, r8 \n\t" \
|
||||
"adcs r9, r9 \n\t" \
|
||||
"adcs r10, r10 \n\t" \
|
||||
"adcs r11, r11 \n\t" \
|
||||
"adcs r12, #0 \n\t" \
|
||||
\
|
||||
/* Add into previous */ \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adds r4, r14 \n\t" \
|
||||
"str r4, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r5, r14 \n\t" \
|
||||
"str r5, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r6, r14 \n\t" \
|
||||
"str r6, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r7, r14 \n\t" \
|
||||
"str r7, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r8, r14 \n\t" \
|
||||
"str r8, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r9, r14 \n\t" \
|
||||
"str r9, [r0], #4 \n\t" \
|
||||
"ldr r14, [r0] \n\t" \
|
||||
"adcs r10, r14 \n\t" \
|
||||
"str r10, [r0], #4 \n\t" \
|
||||
"adcs r11, #0 \n\t" \
|
||||
"adcs r12, #0 \n\t" \
|
||||
\
|
||||
/* Perform center multiplication */ \
|
||||
"umull r4, r5, r3, r3 \n\t" \
|
||||
"adds r4, r11 \n\t" \
|
||||
"adc r5, r12 \n\t" \
|
||||
"stmia r0!, {r4, r5} \n\t"
|
||||
|
||||
static void vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"push {r1, r2} \n\t"
|
||||
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_SQUARE_ASM_5
|
||||
"pop {r1, r2} \n\t"
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
"add r1, #20 \n\t"
|
||||
FAST_SQUARE_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_SQUARE_ASM_6
|
||||
"pop {r1, r2} \n\t"
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
"add r1, #24 \n\t"
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_SQUARE_ASM_7
|
||||
"pop {r1, r2} \n\t"
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
"add r1, #28 \n\t"
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_SQUARE_ASM_8
|
||||
"pop {r1, r2} \n\t"
|
||||
#endif
|
||||
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* uECC_PLATFORM != uECC_arm_thumb */
|
||||
|
||||
#endif /* _UECC_ASM_ARM_FAST_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
+19
-4
@@ -1,3 +1,8 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_ASM_ARM_SMALL_H_
|
||||
#define _UECC_ASM_ARM_SMALL_H_
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb)
|
||||
#define REG_RW "+l"
|
||||
#define REG_WRITE "=l"
|
||||
@@ -12,6 +17,7 @@
|
||||
#define RESUME_SYNTAX ".syntax divided \n\t"
|
||||
#endif
|
||||
|
||||
#if !asm_add
|
||||
static uECC_word_t vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
@@ -41,11 +47,13 @@ static uECC_word_t vli_add(uECC_word_t *result,
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
#endif
|
||||
|
||||
static uint32_t vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if !asm_sub
|
||||
static uECC_word_t vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
@@ -71,7 +79,9 @@ static uint32_t vli_sub(uECC_word_t *result,
|
||||
return !carry;
|
||||
}
|
||||
#define asm_sub 1
|
||||
#endif
|
||||
|
||||
#if !asm_mult
|
||||
static void vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
@@ -229,8 +239,10 @@ static void vli_mult(uECC_word_t *result,
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
#endif
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
#if !asm_square
|
||||
static void vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
@@ -404,4 +416,7 @@ static void vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* _UECC_ASM_ARM_SMALL_H_ */
|
||||
|
||||
+450
-388
@@ -1,3 +1,8 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_CURVE_SPECIFIC_H_
|
||||
#define _UECC_CURVE_SPECIFIC_H_
|
||||
|
||||
#define num_bytes_secp160r1 20
|
||||
#define num_bytes_secp192r1 24
|
||||
#define num_bytes_secp224r1 28
|
||||
@@ -46,26 +51,85 @@
|
||||
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
static void double_jacobian_secp256k1(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve);
|
||||
static void double_jacobian_default(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve);
|
||||
uECC_Curve curve) {
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[uECC_MAX_WORDS];
|
||||
uECC_word_t t5[uECC_MAX_WORDS];
|
||||
|
||||
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve);
|
||||
static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve);
|
||||
if (vli_isZero(Z1, curve->num_words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
|
||||
vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
|
||||
vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
|
||||
vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
|
||||
vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
|
||||
|
||||
vli_modAdd(X1, X1, Z1, curve->p, curve->num_words); /* t1 = x1 + z1^2 */
|
||||
vli_modAdd(Z1, Z1, Z1, curve->p, curve->num_words); /* t3 = 2*z1^2 */
|
||||
vli_modSub(Z1, X1, Z1, curve->p, curve->num_words); /* t3 = x1 - z1^2 */
|
||||
vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
|
||||
|
||||
vli_modAdd(Z1, X1, X1, curve->p, curve->num_words); /* t3 = 2*(x1^2 - z1^4) */
|
||||
vli_modAdd(X1, X1, Z1, curve->p, curve->num_words); /* t1 = 3*(x1^2 - z1^4) */
|
||||
if (vli_testBit(X1, 0)) {
|
||||
uECC_word_t l_carry = vli_add(X1, X1, curve->p, curve->num_words);
|
||||
vli_rshift1(X1, curve->num_words);
|
||||
X1[curve->num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
vli_rshift1(X1, curve->num_words);
|
||||
}
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
|
||||
vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
|
||||
vli_modSub(Z1, Z1, t5, curve->p, curve->num_words); /* t3 = B^2 - A */
|
||||
vli_modSub(Z1, Z1, t5, curve->p, curve->num_words); /* t3 = B^2 - 2A = x3 */
|
||||
vli_modSub(t5, t5, Z1, curve->p, curve->num_words); /* t5 = A - x3 */
|
||||
vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
|
||||
vli_modSub(t4, X1, t4, curve->p, curve->num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
|
||||
|
||||
vli_set(X1, Z1, curve->num_words);
|
||||
vli_set(Z1, Y1, curve->num_words);
|
||||
vli_set(Y1, t4, curve->num_words);
|
||||
}
|
||||
|
||||
/* Compute a = sqrt(a) (mod curve_p). */
|
||||
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
|
||||
bitcount_t i;
|
||||
uECC_word_t p1[uECC_MAX_WORDS] = {1};
|
||||
uECC_word_t l_result[uECC_MAX_WORDS] = {1};
|
||||
|
||||
/* When curve->p == 3 (mod 4), we can compute
|
||||
sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
|
||||
vli_add(p1, curve->p, p1, curve->num_words); /* p1 = curve_p + 1 */
|
||||
for (i = vli_numBits(p1, curve->num_words) - 1; i > 1; --i) {
|
||||
vli_modSquare_fast(l_result, l_result, curve);
|
||||
if (vli_testBit(p1, i)) {
|
||||
vli_modMult_fast(l_result, l_result, a, curve);
|
||||
}
|
||||
}
|
||||
vli_set(a, l_result, curve->num_words);
|
||||
}
|
||||
|
||||
/* Computes result = x^3 + ax + b. result must not overlap x. */
|
||||
static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
|
||||
uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */
|
||||
|
||||
vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
vli_modSub(result, result, _3, curve->p, curve->num_words); /* r = x^2 - 3 */
|
||||
vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
|
||||
vli_modAdd(result, result, curve->b, curve->p, curve->num_words); /* r = x^3 - 3x + b */
|
||||
}
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product);
|
||||
static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product);
|
||||
static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product);
|
||||
static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product);
|
||||
static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
|
||||
static const struct uECC_Curve_t curve_secp160r1 = {
|
||||
num_words_secp160r1,
|
||||
@@ -90,9 +154,126 @@ static const struct uECC_Curve_t curve_secp160r1 = {
|
||||
&double_jacobian_default,
|
||||
&mod_sqrt_default,
|
||||
&x_side_default,
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
&vli_mmod_fast_secp160r1
|
||||
#endif
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; }
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
/* Computes result = product % curve_p
|
||||
see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
|
||||
|
||||
Note that this only works if log2(omega) < log2(p) / 2 */
|
||||
static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right);
|
||||
#if uECC_WORD_SIZE == 8
|
||||
static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
|
||||
uECC_word_t tmp[2 * num_words_secp160r1];
|
||||
uECC_word_t copy;
|
||||
|
||||
vli_clear(tmp, num_words_secp160r1);
|
||||
vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
|
||||
|
||||
omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
|
||||
|
||||
product[num_words_secp160r1 - 1] &= 0xffffffff;
|
||||
copy = tmp[num_words_secp160r1 - 1];
|
||||
tmp[num_words_secp160r1 - 1] &= 0xffffffff;
|
||||
vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
|
||||
vli_clear(product, num_words_secp160r1);
|
||||
tmp[num_words_secp160r1 - 1] = copy;
|
||||
omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
|
||||
vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
|
||||
|
||||
while (vli_cmp(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
}
|
||||
|
||||
static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
|
||||
uint32_t carry;
|
||||
unsigned i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
carry = 0;
|
||||
for (i = 0; i < num_words_secp160r1; ++i) {
|
||||
uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
|
||||
result[i] = (tmp << 31) + tmp + carry;
|
||||
carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
|
||||
}
|
||||
result[i] = carry;
|
||||
}
|
||||
#else
|
||||
static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
|
||||
uECC_word_t tmp[2 * num_words_secp160r1];
|
||||
uECC_word_t carry;
|
||||
|
||||
vli_clear(tmp, num_words_secp160r1);
|
||||
vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
|
||||
|
||||
omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */
|
||||
|
||||
carry = vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
|
||||
vli_clear(product, num_words_secp160r1);
|
||||
omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
|
||||
carry += vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
|
||||
|
||||
while (carry > 0) {
|
||||
--carry;
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
if (vli_cmp(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if uECC_WORD_SIZE == 1
|
||||
static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
|
||||
uint8_t carry;
|
||||
uint8_t i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
|
||||
vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
|
||||
result[3] = right[0] << 7; /* get last bit from shift */
|
||||
|
||||
carry = vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
|
||||
for (i = num_words_secp160r1; carry; ++i) {
|
||||
uint16_t sum = (uint16_t)result[i] + carry;
|
||||
result[i] = (uint8_t)sum;
|
||||
carry = sum >> 8;
|
||||
}
|
||||
}
|
||||
#elif uECC_WORD_SIZE == 4
|
||||
static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
|
||||
uint32_t carry;
|
||||
unsigned i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
|
||||
vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
|
||||
result[0] = right[0] << 31; /* get last bit from shift */
|
||||
|
||||
carry = vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
|
||||
for (i = num_words_secp160r1; carry; ++i) {
|
||||
uint64_t sum = (uint64_t)result[i] + carry;
|
||||
result[i] = (uint32_t)sum;
|
||||
carry = sum >> 32;
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#endif /* uECC_SUPPORTS_secp160r1 */
|
||||
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
|
||||
static const struct uECC_Curve_t curve_secp192r1 = {
|
||||
num_words_secp192r1,
|
||||
num_words_secp192r1,
|
||||
@@ -116,9 +297,109 @@ static const struct uECC_Curve_t curve_secp192r1 = {
|
||||
&double_jacobian_default,
|
||||
&mod_sqrt_default,
|
||||
&x_side_default,
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
&vli_mmod_fast_secp192r1
|
||||
#endif
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; }
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
/* Computes result = product % curve_p.
|
||||
See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
|
||||
#if uECC_WORD_SIZE == 1
|
||||
static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
|
||||
uint8_t tmp[num_words_secp192r1];
|
||||
uint8_t carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[24], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
|
||||
tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27];
|
||||
tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
|
||||
tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
|
||||
tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[8] = product[40];
|
||||
tmp[1] = tmp[9] = product[41];
|
||||
tmp[2] = tmp[10] = product[42];
|
||||
tmp[3] = tmp[11] = product[43];
|
||||
tmp[4] = tmp[12] = product[44];
|
||||
tmp[5] = tmp[13] = product[45];
|
||||
tmp[6] = tmp[14] = product[46];
|
||||
tmp[7] = tmp[15] = product[47];
|
||||
tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#elif uECC_WORD_SIZE == 4
|
||||
static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
|
||||
uint32_t tmp[num_words_secp192r1];
|
||||
int carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[6], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = 0;
|
||||
tmp[2] = product[6];
|
||||
tmp[3] = product[7];
|
||||
tmp[4] = product[8];
|
||||
tmp[5] = product[9];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[2] = product[10];
|
||||
tmp[1] = tmp[3] = product[11];
|
||||
tmp[4] = tmp[5] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
|
||||
uint64_t tmp[num_words_secp192r1];
|
||||
int carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[3], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = 0;
|
||||
tmp[1] = product[3];
|
||||
tmp[2] = product[4];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = product[5];
|
||||
tmp[2] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#endif /* uECC_SUPPORTS_secp192r1 */
|
||||
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
|
||||
static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve);
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
|
||||
static const struct uECC_Curve_t curve_secp224r1 = {
|
||||
num_words_secp224r1,
|
||||
num_words_secp224r1,
|
||||
@@ -147,179 +428,13 @@ static const struct uECC_Curve_t curve_secp224r1 = {
|
||||
&double_jacobian_default,
|
||||
&mod_sqrt_secp224r1,
|
||||
&x_side_default,
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
&vli_mmod_fast_secp224r1
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct uECC_Curve_t curve_secp256r1 = {
|
||||
num_words_secp256r1,
|
||||
num_words_secp256r1,
|
||||
num_bytes_secp256r1,
|
||||
{ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
|
||||
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
|
||||
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
|
||||
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
|
||||
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
|
||||
|
||||
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
|
||||
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
|
||||
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
|
||||
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) },
|
||||
{ BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
|
||||
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
|
||||
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
|
||||
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) },
|
||||
&double_jacobian_default,
|
||||
&mod_sqrt_default,
|
||||
&x_side_default,
|
||||
&vli_mmod_fast_secp256r1
|
||||
};
|
||||
|
||||
static const struct uECC_Curve_t curve_secp256k1 = {
|
||||
num_words_secp256k1,
|
||||
num_words_secp256k1,
|
||||
num_bytes_secp256k1,
|
||||
{ BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
|
||||
BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
|
||||
BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
|
||||
BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
|
||||
BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
|
||||
BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
|
||||
|
||||
BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
|
||||
BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
|
||||
BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
|
||||
BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) },
|
||||
{ BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) },
|
||||
&double_jacobian_secp256k1,
|
||||
&mod_sqrt_default,
|
||||
&x_side_secp256k1,
|
||||
&vli_mmod_fast_secp256k1
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; }
|
||||
uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; }
|
||||
uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; }
|
||||
uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; }
|
||||
uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
|
||||
|
||||
/* Double in place */
|
||||
static void double_jacobian_secp256k1(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve) {
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[num_words_secp256k1];
|
||||
uECC_word_t t5[num_words_secp256k1];
|
||||
|
||||
if (vli_isZero(Z1, num_words_secp256k1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
|
||||
vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
|
||||
vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
|
||||
vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
|
||||
vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
|
||||
|
||||
vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
|
||||
vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
|
||||
if (vli_testBit(Y1, 0)) {
|
||||
uECC_word_t carry = vli_add(Y1, Y1, curve->p, num_words_secp256k1);
|
||||
vli_rshift1(Y1, num_words_secp256k1);
|
||||
Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
vli_rshift1(Y1, num_words_secp256k1);
|
||||
}
|
||||
/* t2 = 3/2*(x1^2) = B */
|
||||
|
||||
vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
|
||||
vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
|
||||
vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
|
||||
|
||||
vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
|
||||
vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
|
||||
vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
|
||||
}
|
||||
|
||||
static void double_jacobian_default(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve) {
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[uECC_MAX_WORDS];
|
||||
uECC_word_t t5[uECC_MAX_WORDS];
|
||||
|
||||
if (vli_isZero(Z1, curve->num_words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
|
||||
vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
|
||||
vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
|
||||
vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
|
||||
vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
|
||||
|
||||
vli_modAdd(X1, X1, Z1, curve->p, curve->num_words); /* t1 = x1 + z1^2 */
|
||||
vli_modAdd(Z1, Z1, Z1, curve->p, curve->num_words); /* t3 = 2*z1^2 */
|
||||
vli_modSub(Z1, X1, Z1, curve->p, curve->num_words); /* t3 = x1 - z1^2 */
|
||||
vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
|
||||
|
||||
vli_modAdd(Z1, X1, X1, curve->p, curve->num_words); /* t3 = 2*(x1^2 - z1^4) */
|
||||
vli_modAdd(X1, X1, Z1, curve->p, curve->num_words); /* t1 = 3*(x1^2 - z1^4) */
|
||||
if (vli_testBit(X1, 0)) {
|
||||
uECC_word_t l_carry = vli_add(X1, X1, curve->p, curve->num_words);
|
||||
vli_rshift1(X1, curve->num_words);
|
||||
X1[curve->num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
vli_rshift1(X1, curve->num_words);
|
||||
}
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
|
||||
vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
|
||||
vli_modSub(Z1, Z1, t5, curve->p, curve->num_words); /* t3 = B^2 - A */
|
||||
vli_modSub(Z1, Z1, t5, curve->p, curve->num_words); /* t3 = B^2 - 2A = x3 */
|
||||
vli_modSub(t5, t5, Z1, curve->p, curve->num_words); /* t5 = A - x3 */
|
||||
vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
|
||||
vli_modSub(t4, X1, t4, curve->p, curve->num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
|
||||
|
||||
vli_set(X1, Z1, curve->num_words);
|
||||
vli_set(Z1, Y1, curve->num_words);
|
||||
vli_set(Y1, t4, curve->num_words);
|
||||
}
|
||||
|
||||
/* Compute a = sqrt(a) (mod curve_p). */
|
||||
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
|
||||
bitcount_t i;
|
||||
uECC_word_t p1[uECC_MAX_WORDS] = {1};
|
||||
uECC_word_t l_result[uECC_MAX_WORDS] = {1};
|
||||
|
||||
/* When curve->p == 3 (mod 4), we can compute
|
||||
sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
|
||||
vli_add(p1, curve->p, p1, curve->num_words); /* p1 = curve_p + 1 */
|
||||
for (i = vli_numBits(p1, curve->num_words) - 1; i > 1; --i) {
|
||||
vli_modSquare_fast(l_result, l_result, curve);
|
||||
if (vli_testBit(p1, i)) {
|
||||
vli_modMult_fast(l_result, l_result, a, curve);
|
||||
}
|
||||
}
|
||||
vli_set(a, l_result, curve->num_words);
|
||||
}
|
||||
|
||||
/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
|
||||
static void mod_sqrt_secp224r1_rs(uECC_word_t *d1,
|
||||
@@ -437,213 +552,11 @@ static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) {
|
||||
vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */
|
||||
}
|
||||
|
||||
/* Computes result = x^3 + ax + b. result must not overlap x. */
|
||||
static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
|
||||
uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */
|
||||
|
||||
vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
vli_modSub(result, result, _3, curve->p, curve->num_words); /* r = x^2 - 3 */
|
||||
vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
|
||||
vli_modAdd(result, result, curve->b, curve->p, curve->num_words); /* r = x^3 - 3x + b */
|
||||
}
|
||||
|
||||
/* Computes result = x^3 + b. result must not overlap x. */
|
||||
static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
|
||||
vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
vli_modMult_fast(result, result, x, curve); /* r = x^3 */
|
||||
vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
|
||||
}
|
||||
|
||||
/* Computes result = product % curve_p
|
||||
see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
|
||||
|
||||
Note that this only works if log2(omega) < log2(p) / 2 */
|
||||
static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right);
|
||||
#if uECC_WORD_SIZE == 8
|
||||
static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
|
||||
uECC_word_t tmp[2 * num_words_secp160r1];
|
||||
uECC_word_t copy;
|
||||
|
||||
vli_clear(tmp, 2 * num_words_secp160r1);
|
||||
|
||||
omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
|
||||
|
||||
product[num_words_secp160r1 - 1] &= 0xffffffff;
|
||||
copy = tmp[num_words_secp160r1 - 1];
|
||||
tmp[num_words_secp160r1 - 1] &= 0xffffffff;
|
||||
vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
|
||||
vli_clear(product, num_words_secp160r1);
|
||||
tmp[num_words_secp160r1 - 1] = copy;
|
||||
omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
|
||||
vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
|
||||
|
||||
while (vli_cmp(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
}
|
||||
|
||||
static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
|
||||
uint32_t carry;
|
||||
unsigned i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
carry = 0;
|
||||
for (i = 0; i < num_words_secp160r1; ++i) {
|
||||
uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
|
||||
result[i] = (tmp << 31) + tmp + carry;
|
||||
carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
|
||||
}
|
||||
result[i] = carry;
|
||||
}
|
||||
#else
|
||||
static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
|
||||
uECC_word_t tmp[2 * num_words_secp160r1];
|
||||
uECC_word_t carry;
|
||||
|
||||
vli_clear(tmp, 2 * num_words_secp160r1);
|
||||
|
||||
omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */
|
||||
|
||||
carry = vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
|
||||
vli_clear(product, num_words_secp160r1);
|
||||
omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
|
||||
carry += vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
|
||||
|
||||
while (carry > 0) {
|
||||
--carry;
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
if (vli_cmp(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
|
||||
vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if uECC_WORD_SIZE == 1
|
||||
static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
|
||||
uint8_t carry;
|
||||
uint8_t i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
|
||||
vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
|
||||
result[3] = right[0] << 7; /* get last bit from shift */
|
||||
|
||||
carry = vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
|
||||
for (i = num_words_secp160r1; carry; ++i) {
|
||||
uint16_t sum = (uint16_t)result[i] + carry;
|
||||
result[i] = (uint8_t)sum;
|
||||
carry = sum >> 8;
|
||||
}
|
||||
}
|
||||
#elif uECC_WORD_SIZE == 4
|
||||
static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
|
||||
uint32_t carry;
|
||||
unsigned i;
|
||||
|
||||
/* Multiply by (2^31 + 1). */
|
||||
vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
|
||||
vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
|
||||
result[0] = right[0] << 31; /* get last bit from shift */
|
||||
|
||||
carry = vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
|
||||
for (i = num_words_secp160r1; carry; ++i) {
|
||||
uint64_t sum = (uint64_t)result[i] + carry;
|
||||
result[i] = (uint32_t)sum;
|
||||
carry = sum >> 32;
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
/* Computes result = product % curve_p.
|
||||
See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
|
||||
#if uECC_WORD_SIZE == 1
|
||||
static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
|
||||
uint8_t tmp[num_words_secp192r1];
|
||||
uint8_t carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[24], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
|
||||
tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27];
|
||||
tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
|
||||
tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
|
||||
tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[8] = product[40];
|
||||
tmp[1] = tmp[9] = product[41];
|
||||
tmp[2] = tmp[10] = product[42];
|
||||
tmp[3] = tmp[11] = product[43];
|
||||
tmp[4] = tmp[12] = product[44];
|
||||
tmp[5] = tmp[13] = product[45];
|
||||
tmp[6] = tmp[14] = product[46];
|
||||
tmp[7] = tmp[15] = product[47];
|
||||
tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#elif uECC_WORD_SIZE == 4
|
||||
static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
|
||||
uint32_t tmp[num_words_secp192r1];
|
||||
int carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[6], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = 0;
|
||||
tmp[2] = product[6];
|
||||
tmp[3] = product[7];
|
||||
tmp[4] = product[8];
|
||||
tmp[5] = product[9];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[2] = product[10];
|
||||
tmp[1] = tmp[3] = product[11];
|
||||
tmp[4] = tmp[5] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
|
||||
uint64_t tmp[num_words_secp192r1];
|
||||
int carry;
|
||||
|
||||
vli_set(result, product, num_words_secp192r1);
|
||||
|
||||
vli_set(tmp, &product[3], num_words_secp192r1);
|
||||
carry = vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = 0;
|
||||
tmp[1] = product[3];
|
||||
tmp[2] = product[4];
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
tmp[0] = tmp[1] = product[5];
|
||||
tmp[2] = 0;
|
||||
carry += vli_add(result, result, tmp, num_words_secp192r1);
|
||||
|
||||
while (carry || vli_cmp(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
|
||||
carry -= vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
/* Computes result = product % curve_p
|
||||
from http://www.nsa.gov/ia/_files/nist-routines.pdf */
|
||||
#if uECC_WORD_SIZE == 1
|
||||
void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
|
||||
static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
|
||||
uint8_t tmp[num_words_secp224r1];
|
||||
int8_t carry;
|
||||
|
||||
@@ -698,7 +611,7 @@ void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
|
||||
}
|
||||
}
|
||||
#elif uECC_WORD_SIZE == 4
|
||||
void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
|
||||
static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
|
||||
{
|
||||
uint32_t tmp[num_words_secp224r1];
|
||||
int carry;
|
||||
@@ -749,7 +662,7 @@ void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
|
||||
}
|
||||
}
|
||||
#else
|
||||
void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
|
||||
static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
|
||||
{
|
||||
uint64_t tmp[num_words_secp224r1];
|
||||
int carry = 0;
|
||||
@@ -795,7 +708,53 @@ void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#endif /* uECC_SUPPORTS_secp224r1 */
|
||||
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
|
||||
static const struct uECC_Curve_t curve_secp256r1 = {
|
||||
num_words_secp256r1,
|
||||
num_words_secp256r1,
|
||||
num_bytes_secp256r1,
|
||||
{ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
|
||||
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
|
||||
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
|
||||
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
|
||||
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
|
||||
|
||||
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
|
||||
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
|
||||
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
|
||||
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) },
|
||||
{ BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
|
||||
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
|
||||
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
|
||||
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) },
|
||||
&double_jacobian_default,
|
||||
&mod_sqrt_default,
|
||||
&x_side_default,
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
&vli_mmod_fast_secp256r1
|
||||
#endif
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; }
|
||||
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
/* Computes result = product % curve_p
|
||||
from http://www.nsa.gov/ia/_files/nist-routines.pdf */
|
||||
#if uECC_WORD_SIZE == 1
|
||||
@@ -1077,13 +1036,111 @@ static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) {
|
||||
}
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#endif /* uECC_SUPPORTS_secp256r1 */
|
||||
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
|
||||
static void double_jacobian_secp256k1(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve);
|
||||
static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
|
||||
static const struct uECC_Curve_t curve_secp256k1 = {
|
||||
num_words_secp256k1,
|
||||
num_words_secp256k1,
|
||||
num_bytes_secp256k1,
|
||||
{ BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
|
||||
BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
|
||||
BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
|
||||
{ BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
|
||||
BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
|
||||
BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
|
||||
BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
|
||||
|
||||
BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
|
||||
BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
|
||||
BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
|
||||
BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) },
|
||||
{ BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) },
|
||||
&double_jacobian_secp256k1,
|
||||
&mod_sqrt_default,
|
||||
&x_side_secp256k1,
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
&vli_mmod_fast_secp256k1
|
||||
#endif
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
|
||||
|
||||
|
||||
/* Double in place */
|
||||
static void double_jacobian_secp256k1(uECC_word_t * X1,
|
||||
uECC_word_t * Y1,
|
||||
uECC_word_t * Z1,
|
||||
uECC_Curve curve) {
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[num_words_secp256k1];
|
||||
uECC_word_t t5[num_words_secp256k1];
|
||||
|
||||
if (vli_isZero(Z1, num_words_secp256k1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
|
||||
vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
|
||||
vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
|
||||
vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
|
||||
vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
|
||||
|
||||
vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
|
||||
vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
|
||||
if (vli_testBit(Y1, 0)) {
|
||||
uECC_word_t carry = vli_add(Y1, Y1, curve->p, num_words_secp256k1);
|
||||
vli_rshift1(Y1, num_words_secp256k1);
|
||||
Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
vli_rshift1(Y1, num_words_secp256k1);
|
||||
}
|
||||
/* t2 = 3/2*(x1^2) = B */
|
||||
|
||||
vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
|
||||
vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
|
||||
vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
|
||||
|
||||
vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
|
||||
vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
|
||||
vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
|
||||
}
|
||||
|
||||
/* Computes result = x^3 + b. result must not overlap x. */
|
||||
static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
|
||||
vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
vli_modMult_fast(result, result, x, curve); /* r = x^3 */
|
||||
vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
|
||||
}
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right);
|
||||
static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
|
||||
uECC_word_t tmp[2 * num_words_secp256k1];
|
||||
uECC_word_t carry;
|
||||
|
||||
vli_clear(tmp, 2 * num_words_secp256k1);
|
||||
vli_clear(tmp, num_words_secp256k1);
|
||||
vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
|
||||
|
||||
omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
|
||||
|
||||
@@ -1163,3 +1220,8 @@ static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) {
|
||||
result[num_words_secp256k1] = r0;
|
||||
}
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#endif /* uECC_SUPPORTS_secp256k1 */
|
||||
|
||||
#endif /* _UECC_CURVE_SPECIFIC_H_ */
|
||||
|
||||
+12
-29
@@ -1,3 +1,8 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_PLATFORM_SPECIFIC_H_
|
||||
#define _UECC_PLATFORM_SPECIFIC_H_
|
||||
|
||||
#ifndef uECC_PLATFORM
|
||||
#if __AVR__
|
||||
#define uECC_PLATFORM uECC_avr
|
||||
@@ -32,29 +37,16 @@
|
||||
#error "Unsupported value for uECC_WORD_SIZE"
|
||||
#endif
|
||||
|
||||
/* Optimization options... */
|
||||
#define uECC_asm_none 0
|
||||
#define uECC_asm_small 1
|
||||
#define uECC_asm_fast 2
|
||||
#ifndef uECC_ASM
|
||||
#define uECC_ASM uECC_asm_small
|
||||
#endif
|
||||
|
||||
#ifndef uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
/* --- end --- */
|
||||
|
||||
#if (uECC_ASM && (uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
|
||||
#pragma message ("uECC_WORD_SIZE must be 1 when using AVR asm")
|
||||
#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
|
||||
#pragma message ("uECC_WORD_SIZE must be 1 for AVR")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 1
|
||||
#endif
|
||||
|
||||
#if (uECC_ASM && \
|
||||
(uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb) && \
|
||||
#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2) && \
|
||||
(uECC_WORD_SIZE != 4))
|
||||
#pragma message ("uECC_WORD_SIZE must be 4 when using ARM asm")
|
||||
#pragma message ("uECC_WORD_SIZE must be 4 for ARM")
|
||||
#undef uECC_WORD_SIZE
|
||||
#define uECC_WORD_SIZE 4
|
||||
#endif
|
||||
@@ -172,15 +164,6 @@ static int default_RNG(uint8_t *dest, unsigned size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* platform */
|
||||
|
||||
// #ifdef __GNUC__ /* Only support GCC inline asm for now */
|
||||
// #if (uECC_ASM && (uECC_PLATFORM == uECC_avr))
|
||||
// #include "asm_avr.inc"
|
||||
// #endif
|
||||
//
|
||||
// #if (uECC_ASM && (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
// uECC_PLATFORM == uECC_arm_thumb2))
|
||||
// #include "asm_arm.inc"
|
||||
// #endif
|
||||
// #endif
|
||||
#endif /* _UECC_PLATFORM_SPECIFIC_H_ */
|
||||
|
||||
@@ -4,14 +4,30 @@
|
||||
|
||||
#define MAX_TRIES 64
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
#define uECC_MAX_BYTES 21 /* Due to the size of curve_n. */
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
#undef uECC_MAX_BYTES
|
||||
#define uECC_MAX_BYTES 24
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
#undef uECC_MAX_BYTES
|
||||
#define uECC_MAX_BYTES 28
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
#undef uECC_MAX_BYTES
|
||||
#define uECC_MAX_BYTES 32
|
||||
#endif
|
||||
|
||||
#include "platform-specific.inc"
|
||||
|
||||
#if (uECC_WORD_SIZE == 1)
|
||||
#define uECC_MAX_WORDS 32
|
||||
#define uECC_MAX_WORDS uECC_MAX_BYTES
|
||||
#elif (uECC_WORD_SIZE == 4)
|
||||
#define uECC_MAX_WORDS 8
|
||||
#define uECC_MAX_WORDS ((uECC_MAX_BYTES + 3) / 4)
|
||||
#elif (uECC_WORD_SIZE == 8)
|
||||
#define uECC_MAX_WORDS 4
|
||||
#define uECC_MAX_WORDS ((uECC_MAX_BYTES + 7) / 8)
|
||||
#endif /* uECC_WORD_SIZE */
|
||||
|
||||
struct uECC_Curve_t {
|
||||
@@ -28,14 +44,24 @@ struct uECC_Curve_t {
|
||||
uECC_Curve curve);
|
||||
void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve);
|
||||
void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
|
||||
#endif
|
||||
};
|
||||
|
||||
#if (uECC_ASM == uECC_asm_small)
|
||||
#if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#include "asm_arm_small.inc"
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0) && (uECC_OPTIMIZATION_LEVEL % 2 == 0)
|
||||
#define uECC_SQUARE_FUNC 1
|
||||
#else
|
||||
#define uECC_SQUARE_FUNC 0
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
|
||||
uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 2)
|
||||
#include "asm_arm_mult_square.inc"
|
||||
#include "asm_arm_fast.inc"
|
||||
#endif
|
||||
#include "asm_arm_small.inc"
|
||||
#endif
|
||||
|
||||
static uECC_RNG_Function g_rng_function = &default_RNG;
|
||||
@@ -190,7 +216,7 @@ static void muladd(uECC_word_t a,
|
||||
|
||||
i2 += (i0 >> 32);
|
||||
i2 += i1;
|
||||
if (i2 < i1) { // overflow
|
||||
if (i2 < i1) { /* overflow */
|
||||
i3 += 0x100000000ull;
|
||||
}
|
||||
|
||||
@@ -266,7 +292,7 @@ static void mul2add(uECC_word_t a,
|
||||
i2 += (i0 >> 32);
|
||||
i2 += i1;
|
||||
if (i2 < i1)
|
||||
{ // overflow
|
||||
{ /* overflow */
|
||||
i3 += 0x100000000ull;
|
||||
}
|
||||
|
||||
@@ -365,7 +391,7 @@ static void vli_mmod(uECC_word_t *result,
|
||||
uECC_word_t *v[2] = {tmp, product};
|
||||
uECC_word_t index;
|
||||
|
||||
// Shift mod so its highest set bit is at the maximum position.
|
||||
/* Shift mod so its highest set bit is at the maximum position. */
|
||||
bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - vli_numBits(mod, num_words);
|
||||
wordcount_t word_shift = shift / uECC_WORD_BITS;
|
||||
wordcount_t bit_shift = shift % uECC_WORD_BITS;
|
||||
@@ -381,9 +407,19 @@ static void vli_mmod(uECC_word_t *result,
|
||||
}
|
||||
|
||||
for (index = 1; shift >= 0; --shift) {
|
||||
uECC_word_t borrow = vli_sub(v[1 - index], v[index], mod_multiple, num_words * 2);
|
||||
uECC_word_t borrow = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words * 2; ++i) {
|
||||
uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
|
||||
if (diff != v[index][i]) {
|
||||
borrow = (diff > v[index][i]);
|
||||
}
|
||||
v[1 - index][i] = diff;
|
||||
}
|
||||
index = !(index ^ borrow); /* Swap the index if there was no borrow */
|
||||
vli_rshift1(mod_multiple, num_words * 2);
|
||||
vli_rshift1(mod_multiple, num_words);
|
||||
mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
|
||||
vli_rshift1(mod_multiple + num_words, num_words);
|
||||
}
|
||||
vli_set(result, v[index], num_words);
|
||||
}
|
||||
@@ -399,6 +435,8 @@ static void vli_modMult(uECC_word_t *result,
|
||||
vli_mmod(result, product, mod, num_words);
|
||||
}
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
|
||||
static void vli_modMult_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
@@ -408,6 +446,13 @@ static void vli_modMult_fast(uECC_word_t *result,
|
||||
curve->mmod_fast(result, product);
|
||||
}
|
||||
|
||||
#else /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#define vli_modMult_fast(result, left, right, curve) \
|
||||
vli_modMult((result), (left), (right), (curve)->p, (curve)->num_words)
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
|
||||
/* Computes result = left^2 % mod. */
|
||||
@@ -420,6 +465,8 @@ static void vli_modSquare(uECC_word_t *result,
|
||||
vli_mmod(result, product, mod, num_words);
|
||||
}
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL > 0)
|
||||
|
||||
static void vli_modSquare_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
uECC_Curve curve) {
|
||||
@@ -428,6 +475,13 @@ static void vli_modSquare_fast(uECC_word_t *result,
|
||||
curve->mmod_fast(result, product);
|
||||
}
|
||||
|
||||
#else /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#define vli_modSquare_fast(result, left, curve) \
|
||||
vli_modSquare((result), (left), (curve)->p, (curve)->num_words)
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
|
||||
|
||||
#else /* uECC_SQUARE_FUNC */
|
||||
|
||||
#define vli_modSquare(result, left, mod, num_words) \
|
||||
@@ -508,7 +562,8 @@ static void vli_modInv(uECC_word_t *result,
|
||||
|
||||
/* Returns 1 if 'point' is the point at infinity, 0 otherwise. */
|
||||
static cmpresult_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) {
|
||||
return vli_isZero(point, curve->num_words * 2);
|
||||
return vli_isZero(point, curve->num_words) &&
|
||||
vli_isZero(point + curve->num_words, curve->num_words);
|
||||
}
|
||||
|
||||
/* Point multiplication algorithm using Montgomery's ladder with co-Z coordinates.
|
||||
@@ -695,8 +750,8 @@ static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Regularize the bitcount for the private key so that attackers cannot use a side channel
|
||||
// attack to learn the number of leading zeros.
|
||||
/* 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, tmp1, tmp2, curve);
|
||||
|
||||
EccPoint_mult(result, curve->G, p2[!carry], 0,
|
||||
@@ -822,12 +877,12 @@ int uECC_shared_secret(const uint8_t *public_key,
|
||||
vli_bytesToNative(public, public_key, curve);
|
||||
vli_bytesToNative(public + curve->num_words, public_key + curve->num_bytes, curve);
|
||||
|
||||
// Regularize the bitcount for the private key so that attackers cannot use a side channel
|
||||
// attack to learn the number of leading zeros.
|
||||
/* 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, private, tmp, curve);
|
||||
|
||||
// If an RNG function was specified, try to get a random initial Z value to improve
|
||||
// protection against side-channel attacks.
|
||||
/* 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 != &default_RNG) {
|
||||
for (tries = 0; tries < MAX_TRIES; ++tries) {
|
||||
if (!generate_random_int(p2[carry], curve->num_words, curve->num_bytes * 8)) {
|
||||
@@ -880,12 +935,12 @@ int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) {
|
||||
vli_bytesToNative(public, public_key, curve);
|
||||
vli_bytesToNative(public + curve->num_words, public_key + curve->num_bytes, curve);
|
||||
|
||||
// The point at infinity is invalid.
|
||||
/* The point at infinity is invalid. */
|
||||
if (EccPoint_isZero(public, curve)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// x and y must be smaller than p.
|
||||
|
||||
/* x and y must be smaller than p. */
|
||||
if (vli_cmp(curve->p, public, curve->num_words) != 1 ||
|
||||
vli_cmp(curve->p, public + curve->num_words, curve->num_words) != 1) {
|
||||
return 0;
|
||||
@@ -1065,8 +1120,8 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
V[i] = 0x01;
|
||||
K[i] = 0;
|
||||
}
|
||||
|
||||
// K = HMAC_K(V || 0x00 || int2octets(x) || h(m))
|
||||
|
||||
/* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */
|
||||
HMAC_init(hash_context, K);
|
||||
V[hash_context->result_size] = 0x00;
|
||||
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
||||
@@ -1075,8 +1130,8 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
HMAC_finish(hash_context, K, K);
|
||||
|
||||
update_V(hash_context, K, V);
|
||||
|
||||
// K = HMAC_K(V || 0x01 || int2octets(x) || h(m))
|
||||
|
||||
/* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */
|
||||
HMAC_init(hash_context, K);
|
||||
V[hash_context->result_size] = 0x01;
|
||||
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
||||
@@ -1106,7 +1161,7 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
||||
return 1;
|
||||
}
|
||||
|
||||
// K = HMAC_K(V || 0x00)
|
||||
/* K = HMAC_K(V || 0x00) */
|
||||
HMAC_init(hash_context, K);
|
||||
V[hash_context->result_size] = 0x00;
|
||||
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _MICRO_ECC_H_
|
||||
#define _MICRO_ECC_H_
|
||||
#ifndef _UECC_H_
|
||||
#define _UECC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -17,11 +17,34 @@ Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arm64 6
|
||||
#define uECC_avr 7
|
||||
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
|
||||
platform. */
|
||||
|
||||
/* Optimization level; trade speed for code size.
|
||||
Larger values produce code that is faster but larger.
|
||||
Currently supported values are 0 - 4; 0 is unusably slow for most applications. */
|
||||
#ifndef uECC_OPTIMIZATION_LEVEL
|
||||
#define uECC_OPTIMIZATION_LEVEL 1
|
||||
#endif
|
||||
|
||||
/* Curve support selection. Set to 0 to remove that curve. */
|
||||
#ifndef uECC_SUPPORTS_secp160r1
|
||||
#define uECC_SUPPORTS_secp160r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp192r1
|
||||
#define uECC_SUPPORTS_secp192r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp224r1
|
||||
#define uECC_SUPPORTS_secp224r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256r1
|
||||
#define uECC_SUPPORTS_secp256r1 1
|
||||
#endif
|
||||
#ifndef uECC_SUPPORTS_secp256k1
|
||||
#define uECC_SUPPORTS_secp256k1 1
|
||||
#endif
|
||||
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t * uECC_Curve;
|
||||
|
||||
@@ -30,11 +53,21 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
uECC_Curve uECC_secp160r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
uECC_Curve uECC_secp192r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
uECC_Curve uECC_secp224r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256r1
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp256k1
|
||||
uECC_Curve uECC_secp256k1(void);
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
|
||||
@@ -261,4 +294,4 @@ int uECC_verify(const uint8_t *private_key,
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MICRO_ECC_H_ */
|
||||
#endif /* _UECC_H_ */
|
||||
|
||||
Reference in New Issue
Block a user