Update pre9
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
# details see http://www.openssl.org/~appro/cryptogams/.
|
||||
# ====================================================================
|
||||
#
|
||||
# X25519 lower-level primitives for x86_86.
|
||||
# X25519 lower-level primitives for x86_64.
|
||||
#
|
||||
# February 2018.
|
||||
#
|
||||
@@ -102,13 +102,22 @@ $code.=<<___;
|
||||
.type x25519_fe51_mul,\@function,3
|
||||
.align 32
|
||||
x25519_fe51_mul:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_mul_body:
|
||||
|
||||
mov 8*0(%rsi),%rax # f[0]
|
||||
mov 8*0(%rdx),%r11 # load g[0-4]
|
||||
@@ -236,19 +245,30 @@ x25519_fe51_mul:
|
||||
|
||||
mov 8*4(%rsp),%rdi # restore 1st argument
|
||||
jmp .Lreduce51
|
||||
.Lfe51_mul_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_mul,.-x25519_fe51_mul
|
||||
|
||||
.globl x25519_fe51_sqr
|
||||
.type x25519_fe51_sqr,\@function,2
|
||||
.align 32
|
||||
x25519_fe51_sqr:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_sqr_body:
|
||||
|
||||
mov 8*0(%rsi),%rax # g[0]
|
||||
mov 8*2(%rsi),%r15 # g[2]
|
||||
@@ -391,27 +411,45 @@ x25519_fe51_sqr:
|
||||
mov %r10,8*4(%rdi)
|
||||
|
||||
mov 8*5(%rsp),%r15
|
||||
.cfi_restore %r15
|
||||
mov 8*6(%rsp),%r14
|
||||
.cfi_restore %r14
|
||||
mov 8*7(%rsp),%r13
|
||||
.cfi_restore %r13
|
||||
mov 8*8(%rsp),%r12
|
||||
.cfi_restore %r12
|
||||
mov 8*9(%rsp),%rbx
|
||||
.cfi_restore %rbx
|
||||
mov 8*10(%rsp),%rbp
|
||||
.cfi_restore %rbp
|
||||
lea 8*11(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 88
|
||||
.Lfe51_sqr_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_sqr,.-x25519_fe51_sqr
|
||||
|
||||
.globl x25519_fe51_mul121666
|
||||
.type x25519_fe51_mul121666,\@function,2
|
||||
.align 32
|
||||
x25519_fe51_mul121666:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
mov \$121666,%eax
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_mul121666_body:
|
||||
mov \$121666,%eax
|
||||
|
||||
mulq 8*0(%rsi)
|
||||
mov %rax,%rbx # %rbx:%rcx = h0
|
||||
@@ -434,6 +472,8 @@ x25519_fe51_mul121666:
|
||||
mov %rdx,%r15
|
||||
|
||||
jmp .Lreduce51
|
||||
.Lfe51_mul121666_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_mul121666,.-x25519_fe51_mul121666
|
||||
___
|
||||
########################################################################
|
||||
@@ -460,14 +500,24 @@ x25519_fe64_eligible:
|
||||
.type x25519_fe64_mul,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_mul:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
push %rdi # offload dst
|
||||
.cfi_push %rdi
|
||||
lea -8*2(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 16
|
||||
.Lfe64_mul_body:
|
||||
|
||||
mov %rdx,%rax
|
||||
mov 8*0(%rdx),%rbp # b[0]
|
||||
@@ -534,20 +584,32 @@ x25519_fe64_mul:
|
||||
adox %rdi,$acc7 # of=0
|
||||
|
||||
jmp .Lreduce64
|
||||
.Lfe64_mul_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe64_mul,.-x25519_fe64_mul
|
||||
|
||||
.globl x25519_fe64_sqr
|
||||
.type x25519_fe64_sqr,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_sqr:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
push %rdi # offload dst
|
||||
.cfi_push %rdi
|
||||
lea -8*2(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 16
|
||||
.Lfe64_sqr_body:
|
||||
|
||||
mov 8*0(%rsi),%rdx # a[0]
|
||||
mov 8*1(%rsi),%rcx # a[1]
|
||||
@@ -637,19 +699,29 @@ x25519_fe64_sqr:
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
mov 8*3(%rsp),%r15
|
||||
.cfi_restore %r15
|
||||
mov 8*4(%rsp),%r14
|
||||
.cfi_restore %r14
|
||||
mov 8*5(%rsp),%r13
|
||||
.cfi_restore %r13
|
||||
mov 8*6(%rsp),%r12
|
||||
.cfi_restore %r12
|
||||
mov 8*7(%rsp),%rbx
|
||||
.cfi_restore %rbx
|
||||
mov 8*8(%rsp),%rbp
|
||||
.cfi_restore %rbp
|
||||
lea 8*9(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 88
|
||||
.Lfe64_sqr_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size x25519_fe64_sqr,.-x25519_fe64_sqr
|
||||
|
||||
.globl x25519_fe64_mul121666
|
||||
.type x25519_fe64_mul121666,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_mul121666:
|
||||
.Lfe64_mul121666_body:
|
||||
mov \$121666,%edx
|
||||
mulx 8*0(%rsi),$acc0,%rcx
|
||||
mulx 8*1(%rsi),$acc1,%rax
|
||||
@@ -676,6 +748,7 @@ x25519_fe64_mul121666:
|
||||
mov $acc3,8*3(%rdi)
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_mul121666_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_mul121666,.-x25519_fe64_mul121666
|
||||
|
||||
@@ -683,6 +756,7 @@ x25519_fe64_mul121666:
|
||||
.type x25519_fe64_add,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_add:
|
||||
.Lfe64_add_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -698,13 +772,18 @@ x25519_fe64_add:
|
||||
|
||||
add %rax,$acc0
|
||||
adc \$0,$acc1
|
||||
mov $acc0,8*0(%rdi)
|
||||
adc \$0,$acc2
|
||||
mov $acc1,8*1(%rdi)
|
||||
adc \$0,$acc3
|
||||
mov $acc2,8*2(%rdi)
|
||||
sbb %rax,%rax # cf -> mask
|
||||
mov $acc3,8*3(%rdi)
|
||||
and \$38,%rax
|
||||
|
||||
add %rax,$acc0
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_add_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_add,.-x25519_fe64_add
|
||||
|
||||
@@ -712,6 +791,7 @@ x25519_fe64_add:
|
||||
.type x25519_fe64_sub,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_sub:
|
||||
.Lfe64_sub_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -727,13 +807,18 @@ x25519_fe64_sub:
|
||||
|
||||
sub %rax,$acc0
|
||||
sbb \$0,$acc1
|
||||
mov $acc0,8*0(%rdi)
|
||||
sbb \$0,$acc2
|
||||
mov $acc1,8*1(%rdi)
|
||||
sbb \$0,$acc3
|
||||
mov $acc2,8*2(%rdi)
|
||||
sbb %rax,%rax # cf -> mask
|
||||
mov $acc3,8*3(%rdi)
|
||||
and \$38,%rax
|
||||
|
||||
sub %rax,$acc0
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_sub_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_sub,.-x25519_fe64_sub
|
||||
|
||||
@@ -741,6 +826,7 @@ x25519_fe64_sub:
|
||||
.type x25519_fe64_tobytes,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_tobytes:
|
||||
.Lfe64_to_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -751,6 +837,7 @@ x25519_fe64_tobytes:
|
||||
sar \$63,$acc3 # most significant bit -> mask
|
||||
shr \$1,%rax # most significant bit cleared
|
||||
and \$19,$acc3
|
||||
add \$19,$acc3 # compare to modulus in the same go
|
||||
|
||||
add $acc3,$acc0
|
||||
adc \$0,$acc1
|
||||
@@ -760,15 +847,20 @@ x25519_fe64_tobytes:
|
||||
lea (%rax,%rax),$acc3
|
||||
sar \$63,%rax # most significant bit -> mask
|
||||
shr \$1,$acc3 # most significant bit cleared
|
||||
not %rax
|
||||
and \$19,%rax
|
||||
|
||||
add %rax,$acc0
|
||||
sub %rax,$acc0
|
||||
sbb \$0,$acc1
|
||||
sbb \$0,$acc2
|
||||
sbb \$0,$acc3
|
||||
|
||||
mov $acc0,8*0(%rdi)
|
||||
mov $acc1,8*1(%rdi)
|
||||
mov $acc2,8*2(%rdi)
|
||||
mov $acc3,8*3(%rdi)
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_to_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_tobytes,.-x25519_fe64_tobytes
|
||||
___
|
||||
@@ -804,6 +896,222 @@ $code.=<<___;
|
||||
.asciz "X25519 primitives for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
___
|
||||
|
||||
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
|
||||
# CONTEXT *context,DISPATCHER_CONTEXT *disp)
|
||||
if ($win64) {
|
||||
$rec="%rcx";
|
||||
$frame="%rdx";
|
||||
$context="%r8";
|
||||
$disp="%r9";
|
||||
|
||||
$code.=<<___;
|
||||
.extern __imp_RtlVirtualUnwind
|
||||
|
||||
.type short_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
short_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
pushfq
|
||||
sub \$64,%rsp
|
||||
|
||||
mov 120($context),%rax # pull context->Rax
|
||||
mov 248($context),%rbx # pull context->Rip
|
||||
|
||||
mov 8($disp),%rsi # disp->ImageBase
|
||||
mov 56($disp),%r11 # disp->HandlerData
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # end of prologue label
|
||||
cmp %r10,%rbx # context->Rip<end of prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
jmp .Lcommon_seh_tail
|
||||
.size short_handler,.-short_handler
|
||||
|
||||
.type full_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
full_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
pushfq
|
||||
sub \$64,%rsp
|
||||
|
||||
mov 120($context),%rax # pull context->Rax
|
||||
mov 248($context),%rbx # pull context->Rip
|
||||
|
||||
mov 8($disp),%rsi # disp->ImageBase
|
||||
mov 56($disp),%r11 # disp->HandlerData
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # end of prologue label
|
||||
cmp %r10,%rbx # context->Rip<end of prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=epilogue label
|
||||
jae .Lcommon_seh_tail
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
lea (%rax,%r10),%rax
|
||||
|
||||
mov -8(%rax),%rbp
|
||||
mov -16(%rax),%rbx
|
||||
mov -24(%rax),%r12
|
||||
mov -32(%rax),%r13
|
||||
mov -40(%rax),%r14
|
||||
mov -48(%rax),%r15
|
||||
mov %rbx,144($context) # restore context->Rbx
|
||||
mov %rbp,160($context) # restore context->Rbp
|
||||
mov %r12,216($context) # restore context->R12
|
||||
mov %r13,224($context) # restore context->R13
|
||||
mov %r14,232($context) # restore context->R14
|
||||
mov %r15,240($context) # restore context->R15
|
||||
|
||||
.Lcommon_seh_tail:
|
||||
mov 8(%rax),%rdi
|
||||
mov 16(%rax),%rsi
|
||||
mov %rax,152($context) # restore context->Rsp
|
||||
mov %rsi,168($context) # restore context->Rsi
|
||||
mov %rdi,176($context) # restore context->Rdi
|
||||
|
||||
mov 40($disp),%rdi # disp->ContextRecord
|
||||
mov $context,%rsi # context
|
||||
mov \$154,%ecx # sizeof(CONTEXT)
|
||||
.long 0xa548f3fc # cld; rep movsq
|
||||
|
||||
mov $disp,%rsi
|
||||
xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
|
||||
mov 8(%rsi),%rdx # arg2, disp->ImageBase
|
||||
mov 0(%rsi),%r8 # arg3, disp->ControlPc
|
||||
mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
|
||||
mov 40(%rsi),%r10 # disp->ContextRecord
|
||||
lea 56(%rsi),%r11 # &disp->HandlerData
|
||||
lea 24(%rsi),%r12 # &disp->EstablisherFrame
|
||||
mov %r10,32(%rsp) # arg5
|
||||
mov %r11,40(%rsp) # arg6
|
||||
mov %r12,48(%rsp) # arg7
|
||||
mov %rcx,56(%rsp) # arg8, (NULL)
|
||||
call *__imp_RtlVirtualUnwind(%rip)
|
||||
|
||||
mov \$1,%eax # ExceptionContinueSearch
|
||||
add \$64,%rsp
|
||||
popfq
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %rbp
|
||||
pop %rbx
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
ret
|
||||
.size full_handler,.-full_handler
|
||||
|
||||
.section .pdata
|
||||
.align 4
|
||||
.rva .LSEH_begin_x25519_fe51_mul
|
||||
.rva .LSEH_end_x25519_fe51_mul
|
||||
.rva .LSEH_info_x25519_fe51_mul
|
||||
|
||||
.rva .LSEH_begin_x25519_fe51_sqr
|
||||
.rva .LSEH_end_x25519_fe51_sqr
|
||||
.rva .LSEH_info_x25519_fe51_sqr
|
||||
|
||||
.rva .LSEH_begin_x25519_fe51_mul121666
|
||||
.rva .LSEH_end_x25519_fe51_mul121666
|
||||
.rva .LSEH_info_x25519_fe51_mul121666
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.rva .LSEH_begin_x25519_fe64_mul
|
||||
.rva .LSEH_end_x25519_fe64_mul
|
||||
.rva .LSEH_info_x25519_fe64_mul
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_sqr
|
||||
.rva .LSEH_end_x25519_fe64_sqr
|
||||
.rva .LSEH_info_x25519_fe64_sqr
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_mul121666
|
||||
.rva .LSEH_end_x25519_fe64_mul121666
|
||||
.rva .LSEH_info_x25519_fe64_mul121666
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_add
|
||||
.rva .LSEH_end_x25519_fe64_add
|
||||
.rva .LSEH_info_x25519_fe64_add
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_sub
|
||||
.rva .LSEH_end_x25519_fe64_sub
|
||||
.rva .LSEH_info_x25519_fe64_sub
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_tobytes
|
||||
.rva .LSEH_end_x25519_fe64_tobytes
|
||||
.rva .LSEH_info_x25519_fe64_tobytes
|
||||
___
|
||||
$code.=<<___;
|
||||
.section .xdata
|
||||
.align 8
|
||||
.LSEH_info_x25519_fe51_mul:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_mul_body,.Lfe51_mul_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
.LSEH_info_x25519_fe51_sqr:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_sqr_body,.Lfe51_sqr_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
.LSEH_info_x25519_fe51_mul121666:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_mul121666_body,.Lfe51_mul121666_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.LSEH_info_x25519_fe64_mul:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe64_mul_body,.Lfe64_mul_epilogue # HandlerData[]
|
||||
.long 72,0
|
||||
.LSEH_info_x25519_fe64_sqr:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe64_sqr_body,.Lfe64_sqr_epilogue # HandlerData[]
|
||||
.long 72,0
|
||||
.LSEH_info_x25519_fe64_mul121666:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_mul121666_body,.Lfe64_mul121666_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_add:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_add_body,.Lfe64_add_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_sub:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_sub_body,.Lfe64_sub_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_tobytes:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_to_body,.Lfe64_to_epilogue # HandlerData[]
|
||||
___
|
||||
}
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
print $code;
|
||||
close STDOUT;
|
||||
+150
-143
@@ -11,149 +11,23 @@
|
||||
#include "ec_lcl.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#if defined(X25519_ASM) \
|
||||
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
|
||||
&& !defined(__sparc__) \
|
||||
&& !(defined(__ANDROID__) && !defined(__clang__)) )
|
||||
/*
|
||||
* Base 2^51 implementation.
|
||||
*/
|
||||
# define BASE_2_51_IMPLEMENTED
|
||||
#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64))
|
||||
|
||||
typedef uint64_t fe51[5];
|
||||
# if !defined(X25519_ASM)
|
||||
typedef __uint128_t u128;
|
||||
# endif
|
||||
|
||||
static const uint64_t MASK51 = 0x7ffffffffffff;
|
||||
|
||||
static uint64_t load_7(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
result |= ((uint64_t)in[6]) << 48;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t load_6(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void fe51_frombytes(fe51 h, const uint8_t *s)
|
||||
{
|
||||
uint64_t h0 = load_7(s); /* 56 bits */
|
||||
uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */
|
||||
uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */
|
||||
uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */
|
||||
uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */
|
||||
|
||||
h1 |= h0 >> 51; h0 &= MASK51;
|
||||
h2 |= h1 >> 51; h1 &= MASK51;
|
||||
h3 |= h2 >> 51; h2 &= MASK51;
|
||||
h4 |= h3 >> 51; h3 &= MASK51;
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
}
|
||||
|
||||
static void fe51_tobytes(uint8_t *s, const fe51 h)
|
||||
{
|
||||
uint64_t h0 = h[0];
|
||||
uint64_t h1 = h[1];
|
||||
uint64_t h2 = h[2];
|
||||
uint64_t h3 = h[3];
|
||||
uint64_t h4 = h[4];
|
||||
uint64_t q;
|
||||
|
||||
/* compare to modulus */
|
||||
q = (h0 + 19) >> 51;
|
||||
q = (h1 + q) >> 51;
|
||||
q = (h2 + q) >> 51;
|
||||
q = (h3 + q) >> 51;
|
||||
q = (h4 + q) >> 51;
|
||||
|
||||
/* full reduce */
|
||||
h0 += 19 * q;
|
||||
h1 += h0 >> 51; h0 &= MASK51;
|
||||
h2 += h1 >> 51; h1 &= MASK51;
|
||||
h3 += h2 >> 51; h2 &= MASK51;
|
||||
h4 += h3 >> 51; h3 &= MASK51;
|
||||
h4 &= MASK51;
|
||||
|
||||
/* smash */
|
||||
s[0] = (uint8_t)(h0 >> 0);
|
||||
s[1] = (uint8_t)(h0 >> 8);
|
||||
s[2] = (uint8_t)(h0 >> 16);
|
||||
s[3] = (uint8_t)(h0 >> 24);
|
||||
s[4] = (uint8_t)(h0 >> 32);
|
||||
s[5] = (uint8_t)(h0 >> 40);
|
||||
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
|
||||
s[7] = (uint8_t)(h1 >> 5);
|
||||
s[8] = (uint8_t)(h1 >> 13);
|
||||
s[9] = (uint8_t)(h1 >> 21);
|
||||
s[10] = (uint8_t)(h1 >> 29);
|
||||
s[11] = (uint8_t)(h1 >> 37);
|
||||
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
|
||||
s[13] = (uint8_t)(h2 >> 2);
|
||||
s[14] = (uint8_t)(h2 >> 10);
|
||||
s[15] = (uint8_t)(h2 >> 18);
|
||||
s[16] = (uint8_t)(h2 >> 26);
|
||||
s[17] = (uint8_t)(h2 >> 34);
|
||||
s[18] = (uint8_t)(h2 >> 42);
|
||||
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
|
||||
s[20] = (uint8_t)(h3 >> 7);
|
||||
s[21] = (uint8_t)(h3 >> 15);
|
||||
s[22] = (uint8_t)(h3 >> 23);
|
||||
s[23] = (uint8_t)(h3 >> 31);
|
||||
s[24] = (uint8_t)(h3 >> 39);
|
||||
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
|
||||
s[26] = (uint8_t)(h4 >> 4);
|
||||
s[27] = (uint8_t)(h4 >> 12);
|
||||
s[28] = (uint8_t)(h4 >> 20);
|
||||
s[29] = (uint8_t)(h4 >> 28);
|
||||
s[30] = (uint8_t)(h4 >> 36);
|
||||
s[31] = (uint8_t)(h4 >> 44);
|
||||
}
|
||||
|
||||
# ifdef X25519_ASM
|
||||
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
|
||||
void x25519_fe51_sqr(fe51 h, const fe51 f);
|
||||
void x25519_fe51_mul121666(fe51 h, fe51 f);
|
||||
# define fe51_mul x25519_fe51_mul
|
||||
# define fe51_sq x25519_fe51_sqr
|
||||
# define fe51_mul121666 x25519_fe51_mul121666
|
||||
|
||||
# if defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64)
|
||||
|
||||
# define BASE_2_64_IMPLEMENTED
|
||||
# define BASE_2_64_IMPLEMENTED
|
||||
|
||||
typedef uint64_t fe64[4];
|
||||
|
||||
int x25519_fe64_eligible(void);
|
||||
|
||||
/*
|
||||
* There are no reference C implementations for this radix.
|
||||
* Following subroutines perform corresponding operations modulo
|
||||
* 2^256-38, i.e. double the curve modulus. However, inputs and
|
||||
* outputs are permitted to be partially reduced, i.e. to remain
|
||||
* in [0..2^256) range. It's all tied up in final fe64_tobytes
|
||||
* that performs full reduction modulo 2^255-19.
|
||||
*
|
||||
* There are no reference C implementations for these.
|
||||
*/
|
||||
void x25519_fe64_mul(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_sqr(fe64 h, const fe64 f);
|
||||
@@ -161,12 +35,12 @@ void x25519_fe64_mul121666(fe64 h, fe64 f);
|
||||
void x25519_fe64_add(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_sub(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_tobytes(uint8_t *s, const fe64 f);
|
||||
# define fe64_mul x25519_fe64_mul
|
||||
# define fe64_sqr x25519_fe64_sqr
|
||||
# define fe64_mul121666 x25519_fe64_mul121666
|
||||
# define fe64_add x25519_fe64_add
|
||||
# define fe64_sub x25519_fe64_sub
|
||||
# define fe64_tobytes x25519_fe64_tobytes
|
||||
# define fe64_mul x25519_fe64_mul
|
||||
# define fe64_sqr x25519_fe64_sqr
|
||||
# define fe64_mul121666 x25519_fe64_mul121666
|
||||
# define fe64_add x25519_fe64_add
|
||||
# define fe64_sub x25519_fe64_sub
|
||||
# define fe64_tobytes x25519_fe64_tobytes
|
||||
|
||||
static uint64_t load_8(const uint8_t *in)
|
||||
{
|
||||
@@ -375,10 +249,143 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
|
||||
|
||||
OPENSSL_cleanse(e, sizeof(e));
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(X25519_ASM) \
|
||||
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
|
||||
&& !defined(__sparc__) \
|
||||
&& !(defined(__ANDROID__) && !defined(__clang__)) )
|
||||
/*
|
||||
* Base 2^51 implementation. It's virtually no different from reference
|
||||
* base 2^25.5 implementation in respect to lax boundary conditions for
|
||||
* intermediate values and even individual limbs. So that whatever you
|
||||
* know about the reference, applies even here...
|
||||
*/
|
||||
# define BASE_2_51_IMPLEMENTED
|
||||
|
||||
typedef uint64_t fe51[5];
|
||||
|
||||
static const uint64_t MASK51 = 0x7ffffffffffff;
|
||||
|
||||
static uint64_t load_7(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
result |= ((uint64_t)in[6]) << 48;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t load_6(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void fe51_frombytes(fe51 h, const uint8_t *s)
|
||||
{
|
||||
uint64_t h0 = load_7(s); /* 56 bits */
|
||||
uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */
|
||||
uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */
|
||||
uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */
|
||||
uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */
|
||||
|
||||
h1 |= h0 >> 51; h0 &= MASK51;
|
||||
h2 |= h1 >> 51; h1 &= MASK51;
|
||||
h3 |= h2 >> 51; h2 &= MASK51;
|
||||
h4 |= h3 >> 51; h3 &= MASK51;
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
}
|
||||
|
||||
static void fe51_tobytes(uint8_t *s, const fe51 h)
|
||||
{
|
||||
uint64_t h0 = h[0];
|
||||
uint64_t h1 = h[1];
|
||||
uint64_t h2 = h[2];
|
||||
uint64_t h3 = h[3];
|
||||
uint64_t h4 = h[4];
|
||||
uint64_t q;
|
||||
|
||||
/* compare to modulus */
|
||||
q = (h0 + 19) >> 51;
|
||||
q = (h1 + q) >> 51;
|
||||
q = (h2 + q) >> 51;
|
||||
q = (h3 + q) >> 51;
|
||||
q = (h4 + q) >> 51;
|
||||
|
||||
/* full reduce */
|
||||
h0 += 19 * q;
|
||||
h1 += h0 >> 51; h0 &= MASK51;
|
||||
h2 += h1 >> 51; h1 &= MASK51;
|
||||
h3 += h2 >> 51; h2 &= MASK51;
|
||||
h4 += h3 >> 51; h3 &= MASK51;
|
||||
h4 &= MASK51;
|
||||
|
||||
/* smash */
|
||||
s[0] = (uint8_t)(h0 >> 0);
|
||||
s[1] = (uint8_t)(h0 >> 8);
|
||||
s[2] = (uint8_t)(h0 >> 16);
|
||||
s[3] = (uint8_t)(h0 >> 24);
|
||||
s[4] = (uint8_t)(h0 >> 32);
|
||||
s[5] = (uint8_t)(h0 >> 40);
|
||||
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
|
||||
s[7] = (uint8_t)(h1 >> 5);
|
||||
s[8] = (uint8_t)(h1 >> 13);
|
||||
s[9] = (uint8_t)(h1 >> 21);
|
||||
s[10] = (uint8_t)(h1 >> 29);
|
||||
s[11] = (uint8_t)(h1 >> 37);
|
||||
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
|
||||
s[13] = (uint8_t)(h2 >> 2);
|
||||
s[14] = (uint8_t)(h2 >> 10);
|
||||
s[15] = (uint8_t)(h2 >> 18);
|
||||
s[16] = (uint8_t)(h2 >> 26);
|
||||
s[17] = (uint8_t)(h2 >> 34);
|
||||
s[18] = (uint8_t)(h2 >> 42);
|
||||
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
|
||||
s[20] = (uint8_t)(h3 >> 7);
|
||||
s[21] = (uint8_t)(h3 >> 15);
|
||||
s[22] = (uint8_t)(h3 >> 23);
|
||||
s[23] = (uint8_t)(h3 >> 31);
|
||||
s[24] = (uint8_t)(h3 >> 39);
|
||||
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
|
||||
s[26] = (uint8_t)(h4 >> 4);
|
||||
s[27] = (uint8_t)(h4 >> 12);
|
||||
s[28] = (uint8_t)(h4 >> 20);
|
||||
s[29] = (uint8_t)(h4 >> 28);
|
||||
s[30] = (uint8_t)(h4 >> 36);
|
||||
s[31] = (uint8_t)(h4 >> 44);
|
||||
}
|
||||
|
||||
# if defined(X25519_ASM)
|
||||
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
|
||||
void x25519_fe51_sqr(fe51 h, const fe51 f);
|
||||
void x25519_fe51_mul121666(fe51 h, fe51 f);
|
||||
# define fe51_mul x25519_fe51_mul
|
||||
# define fe51_sq x25519_fe51_sqr
|
||||
# define fe51_mul121666 x25519_fe51_mul121666
|
||||
# else
|
||||
|
||||
typedef __uint128_t u128;
|
||||
|
||||
static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
|
||||
{
|
||||
u128 h0, h1, h2, h3, h4;
|
||||
|
||||
+271
-57
@@ -15,63 +15,6 @@
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
|
||||
const EC_METHOD *EC_GF2m_simple_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_characteristic_two_field,
|
||||
ec_GF2m_simple_group_init,
|
||||
ec_GF2m_simple_group_finish,
|
||||
ec_GF2m_simple_group_clear_finish,
|
||||
ec_GF2m_simple_group_copy,
|
||||
ec_GF2m_simple_group_set_curve,
|
||||
ec_GF2m_simple_group_get_curve,
|
||||
ec_GF2m_simple_group_get_degree,
|
||||
ec_group_simple_order_bits,
|
||||
ec_GF2m_simple_group_check_discriminant,
|
||||
ec_GF2m_simple_point_init,
|
||||
ec_GF2m_simple_point_finish,
|
||||
ec_GF2m_simple_point_clear_finish,
|
||||
ec_GF2m_simple_point_copy,
|
||||
ec_GF2m_simple_point_set_to_infinity,
|
||||
0 /* set_Jprojective_coordinates_GFp */ ,
|
||||
0 /* get_Jprojective_coordinates_GFp */ ,
|
||||
ec_GF2m_simple_point_set_affine_coordinates,
|
||||
ec_GF2m_simple_point_get_affine_coordinates,
|
||||
0, 0, 0,
|
||||
ec_GF2m_simple_add,
|
||||
ec_GF2m_simple_dbl,
|
||||
ec_GF2m_simple_invert,
|
||||
ec_GF2m_simple_is_at_infinity,
|
||||
ec_GF2m_simple_is_on_curve,
|
||||
ec_GF2m_simple_cmp,
|
||||
ec_GF2m_simple_make_affine,
|
||||
ec_GF2m_simple_points_make_affine,
|
||||
0 /* mul */,
|
||||
0 /* precompute_mul */,
|
||||
0 /* have_precompute_mul */,
|
||||
ec_GF2m_simple_field_mul,
|
||||
ec_GF2m_simple_field_sqr,
|
||||
ec_GF2m_simple_field_div,
|
||||
0 /* field_encode */ ,
|
||||
0 /* field_decode */ ,
|
||||
0, /* field_set_to_one */
|
||||
ec_key_simple_priv2oct,
|
||||
ec_key_simple_oct2priv,
|
||||
0, /* set private */
|
||||
ec_key_simple_generate_key,
|
||||
ec_key_simple_check_key,
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
|
||||
* are handled by EC_GROUP_new.
|
||||
@@ -737,4 +680,275 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
|
||||
return BN_GF2m_mod_div(r, a, b, group->field, ctx);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Lopez-Dahab ladder, pre step.
|
||||
* See e.g. "Guide to ECC" Alg 3.40.
|
||||
* Modified to blind s and r independently.
|
||||
* s:= p, r := 2p
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
/* if p is not affine, something is wrong */
|
||||
if (p->Z_is_one == 0)
|
||||
return 0;
|
||||
|
||||
/* s blinding: make sure lambda (s->Z here) is not zero */
|
||||
do {
|
||||
if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(s->Z));
|
||||
|
||||
/* if field_encode defined convert between representations */
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, s->Z, s->Z, ctx))
|
||||
|| !group->meth->field_mul(group, s->X, p->X, s->Z, ctx))
|
||||
return 0;
|
||||
|
||||
/* r blinding: make sure lambda (r->Y here for storage) is not zero */
|
||||
do {
|
||||
if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(r->Y));
|
||||
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, r->Y, r->Y, ctx))
|
||||
|| !group->meth->field_sqr(group, r->Z, p->X, ctx)
|
||||
|| !group->meth->field_sqr(group, r->X, r->Z, ctx)
|
||||
|| !BN_GF2m_add(r->X, r->X, group->b)
|
||||
|| !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
|
||||
|| !group->meth->field_mul(group, r->X, r->X, r->Y, ctx))
|
||||
return 0;
|
||||
|
||||
s->Z_is_one = 0;
|
||||
r->Z_is_one = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords.
|
||||
* http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3
|
||||
* s := r + s, r := 2r
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_step(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx)
|
||||
|| !group->meth->field_mul(group, s->X, r->X, s->Z, ctx)
|
||||
|| !group->meth->field_sqr(group, s->Y, r->Z, ctx)
|
||||
|| !group->meth->field_sqr(group, r->Z, r->X, ctx)
|
||||
|| !BN_GF2m_add(s->Z, r->Y, s->X)
|
||||
|| !group->meth->field_sqr(group, s->Z, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, s->X, r->Y, s->X, ctx)
|
||||
|| !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx)
|
||||
|| !BN_GF2m_add(s->X, s->X, r->Y)
|
||||
|| !group->meth->field_sqr(group, r->Y, r->Z, ctx)
|
||||
|| !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx)
|
||||
|| !group->meth->field_sqr(group, s->Y, s->Y, ctx)
|
||||
|| !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx)
|
||||
|| !BN_GF2m_add(r->X, r->Y, s->Y))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Recover affine (x,y) result from Lopez-Dahab r and s, affine p.
|
||||
* See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m)
|
||||
* without Precomputation" (Lopez and Dahab, CHES 1999),
|
||||
* Appendix Alg Mxy.
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *t0, *t1, *t2 = NULL;
|
||||
|
||||
if (BN_is_zero(r->Z))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
if (BN_is_zero(s->Z)) {
|
||||
if (!EC_POINT_copy(r, p)
|
||||
|| !EC_POINT_invert(group, r, ctx)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
t0 = BN_CTX_get(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t2 == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, t1, p->X, r->Z, ctx)
|
||||
|| !BN_GF2m_add(t1, r->X, t1)
|
||||
|| !group->meth->field_mul(group, t2, p->X, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, r->Z, r->X, t2, ctx)
|
||||
|| !BN_GF2m_add(t2, t2, s->X)
|
||||
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|
||||
|| !group->meth->field_sqr(group, t2, p->X, ctx)
|
||||
|| !BN_GF2m_add(t2, p->Y, t2)
|
||||
|| !group->meth->field_mul(group, t2, t2, t0, ctx)
|
||||
|| !BN_GF2m_add(t1, t2, t1)
|
||||
|| !group->meth->field_mul(group, t2, p->X, t0, ctx)
|
||||
|| !BN_GF2m_mod_inv(t2, t2, group->field, ctx)
|
||||
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|
||||
|| !group->meth->field_mul(group, r->X, r->Z, t2, ctx)
|
||||
|| !BN_GF2m_add(t2, p->X, r->X)
|
||||
|| !group->meth->field_mul(group, t2, t2, t1, ctx)
|
||||
|| !BN_GF2m_add(r->Y, p->Y, t2)
|
||||
|| !BN_one(r->Z))
|
||||
goto err;
|
||||
|
||||
r->Z_is_one = 1;
|
||||
|
||||
/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
|
||||
BN_set_negative(r->X, 0);
|
||||
BN_set_negative(r->Y, 0);
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, size_t num,
|
||||
const EC_POINT *points[],
|
||||
const BIGNUM *scalars[],
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
EC_POINT *t = NULL;
|
||||
|
||||
/*-
|
||||
* We limit use of the ladder only to the following cases:
|
||||
* - r := scalar * G
|
||||
* Fixed point mul: scalar != NULL && num == 0;
|
||||
* - r := scalars[0] * points[0]
|
||||
* Variable point mul: scalar == NULL && num == 1;
|
||||
* - r := scalar * G + scalars[0] * points[0]
|
||||
* used, e.g., in ECDSA verification: scalar != NULL && num == 1
|
||||
*
|
||||
* In any other case (num > 1) we use the default wNAF implementation.
|
||||
*
|
||||
* We also let the default implementation handle degenerate cases like group
|
||||
* order or cofactor set to 0.
|
||||
*/
|
||||
if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
|
||||
return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
|
||||
if (scalar != NULL && num == 0)
|
||||
/* Fixed point multiplication */
|
||||
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
|
||||
|
||||
if (scalar == NULL && num == 1)
|
||||
/* Variable point multiplication */
|
||||
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
|
||||
|
||||
/*-
|
||||
* Double point multiplication:
|
||||
* r := scalar * G + scalars[0] * points[0]
|
||||
*/
|
||||
|
||||
if ((t = EC_POINT_new(group)) == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
|
||||
|| !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
|
||||
|| !EC_POINT_add(group, r, t, r, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EC_POINT_free(t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const EC_METHOD *EC_GF2m_simple_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_characteristic_two_field,
|
||||
ec_GF2m_simple_group_init,
|
||||
ec_GF2m_simple_group_finish,
|
||||
ec_GF2m_simple_group_clear_finish,
|
||||
ec_GF2m_simple_group_copy,
|
||||
ec_GF2m_simple_group_set_curve,
|
||||
ec_GF2m_simple_group_get_curve,
|
||||
ec_GF2m_simple_group_get_degree,
|
||||
ec_group_simple_order_bits,
|
||||
ec_GF2m_simple_group_check_discriminant,
|
||||
ec_GF2m_simple_point_init,
|
||||
ec_GF2m_simple_point_finish,
|
||||
ec_GF2m_simple_point_clear_finish,
|
||||
ec_GF2m_simple_point_copy,
|
||||
ec_GF2m_simple_point_set_to_infinity,
|
||||
0, /* set_Jprojective_coordinates_GFp */
|
||||
0, /* get_Jprojective_coordinates_GFp */
|
||||
ec_GF2m_simple_point_set_affine_coordinates,
|
||||
ec_GF2m_simple_point_get_affine_coordinates,
|
||||
0, /* point_set_compressed_coordinates */
|
||||
0, /* point2oct */
|
||||
0, /* oct2point */
|
||||
ec_GF2m_simple_add,
|
||||
ec_GF2m_simple_dbl,
|
||||
ec_GF2m_simple_invert,
|
||||
ec_GF2m_simple_is_at_infinity,
|
||||
ec_GF2m_simple_is_on_curve,
|
||||
ec_GF2m_simple_cmp,
|
||||
ec_GF2m_simple_make_affine,
|
||||
ec_GF2m_simple_points_make_affine,
|
||||
ec_GF2m_simple_points_mul,
|
||||
0, /* precompute_mult */
|
||||
0, /* have_precompute_mult */
|
||||
ec_GF2m_simple_field_mul,
|
||||
ec_GF2m_simple_field_sqr,
|
||||
ec_GF2m_simple_field_div,
|
||||
0, /* field_encode */
|
||||
0, /* field_decode */
|
||||
0, /* field_set_to_one */
|
||||
ec_key_simple_priv2oct,
|
||||
ec_key_simple_oct2priv,
|
||||
0, /* set private */
|
||||
ec_key_simple_generate_key,
|
||||
ec_key_simple_check_key,
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0, /* blind_coordinates */
|
||||
ec_GF2m_simple_ladder_pre,
|
||||
ec_GF2m_simple_ladder_step,
|
||||
ec_GF2m_simple_ladder_post
|
||||
};
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
+15
-6
@@ -70,10 +70,16 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
"ec_GF2m_simple_group_check_discriminant"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0),
|
||||
"ec_GF2m_simple_group_set_curve"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_POST, 0),
|
||||
"ec_GF2m_simple_ladder_post"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_PRE, 0),
|
||||
"ec_GF2m_simple_ladder_pre"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_OCT2POINT, 0),
|
||||
"ec_GF2m_simple_oct2point"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT2OCT, 0),
|
||||
"ec_GF2m_simple_point2oct"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINTS_MUL, 0),
|
||||
"ec_GF2m_simple_points_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0),
|
||||
"ec_GF2m_simple_point_get_affine_coordinates"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
|
||||
@@ -191,6 +197,7 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0),
|
||||
"EC_POINTs_make_affine"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MUL, 0), "EC_POINTs_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_BN2POINT, 0), "EC_POINT_bn2point"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_CMP, 0), "EC_POINT_cmp"},
|
||||
@@ -226,6 +233,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_TO_INFINITY, 0),
|
||||
"EC_POINT_set_to_infinity"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_PRE_COMP_NEW, 0), "ec_pre_comp_new"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_SCALAR_MUL_LADDER, 0),
|
||||
"ec_scalar_mul_ladder"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_MUL, 0), "ec_wNAF_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_PRECOMPUTE_MULT, 0),
|
||||
"ec_wNAF_precompute_mult"},
|
||||
@@ -261,12 +270,6 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_KEYGEN, 0), "pkey_sm2_keygen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_PARAMGEN, 0), "pkey_sm2_paramgen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"},
|
||||
{0, NULL}
|
||||
};
|
||||
@@ -320,6 +323,9 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
"invalid trinomial basis"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KEYS_NOT_SET), "keys not set"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_POST_FAILURE), "ladder post failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_PRE_FAILURE), "ladder pre failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_STEP_FAILURE), "ladder step failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "missing parameters"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "missing private key"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NEED_NEW_SETUP_VALUES),
|
||||
@@ -339,6 +345,8 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_ARITHMETIC_FAILURE),
|
||||
"point arithmetic failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "point at infinity"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_COORDINATES_BLIND_FAILURE),
|
||||
"point coordinates blind failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE),
|
||||
"point is not on curve"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_RANDOM_NUMBER_GENERATION_FAILED),
|
||||
@@ -347,6 +355,7 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "slot full"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "unknown group"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "unknown order"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNSUPPORTED_FIELD), "unsupported field"},
|
||||
|
||||
@@ -178,6 +178,15 @@ struct ec_method_st {
|
||||
int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r,
|
||||
const BIGNUM *x, BN_CTX *);
|
||||
int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_pre)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_step)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_post)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -637,4 +646,76 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
|
||||
void X25519_public_from_private(uint8_t out_public_value[32],
|
||||
const uint8_t private_key[32]);
|
||||
|
||||
/*-
|
||||
* This functions computes a single point multiplication over the EC group,
|
||||
* using, at a high level, a Montgomery ladder with conditional swaps, with
|
||||
* various timing attack defenses.
|
||||
*
|
||||
* It performs either a fixed point multiplication
|
||||
* (scalar * generator)
|
||||
* when point is NULL, or a variable point multiplication
|
||||
* (scalar * point)
|
||||
* when point is not NULL.
|
||||
*
|
||||
* `scalar` cannot be NULL and should be in the range [0,n) otherwise all
|
||||
* constant time bets are off (where n is the cardinality of the EC group).
|
||||
*
|
||||
* This function expects `group->order` and `group->cardinality` to be well
|
||||
* defined and non-zero: it fails with an error code otherwise.
|
||||
*
|
||||
* NB: This says nothing about the constant-timeness of the ladder step
|
||||
* implementation (i.e., the default implementation is based on EC_POINT_add and
|
||||
* EC_POINT_dbl, which of course are not constant time themselves) or the
|
||||
* underlying multiprecision arithmetic.
|
||||
*
|
||||
* The product is stored in `r`.
|
||||
*
|
||||
* This is an internal function: callers are in charge of ensuring that the
|
||||
* input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
|
||||
*
|
||||
* Returns 1 on success, 0 otherwise.
|
||||
*/
|
||||
int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx);
|
||||
|
||||
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
|
||||
|
||||
static inline int ec_point_ladder_pre(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_pre != NULL)
|
||||
return group->meth->ladder_pre(group, r, s, p, ctx);
|
||||
|
||||
if (!EC_POINT_copy(s, p)
|
||||
|| !EC_POINT_dbl(group, r, s, ctx))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int ec_point_ladder_step(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_step != NULL)
|
||||
return group->meth->ladder_step(group, r, s, p, ctx);
|
||||
|
||||
if (!EC_POINT_add(group, s, r, s, ctx)
|
||||
|| !EC_POINT_dbl(group, r, r, ctx))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static inline int ec_point_ladder_post(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_post != NULL)
|
||||
return group->meth->ladder_post(group, r, s, p, ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
+31
-4
@@ -919,11 +919,38 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
size_t num, const EC_POINT *points[],
|
||||
const BIGNUM *scalars[], BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->mul == 0)
|
||||
/* use default */
|
||||
return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
int ret = 0;
|
||||
size_t i = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
|
||||
return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
||||
if ((scalar == NULL) && (num == 0)) {
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!ec_point_is_compat(points[i], group)) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (group->meth->mul != NULL)
|
||||
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
||||
else
|
||||
/* use default */
|
||||
ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
|
||||
|
||||
+114
-81
@@ -108,10 +108,9 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
|
||||
} while(0)
|
||||
|
||||
/*-
|
||||
* This functions computes (in constant time) a point multiplication over the
|
||||
* EC group.
|
||||
*
|
||||
* At a high level, it is Montgomery ladder with conditional swaps.
|
||||
* This functions computes a single point multiplication over the EC group,
|
||||
* using, at a high level, a Montgomery ladder with conditional swaps, with
|
||||
* various timing attack defenses.
|
||||
*
|
||||
* It performs either a fixed point multiplication
|
||||
* (scalar * generator)
|
||||
@@ -119,51 +118,85 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
|
||||
* (scalar * point)
|
||||
* when point is not NULL.
|
||||
*
|
||||
* scalar should be in the range [0,n) otherwise all constant time bets are off.
|
||||
* `scalar` cannot be NULL and should be in the range [0,n) otherwise all
|
||||
* constant time bets are off (where n is the cardinality of the EC group).
|
||||
*
|
||||
* NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
|
||||
* which of course are not constant time themselves.
|
||||
* This function expects `group->order` and `group->cardinality` to be well
|
||||
* defined and non-zero: it fails with an error code otherwise.
|
||||
*
|
||||
* The product is stored in r.
|
||||
* NB: This says nothing about the constant-timeness of the ladder step
|
||||
* implementation (i.e., the default implementation is based on EC_POINT_add and
|
||||
* EC_POINT_dbl, which of course are not constant time themselves) or the
|
||||
* underlying multiprecision arithmetic.
|
||||
*
|
||||
* The product is stored in `r`.
|
||||
*
|
||||
* This is an internal function: callers are in charge of ensuring that the
|
||||
* input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
|
||||
*
|
||||
* Returns 1 on success, 0 otherwise.
|
||||
*/
|
||||
static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
|
||||
EC_POINT *p = NULL;
|
||||
EC_POINT *s = NULL;
|
||||
BIGNUM *k = NULL;
|
||||
BIGNUM *lambda = NULL;
|
||||
BIGNUM *cardinality = NULL;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
|
||||
/* early exit if the input point is the point at infinity */
|
||||
if (point != NULL && EC_POINT_is_at_infinity(group, point))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
if (BN_is_zero(group->order)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER);
|
||||
return 0;
|
||||
}
|
||||
if (BN_is_zero(group->cofactor)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
s = EC_POINT_new(group);
|
||||
if (s == NULL)
|
||||
if (((p = EC_POINT_new(group)) == NULL)
|
||||
|| ((s = EC_POINT_new(group)) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
|
||||
if (point == NULL) {
|
||||
if (!EC_POINT_copy(s, group->generator))
|
||||
goto err;
|
||||
} else {
|
||||
if (!EC_POINT_copy(s, point))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (point == NULL) {
|
||||
if (!EC_POINT_copy(p, group->generator)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!EC_POINT_copy(p, point)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME);
|
||||
EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
|
||||
EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
|
||||
|
||||
cardinality = BN_CTX_get(ctx);
|
||||
lambda = BN_CTX_get(ctx);
|
||||
k = BN_CTX_get(ctx);
|
||||
if (k == NULL || !BN_mul(cardinality, group->order, group->cofactor, ctx))
|
||||
if (k == NULL) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Group cardinalities are often on a word boundary.
|
||||
@@ -174,11 +207,15 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
cardinality_bits = BN_num_bits(cardinality);
|
||||
group_top = bn_get_top(cardinality);
|
||||
if ((bn_wexpand(k, group_top + 1) == NULL)
|
||||
|| (bn_wexpand(lambda, group_top + 1) == NULL))
|
||||
|| (bn_wexpand(lambda, group_top + 1) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_copy(k, scalar))
|
||||
if (!BN_copy(k, scalar)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_set_flags(k, BN_FLG_CONSTTIME);
|
||||
|
||||
@@ -187,15 +224,21 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
* this is an unusual input, and we don't guarantee
|
||||
* constant-timeness
|
||||
*/
|
||||
if (!BN_nnmod(k, k, cardinality, ctx))
|
||||
if (!BN_nnmod(k, k, cardinality, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BN_add(lambda, k, cardinality))
|
||||
if (!BN_add(lambda, k, cardinality)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
BN_set_flags(lambda, BN_FLG_CONSTTIME);
|
||||
if (!BN_add(k, lambda, cardinality))
|
||||
if (!BN_add(k, lambda, cardinality)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* lambda := scalar + cardinality
|
||||
* k := scalar + 2*cardinality
|
||||
@@ -209,8 +252,13 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
|| (bn_wexpand(s->Z, group_top) == NULL)
|
||||
|| (bn_wexpand(r->X, group_top) == NULL)
|
||||
|| (bn_wexpand(r->Y, group_top) == NULL)
|
||||
|| (bn_wexpand(r->Z, group_top) == NULL))
|
||||
|| (bn_wexpand(r->Z, group_top) == NULL)
|
||||
|| (bn_wexpand(p->X, group_top) == NULL)
|
||||
|| (bn_wexpand(p->Y, group_top) == NULL)
|
||||
|| (bn_wexpand(p->Z, group_top) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Apply coordinate blinding for EC_POINT.
|
||||
@@ -220,19 +268,19 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
* success or if coordinate blinding is not implemented for this
|
||||
* group.
|
||||
*/
|
||||
if (!ec_point_blind_coordinates(group, s, ctx))
|
||||
if (!ec_point_blind_coordinates(group, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Initialize the Montgomery ladder */
|
||||
if (!ec_point_ladder_pre(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* top bit is a 1, in a fixed pos */
|
||||
if (!EC_POINT_copy(r, s))
|
||||
goto err;
|
||||
|
||||
EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!EC_POINT_dbl(group, s, s, ctx))
|
||||
goto err;
|
||||
|
||||
pbit = 0;
|
||||
pbit = 1;
|
||||
|
||||
#define EC_POINT_CSWAP(c, a, b, w, t) do { \
|
||||
BN_consttime_swap(c, (a)->X, (b)->X, w); \
|
||||
@@ -304,10 +352,12 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
for (i = cardinality_bits - 1; i >= 0; i--) {
|
||||
kbit = BN_is_bit_set(k, i) ^ pbit;
|
||||
EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
|
||||
if (!EC_POINT_add(group, s, r, s, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_dbl(group, r, r, ctx))
|
||||
|
||||
/* Perform a single step of the Montgomery ladder */
|
||||
if (!ec_point_ladder_step(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* pbit logic merges this cswap with that of the
|
||||
* next iteration
|
||||
@@ -318,12 +368,18 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
|
||||
#undef EC_POINT_CSWAP
|
||||
|
||||
/* Finalize ladder (and recover full point coordinates) */
|
||||
if (!ec_point_ladder_post(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EC_POINT_free(p);
|
||||
EC_POINT_free(s);
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(new_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -355,7 +411,6 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
const EC_POINT *generator = NULL;
|
||||
EC_POINT *tmp = NULL;
|
||||
size_t totalnum;
|
||||
@@ -380,56 +435,35 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
* precomputation is not available */
|
||||
int ret = 0;
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((scalar == NULL) && (num == 0)) {
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {
|
||||
/*-
|
||||
* Handle the common cases where the scalar is secret, enforcing a constant
|
||||
* time scalar multiplication algorithm.
|
||||
* Handle the common cases where the scalar is secret, enforcing a
|
||||
* scalar multiplication implementation based on a Montgomery ladder,
|
||||
* with various timing attack defenses.
|
||||
*/
|
||||
if ((scalar != NULL) && (num == 0)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * GeneratorPoint: this
|
||||
* codepath is reached most prominently by (ephemeral) key generation
|
||||
* of EC cryptosystems (i.e. ECDSA keygen and sign setup, ECDH
|
||||
* keygen/first half), where the scalar is always secret. This is why
|
||||
* we ignore if BN_FLG_CONSTTIME is actually set and we always call the
|
||||
* constant time version.
|
||||
* codepath is reached most prominently by (ephemeral) key
|
||||
* generation of EC cryptosystems (i.e. ECDSA keygen and sign setup,
|
||||
* ECDH keygen/first half), where the scalar is always secret. This
|
||||
* is why we ignore if BN_FLG_CONSTTIME is actually set and we
|
||||
* always call the ladder version.
|
||||
*/
|
||||
return ec_mul_consttime(group, r, scalar, NULL, ctx);
|
||||
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
|
||||
}
|
||||
if ((scalar == NULL) && (num == 1)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * GenericPoint: this codepath
|
||||
* is reached most prominently by the second half of ECDH, where the
|
||||
* secret scalar is multiplied by the peer's public point. To protect
|
||||
* the secret scalar, we ignore if BN_FLG_CONSTTIME is actually set and
|
||||
* we always call the constant time version.
|
||||
* In this case we want to compute scalar * VariablePoint: this
|
||||
* codepath is reached most prominently by the second half of ECDH,
|
||||
* where the secret scalar is multiplied by the peer's public point.
|
||||
* To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is
|
||||
* actually set and we always call the ladder version.
|
||||
*/
|
||||
return ec_mul_consttime(group, r, scalars[0], points[0], ctx);
|
||||
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!ec_point_is_compat(points[i], group)) {
|
||||
ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (scalar != NULL) {
|
||||
generator = EC_GROUP_get0_generator(group);
|
||||
if (generator == NULL) {
|
||||
@@ -736,7 +770,6 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_free(new_ctx);
|
||||
EC_POINT_free(tmp);
|
||||
OPENSSL_free(wsize);
|
||||
OPENSSL_free(wNAF_len);
|
||||
|
||||
+37
-94
@@ -10,9 +10,8 @@
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/ec.h>
|
||||
#include "internal/bn_int.h"
|
||||
#include "ec_lcl.h"
|
||||
|
||||
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
|
||||
@@ -53,13 +52,12 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx_in == NULL) {
|
||||
if ((ctx = ctx_in) == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
ctx = ctx_in;
|
||||
}
|
||||
|
||||
k = BN_new(); /* this value is later returned in *kinvp */
|
||||
r = BN_new(); /* this value is later returned in *rp */
|
||||
@@ -73,10 +71,6 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
goto err;
|
||||
}
|
||||
order = EC_GROUP_get0_order(group);
|
||||
if (order == NULL) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Preallocate space */
|
||||
order_bits = BN_num_bits(order);
|
||||
@@ -87,23 +81,23 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
|
||||
do {
|
||||
/* get random k */
|
||||
do
|
||||
do {
|
||||
if (dgst != NULL) {
|
||||
if (!BN_generate_dsa_nonce
|
||||
(k, order, EC_KEY_get0_private_key(eckey), dgst, dlen,
|
||||
ctx)) {
|
||||
if (!BN_generate_dsa_nonce(k, order,
|
||||
EC_KEY_get0_private_key(eckey),
|
||||
dgst, dlen, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP,
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!BN_priv_rand_range(k, order)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP,
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (BN_is_zero(k));
|
||||
} while (BN_is_zero(k));
|
||||
|
||||
/* compute r the x-coordinate of generator * k */
|
||||
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
|
||||
@@ -112,18 +106,16 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
}
|
||||
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
|
||||
NID_X9_62_prime_field) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp
|
||||
(group, tmp_point, X, NULL, ctx)) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X,
|
||||
NULL, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
else { /* NID_X9_62_characteristic_two_field */
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group,
|
||||
tmp_point, X, NULL,
|
||||
ctx)) {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X,
|
||||
NULL, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -133,8 +125,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (BN_is_zero(r));
|
||||
} while (BN_is_zero(r));
|
||||
|
||||
/* compute the inverse of k */
|
||||
if (!ec_group_do_inverse_ord(group, k, k, ctx)) {
|
||||
@@ -172,8 +163,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
EC_KEY *eckey)
|
||||
{
|
||||
int ok = 0, i;
|
||||
BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *blind = NULL;
|
||||
BIGNUM *blindm = NULL;
|
||||
BIGNUM *kinv = NULL, *s, *m = NULL;
|
||||
const BIGNUM *order, *ckinv;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_GROUP *group;
|
||||
@@ -206,27 +196,13 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
}
|
||||
s = ret->s;
|
||||
|
||||
ctx = BN_CTX_secure_new();
|
||||
if (ctx == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
m = BN_CTX_get(ctx);
|
||||
blind = BN_CTX_get(ctx);
|
||||
blindm = BN_CTX_get(ctx);
|
||||
if (blindm == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL
|
||||
|| (m = BN_new()) == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
order = EC_GROUP_get0_order(group);
|
||||
if (order == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
i = BN_num_bits(order);
|
||||
/*
|
||||
* Need to truncate digest if it is too long: first truncate whole bytes.
|
||||
@@ -237,7 +213,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
/* If still too long truncate remaining bits with a shift */
|
||||
/* If still too long, truncate remaining bits with a shift */
|
||||
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
@@ -258,59 +234,27 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
}
|
||||
|
||||
/*
|
||||
* The normal signature calculation is:
|
||||
*
|
||||
* s := k^-1 * (m + r * priv_key) mod order
|
||||
*
|
||||
* We will blind this to protect against side channel attacks
|
||||
*
|
||||
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod order
|
||||
* With only one multiplicant being in Montgomery domain
|
||||
* multiplication yields real result without post-conversion.
|
||||
* Also note that all operations but last are performed with
|
||||
* zero-padded vectors. Last operation, BN_mod_mul_montgomery
|
||||
* below, returns user-visible value with removed zero padding.
|
||||
*/
|
||||
|
||||
/* Generate a blinding value */
|
||||
do {
|
||||
if (!BN_priv_rand(blind, BN_num_bits(order) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
|
||||
goto err;
|
||||
} while (BN_is_zero(blind));
|
||||
BN_set_flags(blind, BN_FLG_CONSTTIME);
|
||||
BN_set_flags(blindm, BN_FLG_CONSTTIME);
|
||||
BN_set_flags(tmp, BN_FLG_CONSTTIME);
|
||||
|
||||
/* tmp := blind * priv_key * r mod order */
|
||||
if (!BN_mod_mul(tmp, blind, priv_key, order, ctx)) {
|
||||
if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
|
||||
|| !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(tmp, tmp, ret->r, order, ctx)) {
|
||||
if (!bn_mod_add_fixed_top(s, s, m, order)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* blindm := blind * m mod order */
|
||||
if (!BN_mod_mul(blindm, blind, m, order, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s : = (blind * priv_key * r) + (blind * m) mod order */
|
||||
if (!BN_mod_add_quick(s, tmp, blindm, order)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s := s * k^-1 mod order */
|
||||
if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s:= s * blind^-1 mod order */
|
||||
if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(s, s, blind, order, ctx)) {
|
||||
/*
|
||||
* |s| can still be larger than modulus, because |m| can be. In
|
||||
* such case we count on Montgomery reduction to tie it up.
|
||||
*/
|
||||
if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
|
||||
|| !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -324,11 +268,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES);
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/* s != 0 => we have a valid signature */
|
||||
break;
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
@@ -336,9 +280,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECDSA_SIG_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
BN_clear_free(m);
|
||||
BN_clear_free(kinv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,10 @@ const EC_METHOD *EC_GFp_mont_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -65,7 +65,10 @@ const EC_METHOD *EC_GFp_nist_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -292,7 +292,10 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1393,7 +1396,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int j;
|
||||
unsigned i;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -1410,9 +1412,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -1575,7 +1574,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_felems);
|
||||
|
||||
@@ -1821,7 +1821,12 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -2013,7 +2018,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int ret = 0;
|
||||
int j;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -2031,9 +2035,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -2202,7 +2203,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_smallfelems);
|
||||
|
||||
@@ -1660,7 +1660,10 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1852,7 +1855,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int ret = 0;
|
||||
int j;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -1869,9 +1871,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -2038,7 +2037,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_felems);
|
||||
|
||||
@@ -1139,12 +1139,10 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
const BIGNUM *scalars[], BN_CTX *ctx)
|
||||
{
|
||||
int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0;
|
||||
size_t j;
|
||||
unsigned char p_str[33] = { 0 };
|
||||
const PRECOMP256_ROW *preComputedTable = NULL;
|
||||
const NISTZ256_PRE_COMP *pre_comp = NULL;
|
||||
const EC_POINT *generator = NULL;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
const BIGNUM **new_scalars = NULL;
|
||||
const EC_POINT **new_points = NULL;
|
||||
unsigned int idx = 0;
|
||||
@@ -1162,27 +1160,6 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((scalar == NULL) && (num == 0))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
for (j = 0; j < num; j++) {
|
||||
if (!ec_point_is_compat(points[j], group)) {
|
||||
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
if (scalar) {
|
||||
@@ -1380,7 +1357,6 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(new_points);
|
||||
OPENSSL_free(new_scalars);
|
||||
return ret;
|
||||
@@ -1731,7 +1707,10 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -64,7 +64,10 @@ const EC_METHOD *EC_GFp_simple_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1418,4 +1421,3 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user