summaryrefslogtreecommitdiff
path: root/deps/openssl/openssl/crypto/ec
diff options
context:
space:
mode:
Diffstat (limited to 'deps/openssl/openssl/crypto/ec')
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv4.pl4
-rw-r--r--deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv8.pl311
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl42
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-ppc64.pl2382
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-sparcv9.pl8
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86.pl4
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl1874
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/x25519-ppc64.pl824
-rwxr-xr-xdeps/openssl/openssl/crypto/ec/asm/x25519-x86_64.pl1117
-rw-r--r--deps/openssl/openssl/crypto/ec/build.info18
-rw-r--r--deps/openssl/openssl/crypto/ec/curve25519.c2237
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/arch_32/arch_intrinsics.h27
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.c95
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.h60
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/curve448.c727
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/curve448_lcl.h38
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/curve448_tables.c475
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/curve448utils.h78
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/ed448.h195
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/eddsa.c346
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/f_generic.c204
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/field.h168
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/point_448.h301
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/scalar.c235
-rw-r--r--deps/openssl/openssl/crypto/ec/curve448/word.h81
-rw-r--r--deps/openssl/openssl/crypto/ec/ec2_mult.c418
-rw-r--r--deps/openssl/openssl/crypto/ec/ec2_oct.c29
-rw-r--r--deps/openssl/openssl/crypto/ec/ec2_smpl.c370
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_ameth.c62
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_asn1.c144
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_curve.c64
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_cvt.c21
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_err.c543
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_key.c57
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_lcl.h159
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_lib.c280
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_mult.c201
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_oct.c59
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_pmeth.c81
-rw-r--r--deps/openssl/openssl/crypto/ec/ec_print.c8
-rw-r--r--deps/openssl/openssl/crypto/ec/ecdh_kdf.c19
-rw-r--r--deps/openssl/openssl/crypto/ec/ecdh_ossl.c40
-rw-r--r--deps/openssl/openssl/crypto/ec/ecdsa_ossl.c97
-rw-r--r--deps/openssl/openssl/crypto/ec/eck_prn.c40
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_mont.c13
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_nist.c13
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_nistp224.c77
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_nistp256.c48
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_nistp521.c67
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_nistz256.c274
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_oct.c22
-rw-r--r--deps/openssl/openssl/crypto/ec/ecp_smpl.c246
-rw-r--r--deps/openssl/openssl/crypto/ec/ecx_meth.c641
53 files changed, 14069 insertions, 1875 deletions
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv4.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv4.pl
index 4eb4c68977..83abbdd895 100755
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv4.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv4.pl
@@ -233,7 +233,7 @@ __ecp_nistz256_add:
@ if a+b >= modulus, subtract modulus.
@
@ But since comparison implies subtraction, we subtract
- @ modulus and then add it back if subraction borrowed.
+ @ modulus and then add it back if subtraction borrowed.
subs $a0,$a0,#-1
sbcs $a1,$a1,#-1
@@ -1222,7 +1222,7 @@ __ecp_nistz256_add_self:
@ if a+b >= modulus, subtract modulus.
@
@ But since comparison implies subtraction, we subtract
- @ modulus and then add it back if subraction borrowed.
+ @ modulus and then add it back if subtraction borrowed.
subs $a0,$a0,#-1
sbcs $a1,$a1,#-1
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv8.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv8.pl
index 2a39675bfd..1361cb395f 100644
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv8.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-armv8.pl
@@ -22,11 +22,10 @@
# http://eprint.iacr.org/2013/816.
#
# with/without -DECP_NISTZ256_ASM
-# Apple A7 +120-360%
-# Cortex-A53 +120-400%
-# Cortex-A57 +120-350%
-# X-Gene +200-330%
-# Denver +140-400%
+# Apple A7 +190-360%
+# Cortex-A53 +190-400%
+# Cortex-A57 +190-350%
+# Denver +230-400%
#
# Ranges denote minimum and maximum improvement coefficients depending
# on benchmark. Lower coefficients are for ECDSA sign, server-side
@@ -109,6 +108,10 @@ $code.=<<___;
.quad 0x0000000000000001,0xffffffff00000000,0xffffffffffffffff,0x00000000fffffffe
.Lone:
.quad 1,0,0,0
+.Lord:
+.quad 0xf3b9cac2fc632551,0xbce6faada7179e84,0xffffffffffffffff,0xffffffff00000000
+.LordK:
+.quad 0xccd1c8aaee00bc4f
.asciz "ECP_NISTZ256 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
// void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
@@ -660,7 +663,7 @@ __ecp_nistz256_div_by_2:
adc $ap,xzr,xzr // zap $ap
tst $acc0,#1 // is a even?
- csel $acc0,$acc0,$t0,eq // ret = even ? a : a+modulus
+ csel $acc0,$acc0,$t0,eq // ret = even ? a : a+modulus
csel $acc1,$acc1,$t1,eq
csel $acc2,$acc2,$t2,eq
csel $acc3,$acc3,$t3,eq
@@ -1309,6 +1312,302 @@ $code.=<<___;
ret
.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine
___
+}
+if (1) {
+my ($ord0,$ord1) = ($poly1,$poly3);
+my ($ord2,$ord3,$ordk,$t4) = map("x$_",(21..24));
+my $acc7 = $bi;
+
+$code.=<<___;
+////////////////////////////////////////////////////////////////////////
+// void ecp_nistz256_ord_mul_mont(uint64_t res[4], uint64_t a[4],
+// uint64_t b[4]);
+.globl ecp_nistz256_ord_mul_mont
+.type ecp_nistz256_ord_mul_mont,%function
+.align 4
+ecp_nistz256_ord_mul_mont:
+ stp x29,x30,[sp,#-64]!
+ add x29,sp,#0
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+
+ adr $ordk,.Lord
+ ldr $bi,[$bp] // bp[0]
+ ldp $a0,$a1,[$ap]
+ ldp $a2,$a3,[$ap,#16]
+
+ ldp $ord0,$ord1,[$ordk,#0]
+ ldp $ord2,$ord3,[$ordk,#16]
+ ldr $ordk,[$ordk,#32]
+
+ mul $acc0,$a0,$bi // a[0]*b[0]
+ umulh $t0,$a0,$bi
+
+ mul $acc1,$a1,$bi // a[1]*b[0]
+ umulh $t1,$a1,$bi
+
+ mul $acc2,$a2,$bi // a[2]*b[0]
+ umulh $t2,$a2,$bi
+
+ mul $acc3,$a3,$bi // a[3]*b[0]
+ umulh $acc4,$a3,$bi
+
+ mul $t4,$acc0,$ordk
+
+ adds $acc1,$acc1,$t0 // accumulate high parts of multiplication
+ adcs $acc2,$acc2,$t1
+ adcs $acc3,$acc3,$t2
+ adc $acc4,$acc4,xzr
+ mov $acc5,xzr
+___
+for ($i=1;$i<4;$i++) {
+ ################################################################
+ # ffff0000.ffffffff.yyyyyyyy.zzzzzzzz
+ # * abcdefgh
+ # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
+ #
+ # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we
+ # rewrite above as:
+ #
+ # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
+ # - 0000abcd.efgh0000.abcdefgh.00000000.00000000
+ # + abcdefgh.abcdefgh.yzayzbyz.cyzdyzey.zfyzgyzh
+$code.=<<___;
+ ldr $bi,[$bp,#8*$i] // b[i]
+
+ lsl $t0,$t4,#32
+ subs $acc2,$acc2,$t4
+ lsr $t1,$t4,#32
+ sbcs $acc3,$acc3,$t0
+ sbcs $acc4,$acc4,$t1
+ sbc $acc5,$acc5,xzr
+
+ subs xzr,$acc0,#1
+ umulh $t1,$ord0,$t4
+ mul $t2,$ord1,$t4
+ umulh $t3,$ord1,$t4
+
+ adcs $t2,$t2,$t1
+ mul $t0,$a0,$bi
+ adc $t3,$t3,xzr
+ mul $t1,$a1,$bi
+
+ adds $acc0,$acc1,$t2
+ mul $t2,$a2,$bi
+ adcs $acc1,$acc2,$t3
+ mul $t3,$a3,$bi
+ adcs $acc2,$acc3,$t4
+ adcs $acc3,$acc4,$t4
+ adc $acc4,$acc5,xzr
+
+ adds $acc0,$acc0,$t0 // accumulate low parts
+ umulh $t0,$a0,$bi
+ adcs $acc1,$acc1,$t1
+ umulh $t1,$a1,$bi
+ adcs $acc2,$acc2,$t2
+ umulh $t2,$a2,$bi
+ adcs $acc3,$acc3,$t3
+ umulh $t3,$a3,$bi
+ adc $acc4,$acc4,xzr
+ mul $t4,$acc0,$ordk
+ adds $acc1,$acc1,$t0 // accumulate high parts
+ adcs $acc2,$acc2,$t1
+ adcs $acc3,$acc3,$t2
+ adcs $acc4,$acc4,$t3
+ adc $acc5,xzr,xzr
+___
+}
+$code.=<<___;
+ lsl $t0,$t4,#32 // last reduction
+ subs $acc2,$acc2,$t4
+ lsr $t1,$t4,#32
+ sbcs $acc3,$acc3,$t0
+ sbcs $acc4,$acc4,$t1
+ sbc $acc5,$acc5,xzr
+
+ subs xzr,$acc0,#1
+ umulh $t1,$ord0,$t4
+ mul $t2,$ord1,$t4
+ umulh $t3,$ord1,$t4
+
+ adcs $t2,$t2,$t1
+ adc $t3,$t3,xzr
+
+ adds $acc0,$acc1,$t2
+ adcs $acc1,$acc2,$t3
+ adcs $acc2,$acc3,$t4
+ adcs $acc3,$acc4,$t4
+ adc $acc4,$acc5,xzr
+
+ subs $t0,$acc0,$ord0 // ret -= modulus
+ sbcs $t1,$acc1,$ord1
+ sbcs $t2,$acc2,$ord2
+ sbcs $t3,$acc3,$ord3
+ sbcs xzr,$acc4,xzr
+
+ csel $acc0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus
+ csel $acc1,$acc1,$t1,lo
+ csel $acc2,$acc2,$t2,lo
+ stp $acc0,$acc1,[$rp]
+ csel $acc3,$acc3,$t3,lo
+ stp $acc2,$acc3,[$rp,#16]
+
+ ldp x19,x20,[sp,#16]
+ ldp x21,x22,[sp,#32]
+ ldp x23,x24,[sp,#48]
+ ldr x29,[sp],#64
+ ret
+.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont
+
+////////////////////////////////////////////////////////////////////////
+// void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
+// int rep);
+.globl ecp_nistz256_ord_sqr_mont
+.type ecp_nistz256_ord_sqr_mont,%function
+.align 4
+ecp_nistz256_ord_sqr_mont:
+ stp x29,x30,[sp,#-64]!
+ add x29,sp,#0
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+
+ adr $ordk,.Lord
+ ldp $a0,$a1,[$ap]
+ ldp $a2,$a3,[$ap,#16]
+
+ ldp $ord0,$ord1,[$ordk,#0]
+ ldp $ord2,$ord3,[$ordk,#16]
+ ldr $ordk,[$ordk,#32]
+ b .Loop_ord_sqr
+
+.align 4
+.Loop_ord_sqr:
+ sub $bp,$bp,#1
+ ////////////////////////////////////////////////////////////////
+ // | | | | | |a1*a0| |
+ // | | | | |a2*a0| | |
+ // | |a3*a2|a3*a0| | | |
+ // | | | |a2*a1| | | |
+ // | | |a3*a1| | | | |
+ // *| | | | | | | | 2|
+ // +|a3*a3|a2*a2|a1*a1|a0*a0|
+ // |--+--+--+--+--+--+--+--|
+ // |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx
+ //
+ // "can't overflow" below mark carrying into high part of
+ // multiplication result, which can't overflow, because it
+ // can never be all ones.
+
+ mul $acc1,$a1,$a0 // a[1]*a[0]
+ umulh $t1,$a1,$a0
+ mul $acc2,$a2,$a0 // a[2]*a[0]
+ umulh $t2,$a2,$a0
+ mul $acc3,$a3,$a0 // a[3]*a[0]
+ umulh $acc4,$a3,$a0
+
+ adds $acc2,$acc2,$t1 // accumulate high parts of multiplication
+ mul $t0,$a2,$a1 // a[2]*a[1]
+ umulh $t1,$a2,$a1
+ adcs $acc3,$acc3,$t2
+ mul $t2,$a3,$a1 // a[3]*a[1]
+ umulh $t3,$a3,$a1
+ adc $acc4,$acc4,xzr // can't overflow
+
+ mul $acc5,$a3,$a2 // a[3]*a[2]
+ umulh $acc6,$a3,$a2
+
+ adds $t1,$t1,$t2 // accumulate high parts of multiplication
+ mul $acc0,$a0,$a0 // a[0]*a[0]
+ adc $t2,$t3,xzr // can't overflow
+
+ adds $acc3,$acc3,$t0 // accumulate low parts of multiplication
+ umulh $a0,$a0,$a0
+ adcs $acc4,$acc4,$t1
+ mul $t1,$a1,$a1 // a[1]*a[1]
+ adcs $acc5,$acc5,$t2
+ umulh $a1,$a1,$a1
+ adc $acc6,$acc6,xzr // can't overflow
+
+ adds $acc1,$acc1,$acc1 // acc[1-6]*=2
+ mul $t2,$a2,$a2 // a[2]*a[2]
+ adcs $acc2,$acc2,$acc2
+ umulh $a2,$a2,$a2
+ adcs $acc3,$acc3,$acc3
+ mul $t3,$a3,$a3 // a[3]*a[3]
+ adcs $acc4,$acc4,$acc4
+ umulh $a3,$a3,$a3
+ adcs $acc5,$acc5,$acc5
+ adcs $acc6,$acc6,$acc6
+ adc $acc7,xzr,xzr
+
+ adds $acc1,$acc1,$a0 // +a[i]*a[i]
+ mul $t4,$acc0,$ordk
+ adcs $acc2,$acc2,$t1
+ adcs $acc3,$acc3,$a1
+ adcs $acc4,$acc4,$t2
+ adcs $acc5,$acc5,$a2
+ adcs $acc6,$acc6,$t3
+ adc $acc7,$acc7,$a3
+___
+for($i=0; $i<4; $i++) { # reductions
+$code.=<<___;
+ subs xzr,$acc0,#1
+ umulh $t1,$ord0,$t4
+ mul $t2,$ord1,$t4
+ umulh $t3,$ord1,$t4
+
+ adcs $t2,$t2,$t1
+ adc $t3,$t3,xzr
+
+ adds $acc0,$acc1,$t2
+ adcs $acc1,$acc2,$t3
+ adcs $acc2,$acc3,$t4
+ adc $acc3,xzr,$t4 // can't overflow
+___
+$code.=<<___ if ($i<3);
+ mul $t3,$acc0,$ordk
+___
+$code.=<<___;
+ lsl $t0,$t4,#32
+ subs $acc1,$acc1,$t4
+ lsr $t1,$t4,#32
+ sbcs $acc2,$acc2,$t0
+ sbc $acc3,$acc3,$t1 // can't borrow
+___
+ ($t3,$t4) = ($t4,$t3);
+}
+$code.=<<___;
+ adds $acc0,$acc0,$acc4 // accumulate upper half
+ adcs $acc1,$acc1,$acc5
+ adcs $acc2,$acc2,$acc6
+ adcs $acc3,$acc3,$acc7
+ adc $acc4,xzr,xzr
+
+ subs $t0,$acc0,$ord0 // ret -= modulus
+ sbcs $t1,$acc1,$ord1
+ sbcs $t2,$acc2,$ord2
+ sbcs $t3,$acc3,$ord3
+ sbcs xzr,$acc4,xzr
+
+ csel $a0,$acc0,$t0,lo // ret = borrow ? ret : ret-modulus
+ csel $a1,$acc1,$t1,lo
+ csel $a2,$acc2,$t2,lo
+ csel $a3,$acc3,$t3,lo
+
+ cbnz $bp,.Loop_ord_sqr
+
+ stp $a0,$a1,[$rp]
+ stp $a2,$a3,[$rp,#16]
+
+ ldp x19,x20,[sp,#16]
+ ldp x21,x22,[sp,#32]
+ ldp x23,x24,[sp,#48]
+ ldr x29,[sp],#64
+ ret
+.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont
+___
} }
########################################################################
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl
index edd7d01281..794e56a082 100755
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl
@@ -1,39 +1,19 @@
#! /usr/bin/env perl
# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright (c) 2014, Intel Corporation. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-
-
-##############################################################################
-# #
-# Copyright 2014 Intel Corporation #
-# #
-# Licensed under the Apache License, Version 2.0 (the "License"); #
-# you may not use this file except in compliance with the License. #
-# You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-# Unless required by applicable law or agreed to in writing, software #
-# distributed under the License is distributed on an "AS IS" BASIS, #
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-# See the License for the specific language governing permissions and #
-# limitations under the License. #
-# #
-##############################################################################
-# #
-# Developers and authors: #
-# Shay Gueron (1, 2), and Vlad Krasnov (1) #
-# (1) Intel Corporation, Israel Development Center #
-# (2) University of Haifa #
-# Reference: #
-# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with#
-# 256 Bit Primes" #
-# #
-##############################################################################
+#
+# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
+# (1) Intel Corporation, Israel Development Center, Haifa, Israel
+# (2) University of Haifa, Israel
+#
+# Reference:
+# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
+# 256 Bit Primes"
$flavour = shift;
$output = shift;
@@ -157,7 +137,7 @@ ___
{
# This function receives a pointer to an array of four affine points
-# (X, Y, <1>) and rearanges the data for AVX2 execution, while
+# (X, Y, <1>) and rearranges the data for AVX2 execution, while
# converting it to 2^29 radix redundant form
my ($X0,$X1,$X2,$X3, $Y0,$Y1,$Y2,$Y3,
@@ -309,7 +289,7 @@ ___
{
################################################################################
# This function receives a pointer to an array of four AVX2 formatted points
-# (X, Y, Z) convert the data to normal representation, and rearanges the data
+# (X, Y, Z) convert the data to normal representation, and rearranges the data
my ($D0,$D1,$D2,$D3, $D4,$D5,$D6,$D7, $D8)=map("%ymm$_",(0..8));
my ($T0,$T1,$T2,$T3, $T4,$T5,$T6)=map("%ymm$_",(9..15));
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-ppc64.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-ppc64.pl
new file mode 100755
index 0000000000..984c7f2050
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-ppc64.pl
@@ -0,0 +1,2382 @@
+#! /usr/bin/env perl
+# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# ECP_NISTZ256 module for PPC64.
+#
+# August 2016.
+#
+# Original ECP_NISTZ256 submission targeting x86_64 is detailed in
+# http://eprint.iacr.org/2013/816.
+#
+# with/without -DECP_NISTZ256_ASM
+# POWER7 +260-530%
+# POWER8 +220-340%
+
+$flavour = shift;
+while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my $sp="r1";
+
+{
+my ($rp,$ap,$bp,$bi,$acc0,$acc1,$acc2,$acc3,$poly1,$poly3,
+ $acc4,$acc5,$a0,$a1,$a2,$a3,$t0,$t1,$t2,$t3) =
+ map("r$_",(3..12,22..31));
+
+my ($acc6,$acc7)=($bp,$bi); # used in __ecp_nistz256_sqr_mont
+
+$code.=<<___;
+.machine "any"
+.text
+___
+########################################################################
+# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7
+#
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+open TABLE,"<ecp_nistz256_table.c" or
+open TABLE,"<${dir}../ecp_nistz256_table.c" or
+die "failed to open ecp_nistz256_table.c:",$!;
+
+use integer;
+
+foreach(<TABLE>) {
+ s/TOBN\(\s*(0x[0-9a-f]+),\s*(0x[0-9a-f]+)\s*\)/push @arr,hex($2),hex($1)/geo;
+}
+close TABLE;
+
+# See ecp_nistz256_table.c for explanation for why it's 64*16*37.
+# 64*16*37-1 is because $#arr returns last valid index or @arr, not
+# amount of elements.
+die "insane number of elements" if ($#arr != 64*16*37-1);
+
+$code.=<<___;
+.type ecp_nistz256_precomputed,\@object
+.globl ecp_nistz256_precomputed
+.align 12
+ecp_nistz256_precomputed:
+___
+########################################################################
+# this conversion smashes P256_POINT_AFFINE by individual bytes with
+# 64 byte interval, similar to
+# 1111222233334444
+# 1234123412341234
+for(1..37) {
+ @tbl = splice(@arr,0,64*16);
+ for($i=0;$i<64;$i++) {
+ undef @line;
+ for($j=0;$j<64;$j++) {
+ push @line,(@tbl[$j*16+$i/4]>>(($i%4)*8))&0xff;
+ }
+ $code.=".byte\t";
+ $code.=join(',',map { sprintf "0x%02x",$_} @line);
+ $code.="\n";
+ }
+}
+
+$code.=<<___;
+.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed
+.asciz "ECP_NISTZ256 for PPC64, CRYPTOGAMS by <appro\@openssl.org>"
+
+# void ecp_nistz256_mul_mont(BN_ULONG x0[4],const BN_ULONG x1[4],
+# const BN_ULONG x2[4]);
+.globl ecp_nistz256_mul_mont
+.align 5
+ecp_nistz256_mul_mont:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r22,48($sp)
+ std r23,56($sp)
+ std r24,64($sp)
+ std r25,72($sp)
+ std r26,80($sp)
+ std r27,88($sp)
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $a0,0($ap)
+ ld $bi,0($bp)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_mul_mont
+
+ mtlr r0
+ ld r22,48($sp)
+ ld r23,56($sp)
+ ld r24,64($sp)
+ ld r25,72($sp)
+ ld r26,80($sp)
+ ld r27,88($sp)
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,10,3,0
+ .long 0
+.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont
+
+# void ecp_nistz256_sqr_mont(BN_ULONG x0[4],const BN_ULONG x1[4]);
+.globl ecp_nistz256_sqr_mont
+.align 4
+ecp_nistz256_sqr_mont:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r22,48($sp)
+ std r23,56($sp)
+ std r24,64($sp)
+ std r25,72($sp)
+ std r26,80($sp)
+ std r27,88($sp)
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_sqr_mont
+
+ mtlr r0
+ ld r22,48($sp)
+ ld r23,56($sp)
+ ld r24,64($sp)
+ ld r25,72($sp)
+ ld r26,80($sp)
+ ld r27,88($sp)
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,10,2,0
+ .long 0
+.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont
+
+# void ecp_nistz256_add(BN_ULONG x0[4],const BN_ULONG x1[4],
+# const BN_ULONG x2[4]);
+.globl ecp_nistz256_add
+.align 4
+ecp_nistz256_add:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $acc0,0($ap)
+ ld $t0, 0($bp)
+ ld $acc1,8($ap)
+ ld $t1, 8($bp)
+ ld $acc2,16($ap)
+ ld $t2, 16($bp)
+ ld $acc3,24($ap)
+ ld $t3, 24($bp)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_add
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,3,0
+ .long 0
+.size ecp_nistz256_add,.-ecp_nistz256_add
+
+# void ecp_nistz256_div_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]);
+.globl ecp_nistz256_div_by_2
+.align 4
+ecp_nistz256_div_by_2:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $acc0,0($ap)
+ ld $acc1,8($ap)
+ ld $acc2,16($ap)
+ ld $acc3,24($ap)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_div_by_2
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,2,0
+ .long 0
+.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2
+
+# void ecp_nistz256_mul_by_2(BN_ULONG x0[4],const BN_ULONG x1[4]);
+.globl ecp_nistz256_mul_by_2
+.align 4
+ecp_nistz256_mul_by_2:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $acc0,0($ap)
+ ld $acc1,8($ap)
+ ld $acc2,16($ap)
+ ld $acc3,24($ap)
+
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_add # ret = a+a // 2*a
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,3,0
+ .long 0
+.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
+
+# void ecp_nistz256_mul_by_3(BN_ULONG x0[4],const BN_ULONG x1[4]);
+.globl ecp_nistz256_mul_by_3
+.align 4
+ecp_nistz256_mul_by_3:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $acc0,0($ap)
+ ld $acc1,8($ap)
+ ld $acc2,16($ap)
+ ld $acc3,24($ap)
+
+ mr $t0,$acc0
+ std $acc0,64($sp)
+ mr $t1,$acc1
+ std $acc1,72($sp)
+ mr $t2,$acc2
+ std $acc2,80($sp)
+ mr $t3,$acc3
+ std $acc3,88($sp)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_add # ret = a+a // 2*a
+
+ ld $t0,64($sp)
+ ld $t1,72($sp)
+ ld $t2,80($sp)
+ ld $t3,88($sp)
+
+ bl __ecp_nistz256_add # ret += a // 2*a+a=3*a
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,2,0
+ .long 0
+.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3
+
+# void ecp_nistz256_sub(BN_ULONG x0[4],const BN_ULONG x1[4],
+# const BN_ULONG x2[4]);
+.globl ecp_nistz256_sub
+.align 4
+ecp_nistz256_sub:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ ld $acc0,0($ap)
+ ld $acc1,8($ap)
+ ld $acc2,16($ap)
+ ld $acc3,24($ap)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_sub_from
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,3,0
+ .long 0
+.size ecp_nistz256_sub,.-ecp_nistz256_sub
+
+# void ecp_nistz256_neg(BN_ULONG x0[4],const BN_ULONG x1[4]);
+.globl ecp_nistz256_neg
+.align 4
+ecp_nistz256_neg:
+ stdu $sp,-128($sp)
+ mflr r0
+ std r28,96($sp)
+ std r29,104($sp)
+ std r30,112($sp)
+ std r31,120($sp)
+
+ mr $bp,$ap
+ li $acc0,0
+ li $acc1,0
+ li $acc2,0
+ li $acc3,0
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ bl __ecp_nistz256_sub_from
+
+ mtlr r0
+ ld r28,96($sp)
+ ld r29,104($sp)
+ ld r30,112($sp)
+ ld r31,120($sp)
+ addi $sp,$sp,128
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,4,2,0
+ .long 0
+.size ecp_nistz256_neg,.-ecp_nistz256_neg
+
+# note that __ecp_nistz256_mul_mont expects a[0-3] input pre-loaded
+# to $a0-$a3 and b[0] - to $bi
+.type __ecp_nistz256_mul_mont,\@function
+.align 4
+__ecp_nistz256_mul_mont:
+ mulld $acc0,$a0,$bi # a[0]*b[0]
+ mulhdu $t0,$a0,$bi
+
+ mulld $acc1,$a1,$bi # a[1]*b[0]
+ mulhdu $t1,$a1,$bi
+
+ mulld $acc2,$a2,$bi # a[2]*b[0]
+ mulhdu $t2,$a2,$bi
+
+ mulld $acc3,$a3,$bi # a[3]*b[0]
+ mulhdu $t3,$a3,$bi
+ ld $bi,8($bp) # b[1]
+
+ addc $acc1,$acc1,$t0 # accumulate high parts of multiplication
+ sldi $t0,$acc0,32
+ adde $acc2,$acc2,$t1
+ srdi $t1,$acc0,32
+ adde $acc3,$acc3,$t2
+ addze $acc4,$t3
+ li $acc5,0
+___
+for($i=1;$i<4;$i++) {
+ ################################################################
+ # Reduction iteration is normally performed by accumulating
+ # result of multiplication of modulus by "magic" digit [and
+ # omitting least significant word, which is guaranteed to
+ # be 0], but thanks to special form of modulus and "magic"
+ # digit being equal to least significant word, it can be
+ # performed with additions and subtractions alone. Indeed:
+ #
+ # ffff0001.00000000.0000ffff.ffffffff
+ # * abcdefgh
+ # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh
+ #
+ # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we
+ # rewrite above as:
+ #
+ # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.abcdefgh
+ # + abcdefgh.abcdefgh.0000abcd.efgh0000.00000000
+ # - 0000abcd.efgh0000.00000000.00000000.abcdefgh
+ #
+ # or marking redundant operations:
+ #
+ # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.--------
+ # + abcdefgh.abcdefgh.0000abcd.efgh0000.--------
+ # - 0000abcd.efgh0000.--------.--------.--------
+
+$code.=<<___;
+ subfc $t2,$t0,$acc0 # "*0xffff0001"
+ subfe $t3,$t1,$acc0
+ addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0]
+ adde $acc1,$acc2,$t1
+ adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001
+ adde $acc3,$acc4,$t3
+ addze $acc4,$acc5
+
+ mulld $t0,$a0,$bi # lo(a[0]*b[i])
+ mulld $t1,$a1,$bi # lo(a[1]*b[i])
+ mulld $t2,$a2,$bi # lo(a[2]*b[i])
+ mulld $t3,$a3,$bi # lo(a[3]*b[i])
+ addc $acc0,$acc0,$t0 # accumulate low parts of multiplication
+ mulhdu $t0,$a0,$bi # hi(a[0]*b[i])
+ adde $acc1,$acc1,$t1
+ mulhdu $t1,$a1,$bi # hi(a[1]*b[i])
+ adde $acc2,$acc2,$t2
+ mulhdu $t2,$a2,$bi # hi(a[2]*b[i])
+ adde $acc3,$acc3,$t3
+ mulhdu $t3,$a3,$bi # hi(a[3]*b[i])
+ addze $acc4,$acc4
+___
+$code.=<<___ if ($i<3);
+ ld $bi,8*($i+1)($bp) # b[$i+1]
+___
+$code.=<<___;
+ addc $acc1,$acc1,$t0 # accumulate high parts of multiplication
+ sldi $t0,$acc0,32
+ adde $acc2,$acc2,$t1
+ srdi $t1,$acc0,32
+ adde $acc3,$acc3,$t2
+ adde $acc4,$acc4,$t3
+ li $acc5,0
+ addze $acc5,$acc5
+___
+}
+$code.=<<___;
+ # last reduction
+ subfc $t2,$t0,$acc0 # "*0xffff0001"
+ subfe $t3,$t1,$acc0
+ addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0]
+ adde $acc1,$acc2,$t1
+ adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001
+ adde $acc3,$acc4,$t3
+ addze $acc4,$acc5
+
+ li $t2,0
+ addic $acc0,$acc0,1 # ret -= modulus
+ subfe $acc1,$poly1,$acc1
+ subfe $acc2,$t2,$acc2
+ subfe $acc3,$poly3,$acc3
+ subfe $acc4,$t2,$acc4
+
+ addc $acc0,$acc0,$acc4 # ret += modulus if borrow
+ and $t1,$poly1,$acc4
+ and $t3,$poly3,$acc4
+ adde $acc1,$acc1,$t1
+ addze $acc2,$acc2
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,1,0
+ .long 0
+.size __ecp_nistz256_mul_mont,.-__ecp_nistz256_mul_mont
+
+# note that __ecp_nistz256_sqr_mont expects a[0-3] input pre-loaded
+# to $a0-$a3
+.type __ecp_nistz256_sqr_mont,\@function
+.align 4
+__ecp_nistz256_sqr_mont:
+ ################################################################
+ # | | | | | |a1*a0| |
+ # | | | | |a2*a0| | |
+ # | |a3*a2|a3*a0| | | |
+ # | | | |a2*a1| | | |
+ # | | |a3*a1| | | | |
+ # *| | | | | | | | 2|
+ # +|a3*a3|a2*a2|a1*a1|a0*a0|
+ # |--+--+--+--+--+--+--+--|
+ # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx
+ #
+ # "can't overflow" below mark carrying into high part of
+ # multiplication result, which can't overflow, because it
+ # can never be all ones.
+
+ mulld $acc1,$a1,$a0 # a[1]*a[0]
+ mulhdu $t1,$a1,$a0
+ mulld $acc2,$a2,$a0 # a[2]*a[0]
+ mulhdu $t2,$a2,$a0
+ mulld $acc3,$a3,$a0 # a[3]*a[0]
+ mulhdu $acc4,$a3,$a0
+
+ addc $acc2,$acc2,$t1 # accumulate high parts of multiplication
+ mulld $t0,$a2,$a1 # a[2]*a[1]
+ mulhdu $t1,$a2,$a1
+ adde $acc3,$acc3,$t2
+ mulld $t2,$a3,$a1 # a[3]*a[1]
+ mulhdu $t3,$a3,$a1
+ addze $acc4,$acc4 # can't overflow
+
+ mulld $acc5,$a3,$a2 # a[3]*a[2]
+ mulhdu $acc6,$a3,$a2
+
+ addc $t1,$t1,$t2 # accumulate high parts of multiplication
+ addze $t2,$t3 # can't overflow
+
+ addc $acc3,$acc3,$t0 # accumulate low parts of multiplication
+ adde $acc4,$acc4,$t1
+ adde $acc5,$acc5,$t2
+ addze $acc6,$acc6 # can't overflow
+
+ addc $acc1,$acc1,$acc1 # acc[1-6]*=2
+ adde $acc2,$acc2,$acc2
+ adde $acc3,$acc3,$acc3
+ adde $acc4,$acc4,$acc4
+ adde $acc5,$acc5,$acc5
+ adde $acc6,$acc6,$acc6
+ li $acc7,0
+ addze $acc7,$acc7
+
+ mulld $acc0,$a0,$a0 # a[0]*a[0]
+ mulhdu $a0,$a0,$a0
+ mulld $t1,$a1,$a1 # a[1]*a[1]
+ mulhdu $a1,$a1,$a1
+ mulld $t2,$a2,$a2 # a[2]*a[2]
+ mulhdu $a2,$a2,$a2
+ mulld $t3,$a3,$a3 # a[3]*a[3]
+ mulhdu $a3,$a3,$a3
+ addc $acc1,$acc1,$a0 # +a[i]*a[i]
+ sldi $t0,$acc0,32
+ adde $acc2,$acc2,$t1
+ srdi $t1,$acc0,32
+ adde $acc3,$acc3,$a1
+ adde $acc4,$acc4,$t2
+ adde $acc5,$acc5,$a2
+ adde $acc6,$acc6,$t3
+ adde $acc7,$acc7,$a3
+___
+for($i=0;$i<3;$i++) { # reductions, see commentary in
+ # multiplication for details
+$code.=<<___;
+ subfc $t2,$t0,$acc0 # "*0xffff0001"
+ subfe $t3,$t1,$acc0
+ addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0]
+ sldi $t0,$acc0,32
+ adde $acc1,$acc2,$t1
+ srdi $t1,$acc0,32
+ adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001
+ addze $acc3,$t3 # can't overflow
+___
+}
+$code.=<<___;
+ subfc $t2,$t0,$acc0 # "*0xffff0001"
+ subfe $t3,$t1,$acc0
+ addc $acc0,$acc1,$t0 # +=acc[0]<<96 and omit acc[0]
+ adde $acc1,$acc2,$t1
+ adde $acc2,$acc3,$t2 # +=acc[0]*0xffff0001
+ addze $acc3,$t3 # can't overflow
+
+ addc $acc0,$acc0,$acc4 # accumulate upper half
+ adde $acc1,$acc1,$acc5
+ adde $acc2,$acc2,$acc6
+ adde $acc3,$acc3,$acc7
+ li $t2,0
+ addze $acc4,$t2
+
+ addic $acc0,$acc0,1 # ret -= modulus
+ subfe $acc1,$poly1,$acc1
+ subfe $acc2,$t2,$acc2
+ subfe $acc3,$poly3,$acc3
+ subfe $acc4,$t2,$acc4
+
+ addc $acc0,$acc0,$acc4 # ret += modulus if borrow
+ and $t1,$poly1,$acc4
+ and $t3,$poly3,$acc4
+ adde $acc1,$acc1,$t1
+ addze $acc2,$acc2
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,1,0
+ .long 0
+.size __ecp_nistz256_sqr_mont,.-__ecp_nistz256_sqr_mont
+
+# Note that __ecp_nistz256_add expects both input vectors pre-loaded to
+# $a0-$a3 and $t0-$t3. This is done because it's used in multiple
+# contexts, e.g. in multiplication by 2 and 3...
+.type __ecp_nistz256_add,\@function
+.align 4
+__ecp_nistz256_add:
+ addc $acc0,$acc0,$t0 # ret = a+b
+ adde $acc1,$acc1,$t1
+ adde $acc2,$acc2,$t2
+ li $t2,0
+ adde $acc3,$acc3,$t3
+ addze $t0,$t2
+
+ # if a+b >= modulus, subtract modulus
+ #
+ # But since comparison implies subtraction, we subtract
+ # modulus and then add it back if subtraction borrowed.
+
+ subic $acc0,$acc0,-1
+ subfe $acc1,$poly1,$acc1
+ subfe $acc2,$t2,$acc2
+ subfe $acc3,$poly3,$acc3
+ subfe $t0,$t2,$t0
+
+ addc $acc0,$acc0,$t0
+ and $t1,$poly1,$t0
+ and $t3,$poly3,$t0
+ adde $acc1,$acc1,$t1
+ addze $acc2,$acc2
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size __ecp_nistz256_add,.-__ecp_nistz256_add
+
+.type __ecp_nistz256_sub_from,\@function
+.align 4
+__ecp_nistz256_sub_from:
+ ld $t0,0($bp)
+ ld $t1,8($bp)
+ ld $t2,16($bp)
+ ld $t3,24($bp)
+ subfc $acc0,$t0,$acc0 # ret = a-b
+ subfe $acc1,$t1,$acc1
+ subfe $acc2,$t2,$acc2
+ subfe $acc3,$t3,$acc3
+ subfe $t0,$t0,$t0 # t0 = borrow ? -1 : 0
+
+ # if a-b borrowed, add modulus
+
+ addc $acc0,$acc0,$t0 # ret -= modulus & t0
+ and $t1,$poly1,$t0
+ and $t3,$poly3,$t0
+ adde $acc1,$acc1,$t1
+ addze $acc2,$acc2
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size __ecp_nistz256_sub_from,.-__ecp_nistz256_sub_from
+
+.type __ecp_nistz256_sub_morf,\@function
+.align 4
+__ecp_nistz256_sub_morf:
+ ld $t0,0($bp)
+ ld $t1,8($bp)
+ ld $t2,16($bp)
+ ld $t3,24($bp)
+ subfc $acc0,$acc0,$t0 # ret = b-a
+ subfe $acc1,$acc1,$t1
+ subfe $acc2,$acc2,$t2
+ subfe $acc3,$acc3,$t3
+ subfe $t0,$t0,$t0 # t0 = borrow ? -1 : 0
+
+ # if b-a borrowed, add modulus
+
+ addc $acc0,$acc0,$t0 # ret -= modulus & t0
+ and $t1,$poly1,$t0
+ and $t3,$poly3,$t0
+ adde $acc1,$acc1,$t1
+ addze $acc2,$acc2
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size __ecp_nistz256_sub_morf,.-__ecp_nistz256_sub_morf
+
+.type __ecp_nistz256_div_by_2,\@function
+.align 4
+__ecp_nistz256_div_by_2:
+ andi. $t0,$acc0,1
+ addic $acc0,$acc0,-1 # a += modulus
+ neg $t0,$t0
+ adde $acc1,$acc1,$poly1
+ not $t0,$t0
+ addze $acc2,$acc2
+ li $t2,0
+ adde $acc3,$acc3,$poly3
+ and $t1,$poly1,$t0
+ addze $ap,$t2 # ap = carry
+ and $t3,$poly3,$t0
+
+ subfc $acc0,$t0,$acc0 # a -= modulus if a was even
+ subfe $acc1,$t1,$acc1
+ subfe $acc2,$t2,$acc2
+ subfe $acc3,$t3,$acc3
+ subfe $ap, $t2,$ap
+
+ srdi $acc0,$acc0,1
+ sldi $t0,$acc1,63
+ srdi $acc1,$acc1,1
+ sldi $t1,$acc2,63
+ srdi $acc2,$acc2,1
+ sldi $t2,$acc3,63
+ srdi $acc3,$acc3,1
+ sldi $t3,$ap,63
+ or $acc0,$acc0,$t0
+ or $acc1,$acc1,$t1
+ or $acc2,$acc2,$t2
+ or $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,1,0
+ .long 0
+.size __ecp_nistz256_div_by_2,.-__ecp_nistz256_div_by_2
+___
+########################################################################
+# following subroutines are "literal" implementation of those found in
+# ecp_nistz256.c
+#
+########################################################################
+# void ecp_nistz256_point_double(P256_POINT *out,const P256_POINT *inp);
+#
+if (1) {
+my $FRAME=64+32*4+12*8;
+my ($S,$M,$Zsqr,$tmp0)=map(64+32*$_,(0..3));
+# above map() describes stack layout with 4 temporary
+# 256-bit vectors on top.
+my ($rp_real,$ap_real) = map("r$_",(20,21));
+
+$code.=<<___;
+.globl ecp_nistz256_point_double
+.align 5
+ecp_nistz256_point_double:
+ stdu $sp,-$FRAME($sp)
+ mflr r0
+ std r20,$FRAME-8*12($sp)
+ std r21,$FRAME-8*11($sp)
+ std r22,$FRAME-8*10($sp)
+ std r23,$FRAME-8*9($sp)
+ std r24,$FRAME-8*8($sp)
+ std r25,$FRAME-8*7($sp)
+ std r26,$FRAME-8*6($sp)
+ std r27,$FRAME-8*5($sp)
+ std r28,$FRAME-8*4($sp)
+ std r29,$FRAME-8*3($sp)
+ std r30,$FRAME-8*2($sp)
+ std r31,$FRAME-8*1($sp)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+.Ldouble_shortcut:
+ ld $acc0,32($ap)
+ ld $acc1,40($ap)
+ ld $acc2,48($ap)
+ ld $acc3,56($ap)
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ ld $a0,64($ap) # forward load for p256_sqr_mont
+ ld $a1,72($ap)
+ ld $a2,80($ap)
+ ld $a3,88($ap)
+ mr $rp_real,$rp
+ mr $ap_real,$ap
+ addi $rp,$sp,$S
+ bl __ecp_nistz256_add # p256_mul_by_2(S, in_y);
+
+ addi $rp,$sp,$Zsqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Zsqr, in_z);
+
+ ld $t0,0($ap_real)
+ ld $t1,8($ap_real)
+ ld $t2,16($ap_real)
+ ld $t3,24($ap_real)
+ mr $a0,$acc0 # put Zsqr aside for p256_sub
+ mr $a1,$acc1
+ mr $a2,$acc2
+ mr $a3,$acc3
+ addi $rp,$sp,$M
+ bl __ecp_nistz256_add # p256_add(M, Zsqr, in_x);
+
+ addi $bp,$ap_real,0
+ mr $acc0,$a0 # restore Zsqr
+ mr $acc1,$a1
+ mr $acc2,$a2
+ mr $acc3,$a3
+ ld $a0,$S+0($sp) # forward load for p256_sqr_mont
+ ld $a1,$S+8($sp)
+ ld $a2,$S+16($sp)
+ ld $a3,$S+24($sp)
+ addi $rp,$sp,$Zsqr
+ bl __ecp_nistz256_sub_morf # p256_sub(Zsqr, in_x, Zsqr);
+
+ addi $rp,$sp,$S
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(S, S);
+
+ ld $bi,32($ap_real)
+ ld $a0,64($ap_real)
+ ld $a1,72($ap_real)
+ ld $a2,80($ap_real)
+ ld $a3,88($ap_real)
+ addi $bp,$ap_real,32
+ addi $rp,$sp,$tmp0
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(tmp0, in_z, in_y);
+
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ ld $a0,$S+0($sp) # forward load for p256_sqr_mont
+ ld $a1,$S+8($sp)
+ ld $a2,$S+16($sp)
+ ld $a3,$S+24($sp)
+ addi $rp,$rp_real,64
+ bl __ecp_nistz256_add # p256_mul_by_2(res_z, tmp0);
+
+ addi $rp,$sp,$tmp0
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(tmp0, S);
+
+ ld $bi,$Zsqr($sp) # forward load for p256_mul_mont
+ ld $a0,$M+0($sp)
+ ld $a1,$M+8($sp)
+ ld $a2,$M+16($sp)
+ ld $a3,$M+24($sp)
+ addi $rp,$rp_real,32
+ bl __ecp_nistz256_div_by_2 # p256_div_by_2(res_y, tmp0);
+
+ addi $bp,$sp,$Zsqr
+ addi $rp,$sp,$M
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(M, M, Zsqr);
+
+ mr $t0,$acc0 # duplicate M
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ mr $a0,$acc0 # put M aside
+ mr $a1,$acc1
+ mr $a2,$acc2
+ mr $a3,$acc3
+ addi $rp,$sp,$M
+ bl __ecp_nistz256_add
+ mr $t0,$a0 # restore M
+ mr $t1,$a1
+ mr $t2,$a2
+ mr $t3,$a3
+ ld $bi,0($ap_real) # forward load for p256_mul_mont
+ ld $a0,$S+0($sp)
+ ld $a1,$S+8($sp)
+ ld $a2,$S+16($sp)
+ ld $a3,$S+24($sp)
+ bl __ecp_nistz256_add # p256_mul_by_3(M, M);
+
+ addi $bp,$ap_real,0
+ addi $rp,$sp,$S
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S, S, in_x);
+
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ ld $a0,$M+0($sp) # forward load for p256_sqr_mont
+ ld $a1,$M+8($sp)
+ ld $a2,$M+16($sp)
+ ld $a3,$M+24($sp)
+ addi $rp,$sp,$tmp0
+ bl __ecp_nistz256_add # p256_mul_by_2(tmp0, S);
+
+ addi $rp,$rp_real,0
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(res_x, M);
+
+ addi $bp,$sp,$tmp0
+ bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, tmp0);
+
+ addi $bp,$sp,$S
+ addi $rp,$sp,$S
+ bl __ecp_nistz256_sub_morf # p256_sub(S, S, res_x);
+
+ ld $bi,$M($sp)
+ mr $a0,$acc0 # copy S
+ mr $a1,$acc1
+ mr $a2,$acc2
+ mr $a3,$acc3
+ addi $bp,$sp,$M
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S, S, M);
+
+ addi $bp,$rp_real,32
+ addi $rp,$rp_real,32
+ bl __ecp_nistz256_sub_from # p256_sub(res_y, S, res_y);
+
+ mtlr r0
+ ld r20,$FRAME-8*12($sp)
+ ld r21,$FRAME-8*11($sp)
+ ld r22,$FRAME-8*10($sp)
+ ld r23,$FRAME-8*9($sp)
+ ld r24,$FRAME-8*8($sp)
+ ld r25,$FRAME-8*7($sp)
+ ld r26,$FRAME-8*6($sp)
+ ld r27,$FRAME-8*5($sp)
+ ld r28,$FRAME-8*4($sp)
+ ld r29,$FRAME-8*3($sp)
+ ld r30,$FRAME-8*2($sp)
+ ld r31,$FRAME-8*1($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,12,2,0
+ .long 0
+.size ecp_nistz256_point_double,.-ecp_nistz256_point_double
+___
+}
+
+########################################################################
+# void ecp_nistz256_point_add(P256_POINT *out,const P256_POINT *in1,
+# const P256_POINT *in2);
+if (1) {
+my $FRAME = 64 + 32*12 + 16*8;
+my ($res_x,$res_y,$res_z,
+ $H,$Hsqr,$R,$Rsqr,$Hcub,
+ $U1,$U2,$S1,$S2)=map(64+32*$_,(0..11));
+my ($Z1sqr, $Z2sqr) = ($Hsqr, $Rsqr);
+# above map() describes stack layout with 12 temporary
+# 256-bit vectors on top.
+my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("r$_",(16..21));
+
+$code.=<<___;
+.globl ecp_nistz256_point_add
+.align 5
+ecp_nistz256_point_add:
+ stdu $sp,-$FRAME($sp)
+ mflr r0
+ std r16,$FRAME-8*16($sp)
+ std r17,$FRAME-8*15($sp)
+ std r18,$FRAME-8*14($sp)
+ std r19,$FRAME-8*13($sp)
+ std r20,$FRAME-8*12($sp)
+ std r21,$FRAME-8*11($sp)
+ std r22,$FRAME-8*10($sp)
+ std r23,$FRAME-8*9($sp)
+ std r24,$FRAME-8*8($sp)
+ std r25,$FRAME-8*7($sp)
+ std r26,$FRAME-8*6($sp)
+ std r27,$FRAME-8*5($sp)
+ std r28,$FRAME-8*4($sp)
+ std r29,$FRAME-8*3($sp)
+ std r30,$FRAME-8*2($sp)
+ std r31,$FRAME-8*1($sp)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ ld $a0,64($bp) # in2_z
+ ld $a1,72($bp)
+ ld $a2,80($bp)
+ ld $a3,88($bp)
+ mr $rp_real,$rp
+ mr $ap_real,$ap
+ mr $bp_real,$bp
+ or $t0,$a0,$a1
+ or $t2,$a2,$a3
+ or $in2infty,$t0,$t2
+ neg $t0,$in2infty
+ or $in2infty,$in2infty,$t0
+ sradi $in2infty,$in2infty,63 # !in2infty
+ addi $rp,$sp,$Z2sqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z2sqr, in2_z);
+
+ ld $a0,64($ap_real) # in1_z
+ ld $a1,72($ap_real)
+ ld $a2,80($ap_real)
+ ld $a3,88($ap_real)
+ or $t0,$a0,$a1
+ or $t2,$a2,$a3
+ or $in1infty,$t0,$t2
+ neg $t0,$in1infty
+ or $in1infty,$in1infty,$t0
+ sradi $in1infty,$in1infty,63 # !in1infty
+ addi $rp,$sp,$Z1sqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z1sqr, in1_z);
+
+ ld $bi,64($bp_real)
+ ld $a0,$Z2sqr+0($sp)
+ ld $a1,$Z2sqr+8($sp)
+ ld $a2,$Z2sqr+16($sp)
+ ld $a3,$Z2sqr+24($sp)
+ addi $bp,$bp_real,64
+ addi $rp,$sp,$S1
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S1, Z2sqr, in2_z);
+
+ ld $bi,64($ap_real)
+ ld $a0,$Z1sqr+0($sp)
+ ld $a1,$Z1sqr+8($sp)
+ ld $a2,$Z1sqr+16($sp)
+ ld $a3,$Z1sqr+24($sp)
+ addi $bp,$ap_real,64
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, Z1sqr, in1_z);
+
+ ld $bi,32($ap_real)
+ ld $a0,$S1+0($sp)
+ ld $a1,$S1+8($sp)
+ ld $a2,$S1+16($sp)
+ ld $a3,$S1+24($sp)
+ addi $bp,$ap_real,32
+ addi $rp,$sp,$S1
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S1, S1, in1_y);
+
+ ld $bi,32($bp_real)
+ ld $a0,$S2+0($sp)
+ ld $a1,$S2+8($sp)
+ ld $a2,$S2+16($sp)
+ ld $a3,$S2+24($sp)
+ addi $bp,$bp_real,32
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S2, in2_y);
+
+ addi $bp,$sp,$S1
+ ld $bi,$Z2sqr($sp) # forward load for p256_mul_mont
+ ld $a0,0($ap_real)
+ ld $a1,8($ap_real)
+ ld $a2,16($ap_real)
+ ld $a3,24($ap_real)
+ addi $rp,$sp,$R
+ bl __ecp_nistz256_sub_from # p256_sub(R, S2, S1);
+
+ or $acc0,$acc0,$acc1 # see if result is zero
+ or $acc2,$acc2,$acc3
+ or $temp,$acc0,$acc2
+
+ addi $bp,$sp,$Z2sqr
+ addi $rp,$sp,$U1
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(U1, in1_x, Z2sqr);
+
+ ld $bi,$Z1sqr($sp)
+ ld $a0,0($bp_real)
+ ld $a1,8($bp_real)
+ ld $a2,16($bp_real)
+ ld $a3,24($bp_real)
+ addi $bp,$sp,$Z1sqr
+ addi $rp,$sp,$U2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, in2_x, Z1sqr);
+
+ addi $bp,$sp,$U1
+ ld $a0,$R+0($sp) # forward load for p256_sqr_mont
+ ld $a1,$R+8($sp)
+ ld $a2,$R+16($sp)
+ ld $a3,$R+24($sp)
+ addi $rp,$sp,$H
+ bl __ecp_nistz256_sub_from # p256_sub(H, U2, U1);
+
+ or $acc0,$acc0,$acc1 # see if result is zero
+ or $acc2,$acc2,$acc3
+ or. $acc0,$acc0,$acc2
+ bne .Ladd_proceed # is_equal(U1,U2)?
+
+ and. $t0,$in1infty,$in2infty
+ beq .Ladd_proceed # (in1infty || in2infty)?
+
+ cmpldi $temp,0
+ beq .Ladd_double # is_equal(S1,S2)?
+
+ xor $a0,$a0,$a0
+ std $a0,0($rp_real)
+ std $a0,8($rp_real)
+ std $a0,16($rp_real)
+ std $a0,24($rp_real)
+ std $a0,32($rp_real)
+ std $a0,40($rp_real)
+ std $a0,48($rp_real)
+ std $a0,56($rp_real)
+ std $a0,64($rp_real)
+ std $a0,72($rp_real)
+ std $a0,80($rp_real)
+ std $a0,88($rp_real)
+ b .Ladd_done
+
+.align 4
+.Ladd_double:
+ ld $bp,0($sp) # back-link
+ mr $ap,$ap_real
+ mr $rp,$rp_real
+ ld r16,$FRAME-8*16($sp)
+ ld r17,$FRAME-8*15($sp)
+ ld r18,$FRAME-8*14($sp)
+ ld r19,$FRAME-8*13($sp)
+ stdu $bp,$FRAME-288($sp) # difference in stack frame sizes
+ b .Ldouble_shortcut
+
+.align 4
+.Ladd_proceed:
+ addi $rp,$sp,$Rsqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Rsqr, R);
+
+ ld $bi,64($ap_real)
+ ld $a0,$H+0($sp)
+ ld $a1,$H+8($sp)
+ ld $a2,$H+16($sp)
+ ld $a3,$H+24($sp)
+ addi $bp,$ap_real,64
+ addi $rp,$sp,$res_z
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, H, in1_z);
+
+ ld $a0,$H+0($sp)
+ ld $a1,$H+8($sp)
+ ld $a2,$H+16($sp)
+ ld $a3,$H+24($sp)
+ addi $rp,$sp,$Hsqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Hsqr, H);
+
+ ld $bi,64($bp_real)
+ ld $a0,$res_z+0($sp)
+ ld $a1,$res_z+8($sp)
+ ld $a2,$res_z+16($sp)
+ ld $a3,$res_z+24($sp)
+ addi $bp,$bp_real,64
+ addi $rp,$sp,$res_z
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, res_z, in2_z);
+
+ ld $bi,$H($sp)
+ ld $a0,$Hsqr+0($sp)
+ ld $a1,$Hsqr+8($sp)
+ ld $a2,$Hsqr+16($sp)
+ ld $a3,$Hsqr+24($sp)
+ addi $bp,$sp,$H
+ addi $rp,$sp,$Hcub
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(Hcub, Hsqr, H);
+
+ ld $bi,$Hsqr($sp)
+ ld $a0,$U1+0($sp)
+ ld $a1,$U1+8($sp)
+ ld $a2,$U1+16($sp)
+ ld $a3,$U1+24($sp)
+ addi $bp,$sp,$Hsqr
+ addi $rp,$sp,$U2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, U1, Hsqr);
+
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ addi $rp,$sp,$Hsqr
+ bl __ecp_nistz256_add # p256_mul_by_2(Hsqr, U2);
+
+ addi $bp,$sp,$Rsqr
+ addi $rp,$sp,$res_x
+ bl __ecp_nistz256_sub_morf # p256_sub(res_x, Rsqr, Hsqr);
+
+ addi $bp,$sp,$Hcub
+ bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, Hcub);
+
+ addi $bp,$sp,$U2
+ ld $bi,$Hcub($sp) # forward load for p256_mul_mont
+ ld $a0,$S1+0($sp)
+ ld $a1,$S1+8($sp)
+ ld $a2,$S1+16($sp)
+ ld $a3,$S1+24($sp)
+ addi $rp,$sp,$res_y
+ bl __ecp_nistz256_sub_morf # p256_sub(res_y, U2, res_x);
+
+ addi $bp,$sp,$Hcub
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S1, Hcub);
+
+ ld $bi,$R($sp)
+ ld $a0,$res_y+0($sp)
+ ld $a1,$res_y+8($sp)
+ ld $a2,$res_y+16($sp)
+ ld $a3,$res_y+24($sp)
+ addi $bp,$sp,$R
+ addi $rp,$sp,$res_y
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(res_y, res_y, R);
+
+ addi $bp,$sp,$S2
+ bl __ecp_nistz256_sub_from # p256_sub(res_y, res_y, S2);
+
+ ld $t0,0($bp_real) # in2
+ ld $t1,8($bp_real)
+ ld $t2,16($bp_real)
+ ld $t3,24($bp_real)
+ ld $a0,$res_x+0($sp) # res
+ ld $a1,$res_x+8($sp)
+ ld $a2,$res_x+16($sp)
+ ld $a3,$res_x+24($sp)
+___
+for($i=0;$i<64;$i+=32) { # conditional moves
+$code.=<<___;
+ ld $acc0,$i+0($ap_real) # in1
+ ld $acc1,$i+8($ap_real)
+ ld $acc2,$i+16($ap_real)
+ ld $acc3,$i+24($ap_real)
+ andc $t0,$t0,$in1infty
+ andc $t1,$t1,$in1infty
+ andc $t2,$t2,$in1infty
+ andc $t3,$t3,$in1infty
+ and $a0,$a0,$in1infty
+ and $a1,$a1,$in1infty
+ and $a2,$a2,$in1infty
+ and $a3,$a3,$in1infty
+ or $t0,$t0,$a0
+ or $t1,$t1,$a1
+ or $t2,$t2,$a2
+ or $t3,$t3,$a3
+ andc $acc0,$acc0,$in2infty
+ andc $acc1,$acc1,$in2infty
+ andc $acc2,$acc2,$in2infty
+ andc $acc3,$acc3,$in2infty
+ and $t0,$t0,$in2infty
+ and $t1,$t1,$in2infty
+ and $t2,$t2,$in2infty
+ and $t3,$t3,$in2infty
+ or $acc0,$acc0,$t0
+ or $acc1,$acc1,$t1
+ or $acc2,$acc2,$t2
+ or $acc3,$acc3,$t3
+
+ ld $t0,$i+32($bp_real) # in2
+ ld $t1,$i+40($bp_real)
+ ld $t2,$i+48($bp_real)
+ ld $t3,$i+56($bp_real)
+ ld $a0,$res_x+$i+32($sp)
+ ld $a1,$res_x+$i+40($sp)
+ ld $a2,$res_x+$i+48($sp)
+ ld $a3,$res_x+$i+56($sp)
+ std $acc0,$i+0($rp_real)
+ std $acc1,$i+8($rp_real)
+ std $acc2,$i+16($rp_real)
+ std $acc3,$i+24($rp_real)
+___
+}
+$code.=<<___;
+ ld $acc0,$i+0($ap_real) # in1
+ ld $acc1,$i+8($ap_real)
+ ld $acc2,$i+16($ap_real)
+ ld $acc3,$i+24($ap_real)
+ andc $t0,$t0,$in1infty
+ andc $t1,$t1,$in1infty
+ andc $t2,$t2,$in1infty
+ andc $t3,$t3,$in1infty
+ and $a0,$a0,$in1infty
+ and $a1,$a1,$in1infty
+ and $a2,$a2,$in1infty
+ and $a3,$a3,$in1infty
+ or $t0,$t0,$a0
+ or $t1,$t1,$a1
+ or $t2,$t2,$a2
+ or $t3,$t3,$a3
+ andc $acc0,$acc0,$in2infty
+ andc $acc1,$acc1,$in2infty
+ andc $acc2,$acc2,$in2infty
+ andc $acc3,$acc3,$in2infty
+ and $t0,$t0,$in2infty
+ and $t1,$t1,$in2infty
+ and $t2,$t2,$in2infty
+ and $t3,$t3,$in2infty
+ or $acc0,$acc0,$t0
+ or $acc1,$acc1,$t1
+ or $acc2,$acc2,$t2
+ or $acc3,$acc3,$t3
+ std $acc0,$i+0($rp_real)
+ std $acc1,$i+8($rp_real)
+ std $acc2,$i+16($rp_real)
+ std $acc3,$i+24($rp_real)
+
+.Ladd_done:
+ mtlr r0
+ ld r16,$FRAME-8*16($sp)
+ ld r17,$FRAME-8*15($sp)
+ ld r18,$FRAME-8*14($sp)
+ ld r19,$FRAME-8*13($sp)
+ ld r20,$FRAME-8*12($sp)
+ ld r21,$FRAME-8*11($sp)
+ ld r22,$FRAME-8*10($sp)
+ ld r23,$FRAME-8*9($sp)
+ ld r24,$FRAME-8*8($sp)
+ ld r25,$FRAME-8*7($sp)
+ ld r26,$FRAME-8*6($sp)
+ ld r27,$FRAME-8*5($sp)
+ ld r28,$FRAME-8*4($sp)
+ ld r29,$FRAME-8*3($sp)
+ ld r30,$FRAME-8*2($sp)
+ ld r31,$FRAME-8*1($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,16,3,0
+ .long 0
+.size ecp_nistz256_point_add,.-ecp_nistz256_point_add
+___
+}
+
+########################################################################
+# void ecp_nistz256_point_add_affine(P256_POINT *out,const P256_POINT *in1,
+# const P256_POINT_AFFINE *in2);
+if (1) {
+my $FRAME = 64 + 32*10 + 16*8;
+my ($res_x,$res_y,$res_z,
+ $U2,$S2,$H,$R,$Hsqr,$Hcub,$Rsqr)=map(64+32*$_,(0..9));
+my $Z1sqr = $S2;
+# above map() describes stack layout with 10 temporary
+# 256-bit vectors on top.
+my ($rp_real,$ap_real,$bp_real,$in1infty,$in2infty,$temp)=map("r$_",(16..21));
+
+$code.=<<___;
+.globl ecp_nistz256_point_add_affine
+.align 5
+ecp_nistz256_point_add_affine:
+ stdu $sp,-$FRAME($sp)
+ mflr r0
+ std r16,$FRAME-8*16($sp)
+ std r17,$FRAME-8*15($sp)
+ std r18,$FRAME-8*14($sp)
+ std r19,$FRAME-8*13($sp)
+ std r20,$FRAME-8*12($sp)
+ std r21,$FRAME-8*11($sp)
+ std r22,$FRAME-8*10($sp)
+ std r23,$FRAME-8*9($sp)
+ std r24,$FRAME-8*8($sp)
+ std r25,$FRAME-8*7($sp)
+ std r26,$FRAME-8*6($sp)
+ std r27,$FRAME-8*5($sp)
+ std r28,$FRAME-8*4($sp)
+ std r29,$FRAME-8*3($sp)
+ std r30,$FRAME-8*2($sp)
+ std r31,$FRAME-8*1($sp)
+
+ li $poly1,-1
+ srdi $poly1,$poly1,32 # 0x00000000ffffffff
+ li $poly3,1
+ orc $poly3,$poly3,$poly1 # 0xffffffff00000001
+
+ mr $rp_real,$rp
+ mr $ap_real,$ap
+ mr $bp_real,$bp
+
+ ld $a0,64($ap) # in1_z
+ ld $a1,72($ap)
+ ld $a2,80($ap)
+ ld $a3,88($ap)
+ or $t0,$a0,$a1
+ or $t2,$a2,$a3
+ or $in1infty,$t0,$t2
+ neg $t0,$in1infty
+ or $in1infty,$in1infty,$t0
+ sradi $in1infty,$in1infty,63 # !in1infty
+
+ ld $acc0,0($bp) # in2_x
+ ld $acc1,8($bp)
+ ld $acc2,16($bp)
+ ld $acc3,24($bp)
+ ld $t0,32($bp) # in2_y
+ ld $t1,40($bp)
+ ld $t2,48($bp)
+ ld $t3,56($bp)
+ or $acc0,$acc0,$acc1
+ or $acc2,$acc2,$acc3
+ or $acc0,$acc0,$acc2
+ or $t0,$t0,$t1
+ or $t2,$t2,$t3
+ or $t0,$t0,$t2
+ or $in2infty,$acc0,$t0
+ neg $t0,$in2infty
+ or $in2infty,$in2infty,$t0
+ sradi $in2infty,$in2infty,63 # !in2infty
+
+ addi $rp,$sp,$Z1sqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Z1sqr, in1_z);
+
+ mr $a0,$acc0
+ mr $a1,$acc1
+ mr $a2,$acc2
+ mr $a3,$acc3
+ ld $bi,0($bp_real)
+ addi $bp,$bp_real,0
+ addi $rp,$sp,$U2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, Z1sqr, in2_x);
+
+ addi $bp,$ap_real,0
+ ld $bi,64($ap_real) # forward load for p256_mul_mont
+ ld $a0,$Z1sqr+0($sp)
+ ld $a1,$Z1sqr+8($sp)
+ ld $a2,$Z1sqr+16($sp)
+ ld $a3,$Z1sqr+24($sp)
+ addi $rp,$sp,$H
+ bl __ecp_nistz256_sub_from # p256_sub(H, U2, in1_x);
+
+ addi $bp,$ap_real,64
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, Z1sqr, in1_z);
+
+ ld $bi,64($ap_real)
+ ld $a0,$H+0($sp)
+ ld $a1,$H+8($sp)
+ ld $a2,$H+16($sp)
+ ld $a3,$H+24($sp)
+ addi $bp,$ap_real,64
+ addi $rp,$sp,$res_z
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(res_z, H, in1_z);
+
+ ld $bi,32($bp_real)
+ ld $a0,$S2+0($sp)
+ ld $a1,$S2+8($sp)
+ ld $a2,$S2+16($sp)
+ ld $a3,$S2+24($sp)
+ addi $bp,$bp_real,32
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, S2, in2_y);
+
+ addi $bp,$ap_real,32
+ ld $a0,$H+0($sp) # forward load for p256_sqr_mont
+ ld $a1,$H+8($sp)
+ ld $a2,$H+16($sp)
+ ld $a3,$H+24($sp)
+ addi $rp,$sp,$R
+ bl __ecp_nistz256_sub_from # p256_sub(R, S2, in1_y);
+
+ addi $rp,$sp,$Hsqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Hsqr, H);
+
+ ld $a0,$R+0($sp)
+ ld $a1,$R+8($sp)
+ ld $a2,$R+16($sp)
+ ld $a3,$R+24($sp)
+ addi $rp,$sp,$Rsqr
+ bl __ecp_nistz256_sqr_mont # p256_sqr_mont(Rsqr, R);
+
+ ld $bi,$H($sp)
+ ld $a0,$Hsqr+0($sp)
+ ld $a1,$Hsqr+8($sp)
+ ld $a2,$Hsqr+16($sp)
+ ld $a3,$Hsqr+24($sp)
+ addi $bp,$sp,$H
+ addi $rp,$sp,$Hcub
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(Hcub, Hsqr, H);
+
+ ld $bi,0($ap_real)
+ ld $a0,$Hsqr+0($sp)
+ ld $a1,$Hsqr+8($sp)
+ ld $a2,$Hsqr+16($sp)
+ ld $a3,$Hsqr+24($sp)
+ addi $bp,$ap_real,0
+ addi $rp,$sp,$U2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(U2, in1_x, Hsqr);
+
+ mr $t0,$acc0
+ mr $t1,$acc1
+ mr $t2,$acc2
+ mr $t3,$acc3
+ addi $rp,$sp,$Hsqr
+ bl __ecp_nistz256_add # p256_mul_by_2(Hsqr, U2);
+
+ addi $bp,$sp,$Rsqr
+ addi $rp,$sp,$res_x
+ bl __ecp_nistz256_sub_morf # p256_sub(res_x, Rsqr, Hsqr);
+
+ addi $bp,$sp,$Hcub
+ bl __ecp_nistz256_sub_from # p256_sub(res_x, res_x, Hcub);
+
+ addi $bp,$sp,$U2
+ ld $bi,32($ap_real) # forward load for p256_mul_mont
+ ld $a0,$Hcub+0($sp)
+ ld $a1,$Hcub+8($sp)
+ ld $a2,$Hcub+16($sp)
+ ld $a3,$Hcub+24($sp)
+ addi $rp,$sp,$res_y
+ bl __ecp_nistz256_sub_morf # p256_sub(res_y, U2, res_x);
+
+ addi $bp,$ap_real,32
+ addi $rp,$sp,$S2
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(S2, in1_y, Hcub);
+
+ ld $bi,$R($sp)
+ ld $a0,$res_y+0($sp)
+ ld $a1,$res_y+8($sp)
+ ld $a2,$res_y+16($sp)
+ ld $a3,$res_y+24($sp)
+ addi $bp,$sp,$R
+ addi $rp,$sp,$res_y
+ bl __ecp_nistz256_mul_mont # p256_mul_mont(res_y, res_y, R);
+
+ addi $bp,$sp,$S2
+ bl __ecp_nistz256_sub_from # p256_sub(res_y, res_y, S2);
+
+ ld $t0,0($bp_real) # in2
+ ld $t1,8($bp_real)
+ ld $t2,16($bp_real)
+ ld $t3,24($bp_real)
+ ld $a0,$res_x+0($sp) # res
+ ld $a1,$res_x+8($sp)
+ ld $a2,$res_x+16($sp)
+ ld $a3,$res_x+24($sp)
+___
+for($i=0;$i<64;$i+=32) { # conditional moves
+$code.=<<___;
+ ld $acc0,$i+0($ap_real) # in1
+ ld $acc1,$i+8($ap_real)
+ ld $acc2,$i+16($ap_real)
+ ld $acc3,$i+24($ap_real)
+ andc $t0,$t0,$in1infty
+ andc $t1,$t1,$in1infty
+ andc $t2,$t2,$in1infty
+ andc $t3,$t3,$in1infty
+ and $a0,$a0,$in1infty
+ and $a1,$a1,$in1infty
+ and $a2,$a2,$in1infty
+ and $a3,$a3,$in1infty
+ or $t0,$t0,$a0
+ or $t1,$t1,$a1
+ or $t2,$t2,$a2
+ or $t3,$t3,$a3
+ andc $acc0,$acc0,$in2infty
+ andc $acc1,$acc1,$in2infty
+ andc $acc2,$acc2,$in2infty
+ andc $acc3,$acc3,$in2infty
+ and $t0,$t0,$in2infty
+ and $t1,$t1,$in2infty
+ and $t2,$t2,$in2infty
+ and $t3,$t3,$in2infty
+ or $acc0,$acc0,$t0
+ or $acc1,$acc1,$t1
+ or $acc2,$acc2,$t2
+ or $acc3,$acc3,$t3
+___
+$code.=<<___ if ($i==0);
+ ld $t0,32($bp_real) # in2
+ ld $t1,40($bp_real)
+ ld $t2,48($bp_real)
+ ld $t3,56($bp_real)
+___
+$code.=<<___ if ($i==32);
+ li $t0,1 # Lone_mont
+ not $t1,$poly1
+ li $t2,-1
+ not $t3,$poly3
+___
+$code.=<<___;
+ ld $a0,$res_x+$i+32($sp)
+ ld $a1,$res_x+$i+40($sp)
+ ld $a2,$res_x+$i+48($sp)
+ ld $a3,$res_x+$i+56($sp)
+ std $acc0,$i+0($rp_real)
+ std $acc1,$i+8($rp_real)
+ std $acc2,$i+16($rp_real)
+ std $acc3,$i+24($rp_real)
+___
+}
+$code.=<<___;
+ ld $acc0,$i+0($ap_real) # in1
+ ld $acc1,$i+8($ap_real)
+ ld $acc2,$i+16($ap_real)
+ ld $acc3,$i+24($ap_real)
+ andc $t0,$t0,$in1infty
+ andc $t1,$t1,$in1infty
+ andc $t2,$t2,$in1infty
+ andc $t3,$t3,$in1infty
+ and $a0,$a0,$in1infty
+ and $a1,$a1,$in1infty
+ and $a2,$a2,$in1infty
+ and $a3,$a3,$in1infty
+ or $t0,$t0,$a0
+ or $t1,$t1,$a1
+ or $t2,$t2,$a2
+ or $t3,$t3,$a3
+ andc $acc0,$acc0,$in2infty
+ andc $acc1,$acc1,$in2infty
+ andc $acc2,$acc2,$in2infty
+ andc $acc3,$acc3,$in2infty
+ and $t0,$t0,$in2infty
+ and $t1,$t1,$in2infty
+ and $t2,$t2,$in2infty
+ and $t3,$t3,$in2infty
+ or $acc0,$acc0,$t0
+ or $acc1,$acc1,$t1
+ or $acc2,$acc2,$t2
+ or $acc3,$acc3,$t3
+ std $acc0,$i+0($rp_real)
+ std $acc1,$i+8($rp_real)
+ std $acc2,$i+16($rp_real)
+ std $acc3,$i+24($rp_real)
+
+ mtlr r0
+ ld r16,$FRAME-8*16($sp)
+ ld r17,$FRAME-8*15($sp)
+ ld r18,$FRAME-8*14($sp)
+ ld r19,$FRAME-8*13($sp)
+ ld r20,$FRAME-8*12($sp)
+ ld r21,$FRAME-8*11($sp)
+ ld r22,$FRAME-8*10($sp)
+ ld r23,$FRAME-8*9($sp)
+ ld r24,$FRAME-8*8($sp)
+ ld r25,$FRAME-8*7($sp)
+ ld r26,$FRAME-8*6($sp)
+ ld r27,$FRAME-8*5($sp)
+ ld r28,$FRAME-8*4($sp)
+ ld r29,$FRAME-8*3($sp)
+ ld r30,$FRAME-8*2($sp)
+ ld r31,$FRAME-8*1($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,16,3,0
+ .long 0
+.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine
+___
+}
+if (1) {
+my ($ordk,$ord0,$ord1,$t4) = map("r$_",(18..21));
+my ($ord2,$ord3,$zr) = ($poly1,$poly3,"r0");
+
+$code.=<<___;
+########################################################################
+# void ecp_nistz256_ord_mul_mont(uint64_t res[4], uint64_t a[4],
+# uint64_t b[4]);
+.globl ecp_nistz256_ord_mul_mont
+.align 5
+ecp_nistz256_ord_mul_mont:
+ stdu $sp,-160($sp)
+ std r18,48($sp)
+ std r19,56($sp)
+ std r20,64($sp)
+ std r21,72($sp)
+ std r22,80($sp)
+ std r23,88($sp)
+ std r24,96($sp)
+ std r25,104($sp)
+ std r26,112($sp)
+ std r27,120($sp)
+ std r28,128($sp)
+ std r29,136($sp)
+ std r30,144($sp)
+ std r31,152($sp)
+
+ ld $a0,0($ap)
+ ld $bi,0($bp)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ lis $ordk,0xccd1
+ lis $ord0,0xf3b9
+ lis $ord1,0xbce6
+ ori $ordk,$ordk,0xc8aa
+ ori $ord0,$ord0,0xcac2
+ ori $ord1,$ord1,0xfaad
+ sldi $ordk,$ordk,32
+ sldi $ord0,$ord0,32
+ sldi $ord1,$ord1,32
+ oris $ordk,$ordk,0xee00
+ oris $ord0,$ord0,0xfc63
+ oris $ord1,$ord1,0xa717
+ ori $ordk,$ordk,0xbc4f # 0xccd1c8aaee00bc4f
+ ori $ord0,$ord0,0x2551 # 0xf3b9cac2fc632551
+ ori $ord1,$ord1,0x9e84 # 0xbce6faada7179e84
+ li $ord2,-1 # 0xffffffffffffffff
+ sldi $ord3,$ord2,32 # 0xffffffff00000000
+ li $zr,0
+
+ mulld $acc0,$a0,$bi # a[0]*b[0]
+ mulhdu $t0,$a0,$bi
+
+ mulld $acc1,$a1,$bi # a[1]*b[0]
+ mulhdu $t1,$a1,$bi
+
+ mulld $acc2,$a2,$bi # a[2]*b[0]
+ mulhdu $t2,$a2,$bi
+
+ mulld $acc3,$a3,$bi # a[3]*b[0]
+ mulhdu $acc4,$a3,$bi
+
+ mulld $t4,$acc0,$ordk
+
+ addc $acc1,$acc1,$t0 # accumulate high parts of multiplication
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$t2
+ addze $acc4,$acc4
+ li $acc5,0
+___
+for ($i=1;$i<4;$i++) {
+ ################################################################
+ # ffff0000.ffffffff.yyyyyyyy.zzzzzzzz
+ # * abcdefgh
+ # + xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
+ #
+ # Now observing that ff..ff*x = (2^n-1)*x = 2^n*x-x, we
+ # rewrite above as:
+ #
+ # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
+ # - 0000abcd.efgh0000.abcdefgh.00000000.00000000
+ # + abcdefgh.abcdefgh.yzayzbyz.cyzdyzey.zfyzgyzh
+$code.=<<___;
+ ld $bi,8*$i($bp) # b[i]
+
+ sldi $t0,$t4,32
+ subfc $acc2,$t4,$acc2
+ srdi $t1,$t4,32
+ subfe $acc3,$t0,$acc3
+ subfe $acc4,$t1,$acc4
+ subfe $acc5,$zr,$acc5
+
+ addic $t0,$acc0,-1 # discarded
+ mulhdu $t1,$ord0,$t4
+ mulld $t2,$ord1,$t4
+ mulhdu $t3,$ord1,$t4
+
+ adde $t2,$t2,$t1
+ mulld $t0,$a0,$bi
+ addze $t3,$t3
+ mulld $t1,$a1,$bi
+
+ addc $acc0,$acc1,$t2
+ mulld $t2,$a2,$bi
+ adde $acc1,$acc2,$t3
+ mulld $t3,$a3,$bi
+ adde $acc2,$acc3,$t4
+ adde $acc3,$acc4,$t4
+ addze $acc4,$acc5
+
+ addc $acc0,$acc0,$t0 # accumulate low parts
+ mulhdu $t0,$a0,$bi
+ adde $acc1,$acc1,$t1
+ mulhdu $t1,$a1,$bi
+ adde $acc2,$acc2,$t2
+ mulhdu $t2,$a2,$bi
+ adde $acc3,$acc3,$t3
+ mulhdu $t3,$a3,$bi
+ addze $acc4,$acc4
+ mulld $t4,$acc0,$ordk
+ addc $acc1,$acc1,$t0 # accumulate high parts
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$t2
+ adde $acc4,$acc4,$t3
+ addze $acc5,$zr
+___
+}
+$code.=<<___;
+ sldi $t0,$t4,32 # last reduction
+ subfc $acc2,$t4,$acc2
+ srdi $t1,$t4,32
+ subfe $acc3,$t0,$acc3
+ subfe $acc4,$t1,$acc4
+ subfe $acc5,$zr,$acc5
+
+ addic $t0,$acc0,-1 # discarded
+ mulhdu $t1,$ord0,$t4
+ mulld $t2,$ord1,$t4
+ mulhdu $t3,$ord1,$t4
+
+ adde $t2,$t2,$t1
+ addze $t3,$t3
+
+ addc $acc0,$acc1,$t2
+ adde $acc1,$acc2,$t3
+ adde $acc2,$acc3,$t4
+ adde $acc3,$acc4,$t4
+ addze $acc4,$acc5
+
+ subfc $acc0,$ord0,$acc0 # ret -= modulus
+ subfe $acc1,$ord1,$acc1
+ subfe $acc2,$ord2,$acc2
+ subfe $acc3,$ord3,$acc3
+ subfe $acc4,$zr,$acc4
+
+ and $t0,$ord0,$acc4
+ and $t1,$ord1,$acc4
+ addc $acc0,$acc0,$t0 # ret += modulus if borrow
+ and $t3,$ord3,$acc4
+ adde $acc1,$acc1,$t1
+ adde $acc2,$acc2,$acc4
+ adde $acc3,$acc3,$t3
+
+ std $acc0,0($rp)
+ std $acc1,8($rp)
+ std $acc2,16($rp)
+ std $acc3,24($rp)
+
+ ld r18,48($sp)
+ ld r19,56($sp)
+ ld r20,64($sp)
+ ld r21,72($sp)
+ ld r22,80($sp)
+ ld r23,88($sp)
+ ld r24,96($sp)
+ ld r25,104($sp)
+ ld r26,112($sp)
+ ld r27,120($sp)
+ ld r28,128($sp)
+ ld r29,136($sp)
+ ld r30,144($sp)
+ ld r31,152($sp)
+ addi $sp,$sp,160
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,14,3,0
+ .long 0
+.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont
+
+################################################################################
+# void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
+# int rep);
+.globl ecp_nistz256_ord_sqr_mont
+.align 5
+ecp_nistz256_ord_sqr_mont:
+ stdu $sp,-160($sp)
+ std r18,48($sp)
+ std r19,56($sp)
+ std r20,64($sp)
+ std r21,72($sp)
+ std r22,80($sp)
+ std r23,88($sp)
+ std r24,96($sp)
+ std r25,104($sp)
+ std r26,112($sp)
+ std r27,120($sp)
+ std r28,128($sp)
+ std r29,136($sp)
+ std r30,144($sp)
+ std r31,152($sp)
+
+ mtctr $bp
+
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ lis $ordk,0xccd1
+ lis $ord0,0xf3b9
+ lis $ord1,0xbce6
+ ori $ordk,$ordk,0xc8aa
+ ori $ord0,$ord0,0xcac2
+ ori $ord1,$ord1,0xfaad
+ sldi $ordk,$ordk,32
+ sldi $ord0,$ord0,32
+ sldi $ord1,$ord1,32
+ oris $ordk,$ordk,0xee00
+ oris $ord0,$ord0,0xfc63
+ oris $ord1,$ord1,0xa717
+ ori $ordk,$ordk,0xbc4f # 0xccd1c8aaee00bc4f
+ ori $ord0,$ord0,0x2551 # 0xf3b9cac2fc632551
+ ori $ord1,$ord1,0x9e84 # 0xbce6faada7179e84
+ li $ord2,-1 # 0xffffffffffffffff
+ sldi $ord3,$ord2,32 # 0xffffffff00000000
+ li $zr,0
+ b .Loop_ord_sqr
+
+.align 5
+.Loop_ord_sqr:
+ ################################################################
+ # | | | | | |a1*a0| |
+ # | | | | |a2*a0| | |
+ # | |a3*a2|a3*a0| | | |
+ # | | | |a2*a1| | | |
+ # | | |a3*a1| | | | |
+ # *| | | | | | | | 2|
+ # +|a3*a3|a2*a2|a1*a1|a0*a0|
+ # |--+--+--+--+--+--+--+--|
+ # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx
+ #
+ # "can't overflow" below mark carrying into high part of
+ # multiplication result, which can't overflow, because it
+ # can never be all ones.
+
+ mulld $acc1,$a1,$a0 # a[1]*a[0]
+ mulhdu $t1,$a1,$a0
+ mulld $acc2,$a2,$a0 # a[2]*a[0]
+ mulhdu $t2,$a2,$a0
+ mulld $acc3,$a3,$a0 # a[3]*a[0]
+ mulhdu $acc4,$a3,$a0
+
+ addc $acc2,$acc2,$t1 # accumulate high parts of multiplication
+ mulld $t0,$a2,$a1 # a[2]*a[1]
+ mulhdu $t1,$a2,$a1
+ adde $acc3,$acc3,$t2
+ mulld $t2,$a3,$a1 # a[3]*a[1]
+ mulhdu $t3,$a3,$a1
+ addze $acc4,$acc4 # can't overflow
+
+ mulld $acc5,$a3,$a2 # a[3]*a[2]
+ mulhdu $acc6,$a3,$a2
+
+ addc $t1,$t1,$t2 # accumulate high parts of multiplication
+ mulld $acc0,$a0,$a0 # a[0]*a[0]
+ addze $t2,$t3 # can't overflow
+
+ addc $acc3,$acc3,$t0 # accumulate low parts of multiplication
+ mulhdu $a0,$a0,$a0
+ adde $acc4,$acc4,$t1
+ mulld $t1,$a1,$a1 # a[1]*a[1]
+ adde $acc5,$acc5,$t2
+ mulhdu $a1,$a1,$a1
+ addze $acc6,$acc6 # can't overflow
+
+ addc $acc1,$acc1,$acc1 # acc[1-6]*=2
+ mulld $t2,$a2,$a2 # a[2]*a[2]
+ adde $acc2,$acc2,$acc2
+ mulhdu $a2,$a2,$a2
+ adde $acc3,$acc3,$acc3
+ mulld $t3,$a3,$a3 # a[3]*a[3]
+ adde $acc4,$acc4,$acc4
+ mulhdu $a3,$a3,$a3
+ adde $acc5,$acc5,$acc5
+ adde $acc6,$acc6,$acc6
+ addze $acc7,$zr
+
+ addc $acc1,$acc1,$a0 # +a[i]*a[i]
+ mulld $t4,$acc0,$ordk
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$a1
+ adde $acc4,$acc4,$t2
+ adde $acc5,$acc5,$a2
+ adde $acc6,$acc6,$t3
+ adde $acc7,$acc7,$a3
+___
+for($i=0; $i<4; $i++) { # reductions
+$code.=<<___;
+ addic $t0,$acc0,-1 # discarded
+ mulhdu $t1,$ord0,$t4
+ mulld $t2,$ord1,$t4
+ mulhdu $t3,$ord1,$t4
+
+ adde $t2,$t2,$t1
+ addze $t3,$t3
+
+ addc $acc0,$acc1,$t2
+ adde $acc1,$acc2,$t3
+ adde $acc2,$acc3,$t4
+ adde $acc3,$zr,$t4 # can't overflow
+___
+$code.=<<___ if ($i<3);
+ mulld $t3,$acc0,$ordk
+___
+$code.=<<___;
+ sldi $t0,$t4,32
+ subfc $acc1,$t4,$acc1
+ srdi $t1,$t4,32
+ subfe $acc2,$t0,$acc2
+ subfe $acc3,$t1,$acc3 # can't borrow
+___
+ ($t3,$t4) = ($t4,$t3);
+}
+$code.=<<___;
+ addc $acc0,$acc0,$acc4 # accumulate upper half
+ adde $acc1,$acc1,$acc5
+ adde $acc2,$acc2,$acc6
+ adde $acc3,$acc3,$acc7
+ addze $acc4,$zr
+
+ subfc $acc0,$ord0,$acc0 # ret -= modulus
+ subfe $acc1,$ord1,$acc1
+ subfe $acc2,$ord2,$acc2
+ subfe $acc3,$ord3,$acc3
+ subfe $acc4,$zr,$acc4
+
+ and $t0,$ord0,$acc4
+ and $t1,$ord1,$acc4
+ addc $a0,$acc0,$t0 # ret += modulus if borrow
+ and $t3,$ord3,$acc4
+ adde $a1,$acc1,$t1
+ adde $a2,$acc2,$acc4
+ adde $a3,$acc3,$t3
+
+ bdnz .Loop_ord_sqr
+
+ std $a0,0($rp)
+ std $a1,8($rp)
+ std $a2,16($rp)
+ std $a3,24($rp)
+
+ ld r18,48($sp)
+ ld r19,56($sp)
+ ld r20,64($sp)
+ ld r21,72($sp)
+ ld r22,80($sp)
+ ld r23,88($sp)
+ ld r24,96($sp)
+ ld r25,104($sp)
+ ld r26,112($sp)
+ ld r27,120($sp)
+ ld r28,128($sp)
+ ld r29,136($sp)
+ ld r30,144($sp)
+ ld r31,152($sp)
+ addi $sp,$sp,160
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,14,3,0
+ .long 0
+.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont
+___
+} }
+
+########################################################################
+# scatter-gather subroutines
+{
+my ($out,$inp,$index,$mask)=map("r$_",(3..7));
+$code.=<<___;
+########################################################################
+# void ecp_nistz256_scatter_w5(void *out, const P256_POINT *inp,
+# int index);
+.globl ecp_nistz256_scatter_w5
+.align 4
+ecp_nistz256_scatter_w5:
+ slwi $index,$index,2
+ add $out,$out,$index
+
+ ld r8, 0($inp) # X
+ ld r9, 8($inp)
+ ld r10,16($inp)
+ ld r11,24($inp)
+
+ stw r8, 64*0-4($out)
+ srdi r8, r8, 32
+ stw r9, 64*1-4($out)
+ srdi r9, r9, 32
+ stw r10,64*2-4($out)
+ srdi r10,r10,32
+ stw r11,64*3-4($out)
+ srdi r11,r11,32
+ stw r8, 64*4-4($out)
+ stw r9, 64*5-4($out)
+ stw r10,64*6-4($out)
+ stw r11,64*7-4($out)
+ addi $out,$out,64*8
+
+ ld r8, 32($inp) # Y
+ ld r9, 40($inp)
+ ld r10,48($inp)
+ ld r11,56($inp)
+
+ stw r8, 64*0-4($out)
+ srdi r8, r8, 32
+ stw r9, 64*1-4($out)
+ srdi r9, r9, 32
+ stw r10,64*2-4($out)
+ srdi r10,r10,32
+ stw r11,64*3-4($out)
+ srdi r11,r11,32
+ stw r8, 64*4-4($out)
+ stw r9, 64*5-4($out)
+ stw r10,64*6-4($out)
+ stw r11,64*7-4($out)
+ addi $out,$out,64*8
+
+ ld r8, 64($inp) # Z
+ ld r9, 72($inp)
+ ld r10,80($inp)
+ ld r11,88($inp)
+
+ stw r8, 64*0-4($out)
+ srdi r8, r8, 32
+ stw r9, 64*1-4($out)
+ srdi r9, r9, 32
+ stw r10,64*2-4($out)
+ srdi r10,r10,32
+ stw r11,64*3-4($out)
+ srdi r11,r11,32
+ stw r8, 64*4-4($out)
+ stw r9, 64*5-4($out)
+ stw r10,64*6-4($out)
+ stw r11,64*7-4($out)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size ecp_nistz256_scatter_w5,.-ecp_nistz256_scatter_w5
+
+########################################################################
+# void ecp_nistz256_gather_w5(P256_POINT *out, const void *inp,
+# int index);
+.globl ecp_nistz256_gather_w5
+.align 4
+ecp_nistz256_gather_w5:
+ neg r0,$index
+ sradi r0,r0,63
+
+ add $index,$index,r0
+ slwi $index,$index,2
+ add $inp,$inp,$index
+
+ lwz r5, 64*0($inp)
+ lwz r6, 64*1($inp)
+ lwz r7, 64*2($inp)
+ lwz r8, 64*3($inp)
+ lwz r9, 64*4($inp)
+ lwz r10,64*5($inp)
+ lwz r11,64*6($inp)
+ lwz r12,64*7($inp)
+ addi $inp,$inp,64*8
+ sldi r9, r9, 32
+ sldi r10,r10,32
+ sldi r11,r11,32
+ sldi r12,r12,32
+ or r5,r5,r9
+ or r6,r6,r10
+ or r7,r7,r11
+ or r8,r8,r12
+ and r5,r5,r0
+ and r6,r6,r0
+ and r7,r7,r0
+ and r8,r8,r0
+ std r5,0($out) # X
+ std r6,8($out)
+ std r7,16($out)
+ std r8,24($out)
+
+ lwz r5, 64*0($inp)
+ lwz r6, 64*1($inp)
+ lwz r7, 64*2($inp)
+ lwz r8, 64*3($inp)
+ lwz r9, 64*4($inp)
+ lwz r10,64*5($inp)
+ lwz r11,64*6($inp)
+ lwz r12,64*7($inp)
+ addi $inp,$inp,64*8
+ sldi r9, r9, 32
+ sldi r10,r10,32
+ sldi r11,r11,32
+ sldi r12,r12,32
+ or r5,r5,r9
+ or r6,r6,r10
+ or r7,r7,r11
+ or r8,r8,r12
+ and r5,r5,r0
+ and r6,r6,r0
+ and r7,r7,r0
+ and r8,r8,r0
+ std r5,32($out) # Y
+ std r6,40($out)
+ std r7,48($out)
+ std r8,56($out)
+
+ lwz r5, 64*0($inp)
+ lwz r6, 64*1($inp)
+ lwz r7, 64*2($inp)
+ lwz r8, 64*3($inp)
+ lwz r9, 64*4($inp)
+ lwz r10,64*5($inp)
+ lwz r11,64*6($inp)
+ lwz r12,64*7($inp)
+ sldi r9, r9, 32
+ sldi r10,r10,32
+ sldi r11,r11,32
+ sldi r12,r12,32
+ or r5,r5,r9
+ or r6,r6,r10
+ or r7,r7,r11
+ or r8,r8,r12
+ and r5,r5,r0
+ and r6,r6,r0
+ and r7,r7,r0
+ and r8,r8,r0
+ std r5,64($out) # Z
+ std r6,72($out)
+ std r7,80($out)
+ std r8,88($out)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5
+
+########################################################################
+# void ecp_nistz256_scatter_w7(void *out, const P256_POINT_AFFINE *inp,
+# int index);
+.globl ecp_nistz256_scatter_w7
+.align 4
+ecp_nistz256_scatter_w7:
+ li r0,8
+ mtctr r0
+ add $out,$out,$index
+ subi $inp,$inp,8
+
+.Loop_scatter_w7:
+ ldu r0,8($inp)
+ stb r0,64*0($out)
+ srdi r0,r0,8
+ stb r0,64*1($out)
+ srdi r0,r0,8
+ stb r0,64*2($out)
+ srdi r0,r0,8
+ stb r0,64*3($out)
+ srdi r0,r0,8
+ stb r0,64*4($out)
+ srdi r0,r0,8
+ stb r0,64*5($out)
+ srdi r0,r0,8
+ stb r0,64*6($out)
+ srdi r0,r0,8
+ stb r0,64*7($out)
+ addi $out,$out,64*8
+ bdnz .Loop_scatter_w7
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size ecp_nistz256_scatter_w7,.-ecp_nistz256_scatter_w7
+
+########################################################################
+# void ecp_nistz256_gather_w7(P256_POINT_AFFINE *out, const void *inp,
+# int index);
+.globl ecp_nistz256_gather_w7
+.align 4
+ecp_nistz256_gather_w7:
+ li r0,8
+ mtctr r0
+ neg r0,$index
+ sradi r0,r0,63
+
+ add $index,$index,r0
+ add $inp,$inp,$index
+ subi $out,$out,8
+
+.Loop_gather_w7:
+ lbz r5, 64*0($inp)
+ lbz r6, 64*1($inp)
+ lbz r7, 64*2($inp)
+ lbz r8, 64*3($inp)
+ lbz r9, 64*4($inp)
+ lbz r10,64*5($inp)
+ lbz r11,64*6($inp)
+ lbz r12,64*7($inp)
+ addi $inp,$inp,64*8
+
+ sldi r6, r6, 8
+ sldi r7, r7, 16
+ sldi r8, r8, 24
+ sldi r9, r9, 32
+ sldi r10,r10,40
+ sldi r11,r11,48
+ sldi r12,r12,56
+
+ or r5,r5,r6
+ or r7,r7,r8
+ or r9,r9,r10
+ or r11,r11,r12
+ or r5,r5,r7
+ or r9,r9,r11
+ or r5,r5,r9
+ and r5,r5,r0
+ stdu r5,8($out)
+ bdnz .Loop_gather_w7
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7
+___
+}
+
+foreach (split("\n",$code)) {
+ s/\`([^\`]*)\`/eval $1/ge;
+
+ print $_,"\n";
+}
+close STDOUT; # enforce flush
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-sparcv9.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-sparcv9.pl
index 0c1af95b13..0a4def6e2b 100755
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-sparcv9.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-sparcv9.pl
@@ -413,7 +413,7 @@ __ecp_nistz256_add:
! if a+b >= modulus, subtract modulus.
!
! But since comparison implies subtraction, we subtract
- ! modulus and then add it back if subraction borrowed.
+ ! modulus and then add it back if subtraction borrowed.
subcc @acc[0],-1,@acc[0]
subccc @acc[1],-1,@acc[1]
@@ -1592,7 +1592,7 @@ ___
########################################################################
# Following subroutines are VIS3 counterparts of those above that
# implement ones found in ecp_nistz256.c. Key difference is that they
-# use 128-bit muliplication and addition with 64-bit carry, and in order
+# use 128-bit multiplication and addition with 64-bit carry, and in order
# to do that they perform conversion from uin32_t[8] to uint64_t[4] upon
# entry and vice versa on return.
#
@@ -1874,7 +1874,7 @@ $code.=<<___ if ($i<3);
ldx [$bp+8*($i+1)],$bi ! bp[$i+1]
___
$code.=<<___;
- addcc $acc1,$t0,$acc1 ! accumulate high parts of multiplication
+ addcc $acc1,$t0,$acc1 ! accumulate high parts of multiplication
sllx $acc0,32,$t0
addxccc $acc2,$t1,$acc2
srlx $acc0,32,$t1
@@ -1977,7 +1977,7 @@ $code.=<<___;
srlx $acc0,32,$t1
addxccc $acc3,$t2,$acc2 ! +=acc[0]*0xFFFFFFFF00000001
sub $acc0,$t0,$t2 ! acc0*0xFFFFFFFF00000001, low part
- addxc %g0,$t3,$acc3 ! cant't overflow
+ addxc %g0,$t3,$acc3 ! can't overflow
___
}
$code.=<<___;
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86.pl
index b3bec23228..0c6fc665bf 100755
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86.pl
@@ -45,7 +45,7 @@ require "x86asm.pl";
$output=pop;
open STDOUT,">$output";
-&asm_init($ARGV[0],"ecp_nistz256-x86.pl",$ARGV[$#ARGV] eq "386");
+&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
$sse2=0;
for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
@@ -443,7 +443,7 @@ for(1..37) {
&mov (&DWP(20,"esp"),"eax");
&mov (&DWP(24,"esp"),"eax");
&mov (&DWP(28,"esp"),"eax");
-
+
&call ("_ecp_nistz256_sub");
&stack_pop(8);
diff --git a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
index 714e852a18..eba6ffd430 100755
--- a/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
+++ b/deps/openssl/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
@@ -1,60 +1,44 @@
#! /usr/bin/env perl
-# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright (c) 2014, Intel Corporation. All Rights Reserved.
+# Copyright (c) 2015 CloudFlare, Inc.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-
-
-##############################################################################
-# #
-# Copyright 2014 Intel Corporation #
-# #
-# Licensed under the Apache License, Version 2.0 (the "License"); #
-# you may not use this file except in compliance with the License. #
-# You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-# Unless required by applicable law or agreed to in writing, software #
-# distributed under the License is distributed on an "AS IS" BASIS, #
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-# See the License for the specific language governing permissions and #
-# limitations under the License. #
-# #
-##############################################################################
-# #
-# Developers and authors: #
-# Shay Gueron (1, 2), and Vlad Krasnov (1) #
-# (1) Intel Corporation, Israel Development Center #
-# (2) University of Haifa #
-# Reference: #
-# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with#
-# 256 Bit Primes" #
-# #
-##############################################################################
+#
+# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3)
+# (1) Intel Corporation, Israel Development Center, Haifa, Israel
+# (2) University of Haifa, Israel
+# (3) CloudFlare, Inc.
+#
+# Reference:
+# S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
+# 256 Bit Primes"
# Further optimization by <appro@openssl.org>:
#
# this/original with/without -DECP_NISTZ256_ASM(*)
-# Opteron +12-49% +110-150%
-# Bulldozer +14-45% +175-210%
-# P4 +18-46% n/a :-(
-# Westmere +12-34% +80-87%
-# Sandy Bridge +9-35% +110-120%
-# Ivy Bridge +9-35% +110-125%
-# Haswell +8-37% +140-160%
-# Broadwell +18-58% +145-210%
-# Atom +15-50% +130-180%
-# VIA Nano +43-160% +300-480%
+# Opteron +15-49% +150-195%
+# Bulldozer +18-45% +175-240%
+# P4 +24-46% +100-150%
+# Westmere +18-34% +87-160%
+# Sandy Bridge +14-35% +120-185%
+# Ivy Bridge +11-35% +125-180%
+# Haswell +10-37% +160-200%
+# Broadwell +24-58% +210-270%
+# Atom +20-50% +180-240%
+# VIA Nano +50-160% +480-480%
#
# (*) "without -DECP_NISTZ256_ASM" refers to build with
# "enable-ec_nistp_64_gcc_128";
#
# Ranges denote minimum and maximum improvement coefficients depending
-# on benchmark. Lower coefficients are for ECDSA sign, relatively fastest
-# server-side operation. Keep in mind that +100% means 2x improvement.
+# on benchmark. In "this/original" column lower coefficient is for
+# ECDSA sign, while in "with/without" - for ECDH key agreement, and
+# higher - for ECDSA sign, relatively fastest server-side operation.
+# Keep in mind that +100% means 2x improvement.
$flavour = shift;
$output = shift;
@@ -115,6 +99,12 @@ $code.=<<___;
.long 3,3,3,3,3,3,3,3
.LONE_mont:
.quad 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe
+
+# Constants for computations modulo ord(p256)
+.Lord:
+.quad 0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000
+.LordK:
+.quad 0xccd1c8aaee00bc4f
___
{
@@ -131,8 +121,12 @@ $code.=<<___;
.type ecp_nistz256_mul_by_2,\@function,2
.align 64
ecp_nistz256_mul_by_2:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Lmul_by_2_body:
mov 8*0($a_ptr), $a0
xor $t4,$t4
@@ -165,9 +159,15 @@ ecp_nistz256_mul_by_2:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Lmul_by_2_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
################################################################################
@@ -176,8 +176,12 @@ ecp_nistz256_mul_by_2:
.type ecp_nistz256_div_by_2,\@function,2
.align 32
ecp_nistz256_div_by_2:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Ldiv_by_2_body:
mov 8*0($a_ptr), $a0
mov 8*1($a_ptr), $a1
@@ -225,9 +229,15 @@ ecp_nistz256_div_by_2:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Ldiv_by_2_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2
################################################################################
@@ -236,8 +246,12 @@ ecp_nistz256_div_by_2:
.type ecp_nistz256_mul_by_3,\@function,2
.align 32
ecp_nistz256_mul_by_3:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Lmul_by_3_body:
mov 8*0($a_ptr), $a0
xor $t4, $t4
@@ -291,9 +305,15 @@ ecp_nistz256_mul_by_3:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Lmul_by_3_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3
################################################################################
@@ -302,8 +322,12 @@ ecp_nistz256_mul_by_3:
.type ecp_nistz256_add,\@function,3
.align 32
ecp_nistz256_add:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Ladd_body:
mov 8*0($a_ptr), $a0
xor $t4, $t4
@@ -337,9 +361,15 @@ ecp_nistz256_add:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Ladd_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_add,.-ecp_nistz256_add
################################################################################
@@ -348,8 +378,12 @@ ecp_nistz256_add:
.type ecp_nistz256_sub,\@function,3
.align 32
ecp_nistz256_sub:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Lsub_body:
mov 8*0($a_ptr), $a0
xor $t4, $t4
@@ -383,9 +417,15 @@ ecp_nistz256_sub:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Lsub_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_sub,.-ecp_nistz256_sub
################################################################################
@@ -394,8 +434,12 @@ ecp_nistz256_sub:
.type ecp_nistz256_neg,\@function,2
.align 32
ecp_nistz256_neg:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Lneg_body:
xor $a0, $a0
xor $a1, $a1
@@ -429,9 +473,15 @@ ecp_nistz256_neg:
mov $a2, 8*2($r_ptr)
mov $a3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Lneg_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_neg,.-ecp_nistz256_neg
___
}
@@ -443,6 +493,1085 @@ my ($poly1,$poly3)=($acc6,$acc7);
$code.=<<___;
################################################################################
+# void ecp_nistz256_ord_mul_mont(
+# uint64_t res[4],
+# uint64_t a[4],
+# uint64_t b[4]);
+
+.globl ecp_nistz256_ord_mul_mont
+.type ecp_nistz256_ord_mul_mont,\@function,3
+.align 32
+ecp_nistz256_ord_mul_mont:
+.cfi_startproc
+___
+$code.=<<___ if ($addx);
+ mov \$0x80100, %ecx
+ and OPENSSL_ia32cap_P+8(%rip), %ecx
+ cmp \$0x80100, %ecx
+ je .Lecp_nistz256_ord_mul_montx
+___
+$code.=<<___;
+ 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
+.Lord_mul_body:
+
+ mov 8*0($b_org), %rax
+ mov $b_org, $b_ptr
+ lea .Lord(%rip), %r14
+ mov .LordK(%rip), %r15
+
+ ################################# * b[0]
+ mov %rax, $t0
+ mulq 8*0($a_ptr)
+ mov %rax, $acc0
+ mov $t0, %rax
+ mov %rdx, $acc1
+
+ mulq 8*1($a_ptr)
+ add %rax, $acc1
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $acc2
+
+ mulq 8*2($a_ptr)
+ add %rax, $acc2
+ mov $t0, %rax
+ adc \$0, %rdx
+
+ mov $acc0, $acc5
+ imulq %r15,$acc0
+
+ mov %rdx, $acc3
+ mulq 8*3($a_ptr)
+ add %rax, $acc3
+ mov $acc0, %rax
+ adc \$0, %rdx
+ mov %rdx, $acc4
+
+ ################################# First reduction step
+ mulq 8*0(%r14)
+ mov $acc0, $t1
+ add %rax, $acc5 # guaranteed to be zero
+ mov $acc0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t0
+
+ sub $acc0, $acc2
+ sbb \$0, $acc0 # can't borrow
+
+ mulq 8*1(%r14)
+ add $t0, $acc1
+ adc \$0, %rdx
+ add %rax, $acc1
+ mov $t1, %rax
+ adc %rdx, $acc2
+ mov $t1, %rdx
+ adc \$0, $acc0 # can't overflow
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc3
+ mov 8*1($b_ptr), %rax
+ sbb %rdx, $t1 # can't borrow
+
+ add $acc0, $acc3
+ adc $t1, $acc4
+ adc \$0, $acc5
+
+ ################################# * b[1]
+ mov %rax, $t0
+ mulq 8*0($a_ptr)
+ add %rax, $acc1
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*1($a_ptr)
+ add $t1, $acc2
+ adc \$0, %rdx
+ add %rax, $acc2
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*2($a_ptr)
+ add $t1, $acc3
+ adc \$0, %rdx
+ add %rax, $acc3
+ mov $t0, %rax
+ adc \$0, %rdx
+
+ mov $acc1, $t0
+ imulq %r15, $acc1
+
+ mov %rdx, $t1
+ mulq 8*3($a_ptr)
+ add $t1, $acc4
+ adc \$0, %rdx
+ xor $acc0, $acc0
+ add %rax, $acc4
+ mov $acc1, %rax
+ adc %rdx, $acc5
+ adc \$0, $acc0
+
+ ################################# Second reduction step
+ mulq 8*0(%r14)
+ mov $acc1, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov $acc1, %rax
+ adc %rdx, $t0
+
+ sub $acc1, $acc3
+ sbb \$0, $acc1 # can't borrow
+
+ mulq 8*1(%r14)
+ add $t0, $acc2
+ adc \$0, %rdx
+ add %rax, $acc2
+ mov $t1, %rax
+ adc %rdx, $acc3
+ mov $t1, %rdx
+ adc \$0, $acc1 # can't overflow
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc4
+ mov 8*2($b_ptr), %rax
+ sbb %rdx, $t1 # can't borrow
+
+ add $acc1, $acc4
+ adc $t1, $acc5
+ adc \$0, $acc0
+
+ ################################## * b[2]
+ mov %rax, $t0
+ mulq 8*0($a_ptr)
+ add %rax, $acc2
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*1($a_ptr)
+ add $t1, $acc3
+ adc \$0, %rdx
+ add %rax, $acc3
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*2($a_ptr)
+ add $t1, $acc4
+ adc \$0, %rdx
+ add %rax, $acc4
+ mov $t0, %rax
+ adc \$0, %rdx
+
+ mov $acc2, $t0
+ imulq %r15, $acc2
+
+ mov %rdx, $t1
+ mulq 8*3($a_ptr)
+ add $t1, $acc5
+ adc \$0, %rdx
+ xor $acc1, $acc1
+ add %rax, $acc5
+ mov $acc2, %rax
+ adc %rdx, $acc0
+ adc \$0, $acc1
+
+ ################################# Third reduction step
+ mulq 8*0(%r14)
+ mov $acc2, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov $acc2, %rax
+ adc %rdx, $t0
+
+ sub $acc2, $acc4
+ sbb \$0, $acc2 # can't borrow
+
+ mulq 8*1(%r14)
+ add $t0, $acc3
+ adc \$0, %rdx
+ add %rax, $acc3
+ mov $t1, %rax
+ adc %rdx, $acc4
+ mov $t1, %rdx
+ adc \$0, $acc2 # can't overflow
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc5
+ mov 8*3($b_ptr), %rax
+ sbb %rdx, $t1 # can't borrow
+
+ add $acc2, $acc5
+ adc $t1, $acc0
+ adc \$0, $acc1
+
+ ################################# * b[3]
+ mov %rax, $t0
+ mulq 8*0($a_ptr)
+ add %rax, $acc3
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*1($a_ptr)
+ add $t1, $acc4
+ adc \$0, %rdx
+ add %rax, $acc4
+ mov $t0, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mulq 8*2($a_ptr)
+ add $t1, $acc5
+ adc \$0, %rdx
+ add %rax, $acc5
+ mov $t0, %rax
+ adc \$0, %rdx
+
+ mov $acc3, $t0
+ imulq %r15, $acc3
+
+ mov %rdx, $t1
+ mulq 8*3($a_ptr)
+ add $t1, $acc0
+ adc \$0, %rdx
+ xor $acc2, $acc2
+ add %rax, $acc0
+ mov $acc3, %rax
+ adc %rdx, $acc1
+ adc \$0, $acc2
+
+ ################################# Last reduction step
+ mulq 8*0(%r14)
+ mov $acc3, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov $acc3, %rax
+ adc %rdx, $t0
+
+ sub $acc3, $acc5
+ sbb \$0, $acc3 # can't borrow
+
+ mulq 8*1(%r14)
+ add $t0, $acc4
+ adc \$0, %rdx
+ add %rax, $acc4
+ mov $t1, %rax
+ adc %rdx, $acc5
+ mov $t1, %rdx
+ adc \$0, $acc3 # can't overflow
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc0
+ sbb %rdx, $t1 # can't borrow
+
+ add $acc3, $acc0
+ adc $t1, $acc1
+ adc \$0, $acc2
+
+ ################################# Subtract ord
+ mov $acc4, $a_ptr
+ sub 8*0(%r14), $acc4
+ mov $acc5, $acc3
+ sbb 8*1(%r14), $acc5
+ mov $acc0, $t0
+ sbb 8*2(%r14), $acc0
+ mov $acc1, $t1
+ sbb 8*3(%r14), $acc1
+ sbb \$0, $acc2
+
+ cmovc $a_ptr, $acc4
+ cmovc $acc3, $acc5
+ cmovc $t0, $acc0
+ cmovc $t1, $acc1
+
+ mov $acc4, 8*0($r_ptr)
+ mov $acc5, 8*1($r_ptr)
+ mov $acc0, 8*2($r_ptr)
+ mov $acc1, 8*3($r_ptr)
+
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lord_mul_epilogue:
+ ret
+.cfi_endproc
+.size ecp_nistz256_ord_mul_mont,.-ecp_nistz256_ord_mul_mont
+
+################################################################################
+# void ecp_nistz256_ord_sqr_mont(
+# uint64_t res[4],
+# uint64_t a[4],
+# int rep);
+
+.globl ecp_nistz256_ord_sqr_mont
+.type ecp_nistz256_ord_sqr_mont,\@function,3
+.align 32
+ecp_nistz256_ord_sqr_mont:
+.cfi_startproc
+___
+$code.=<<___ if ($addx);
+ mov \$0x80100, %ecx
+ and OPENSSL_ia32cap_P+8(%rip), %ecx
+ cmp \$0x80100, %ecx
+ je .Lecp_nistz256_ord_sqr_montx
+___
+$code.=<<___;
+ 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
+.Lord_sqr_body:
+
+ mov 8*0($a_ptr), $acc0
+ mov 8*1($a_ptr), %rax
+ mov 8*2($a_ptr), $acc6
+ mov 8*3($a_ptr), $acc7
+ lea .Lord(%rip), $a_ptr # pointer to modulus
+ mov $b_org, $b_ptr
+ jmp .Loop_ord_sqr
+
+.align 32
+.Loop_ord_sqr:
+ ################################# a[1:] * a[0]
+ mov %rax, $t1 # put aside a[1]
+ mul $acc0 # a[1] * a[0]
+ mov %rax, $acc1
+ movq $t1, %xmm1 # offload a[1]
+ mov $acc6, %rax
+ mov %rdx, $acc2
+
+ mul $acc0 # a[2] * a[0]
+ add %rax, $acc2
+ mov $acc7, %rax
+ movq $acc6, %xmm2 # offload a[2]
+ adc \$0, %rdx
+ mov %rdx, $acc3
+
+ mul $acc0 # a[3] * a[0]
+ add %rax, $acc3
+ mov $acc7, %rax
+ movq $acc7, %xmm3 # offload a[3]
+ adc \$0, %rdx
+ mov %rdx, $acc4
+
+ ################################# a[3] * a[2]
+ mul $acc6 # a[3] * a[2]
+ mov %rax, $acc5
+ mov $acc6, %rax
+ mov %rdx, $acc6
+
+ ################################# a[2:] * a[1]
+ mul $t1 # a[2] * a[1]
+ add %rax, $acc3
+ mov $acc7, %rax
+ adc \$0, %rdx
+ mov %rdx, $acc7
+
+ mul $t1 # a[3] * a[1]
+ add %rax, $acc4
+ adc \$0, %rdx
+
+ add $acc7, $acc4
+ adc %rdx, $acc5
+ adc \$0, $acc6 # can't overflow
+
+ ################################# *2
+ xor $acc7, $acc7
+ mov $acc0, %rax
+ add $acc1, $acc1
+ adc $acc2, $acc2
+ adc $acc3, $acc3
+ adc $acc4, $acc4
+ adc $acc5, $acc5
+ adc $acc6, $acc6
+ adc \$0, $acc7
+
+ ################################# Missing products
+ mul %rax # a[0] * a[0]
+ mov %rax, $acc0
+ movq %xmm1, %rax
+ mov %rdx, $t1
+
+ mul %rax # a[1] * a[1]
+ add $t1, $acc1
+ adc %rax, $acc2
+ movq %xmm2, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mul %rax # a[2] * a[2]
+ add $t1, $acc3
+ adc %rax, $acc4
+ movq %xmm3, %rax
+ adc \$0, %rdx
+ mov %rdx, $t1
+
+ mov $acc0, $t0
+ imulq 8*4($a_ptr), $acc0 # *= .LordK
+
+ mul %rax # a[3] * a[3]
+ add $t1, $acc5
+ adc %rax, $acc6
+ mov 8*0($a_ptr), %rax # modulus[0]
+ adc %rdx, $acc7 # can't overflow
+
+ ################################# First reduction step
+ mul $acc0
+ mov $acc0, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov 8*1($a_ptr), %rax # modulus[1]
+ adc %rdx, $t0
+
+ sub $acc0, $acc2
+ sbb \$0, $t1 # can't borrow
+
+ mul $acc0
+ add $t0, $acc1
+ adc \$0, %rdx
+ add %rax, $acc1
+ mov $acc0, %rax
+ adc %rdx, $acc2
+ mov $acc0, %rdx
+ adc \$0, $t1 # can't overflow
+
+ mov $acc1, $t0
+ imulq 8*4($a_ptr), $acc1 # *= .LordK
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc3
+ mov 8*0($a_ptr), %rax
+ sbb %rdx, $acc0 # can't borrow
+
+ add $t1, $acc3
+ adc \$0, $acc0 # can't overflow
+
+ ################################# Second reduction step
+ mul $acc1
+ mov $acc1, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov 8*1($a_ptr), %rax
+ adc %rdx, $t0
+
+ sub $acc1, $acc3
+ sbb \$0, $t1 # can't borrow
+
+ mul $acc1
+ add $t0, $acc2
+ adc \$0, %rdx
+ add %rax, $acc2
+ mov $acc1, %rax
+ adc %rdx, $acc3
+ mov $acc1, %rdx
+ adc \$0, $t1 # can't overflow
+
+ mov $acc2, $t0
+ imulq 8*4($a_ptr), $acc2 # *= .LordK
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc0
+ mov 8*0($a_ptr), %rax
+ sbb %rdx, $acc1 # can't borrow
+
+ add $t1, $acc0
+ adc \$0, $acc1 # can't overflow
+
+ ################################# Third reduction step
+ mul $acc2
+ mov $acc2, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov 8*1($a_ptr), %rax
+ adc %rdx, $t0
+
+ sub $acc2, $acc0
+ sbb \$0, $t1 # can't borrow
+
+ mul $acc2
+ add $t0, $acc3
+ adc \$0, %rdx
+ add %rax, $acc3
+ mov $acc2, %rax
+ adc %rdx, $acc0
+ mov $acc2, %rdx
+ adc \$0, $t1 # can't overflow
+
+ mov $acc3, $t0
+ imulq 8*4($a_ptr), $acc3 # *= .LordK
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc1
+ mov 8*0($a_ptr), %rax
+ sbb %rdx, $acc2 # can't borrow
+
+ add $t1, $acc1
+ adc \$0, $acc2 # can't overflow
+
+ ################################# Last reduction step
+ mul $acc3
+ mov $acc3, $t1
+ add %rax, $t0 # guaranteed to be zero
+ mov 8*1($a_ptr), %rax
+ adc %rdx, $t0
+
+ sub $acc3, $acc1
+ sbb \$0, $t1 # can't borrow
+
+ mul $acc3
+ add $t0, $acc0
+ adc \$0, %rdx
+ add %rax, $acc0
+ mov $acc3, %rax
+ adc %rdx, $acc1
+ mov $acc3, %rdx
+ adc \$0, $t1 # can't overflow
+
+ shl \$32, %rax
+ shr \$32, %rdx
+ sub %rax, $acc2
+ sbb %rdx, $acc3 # can't borrow
+
+ add $t1, $acc2
+ adc \$0, $acc3 # can't overflow
+
+ ################################# Add bits [511:256] of the sqr result
+ xor %rdx, %rdx
+ add $acc4, $acc0
+ adc $acc5, $acc1
+ mov $acc0, $acc4
+ adc $acc6, $acc2
+ adc $acc7, $acc3
+ mov $acc1, %rax
+ adc \$0, %rdx
+
+ ################################# Compare to modulus
+ sub 8*0($a_ptr), $acc0
+ mov $acc2, $acc6
+ sbb 8*1($a_ptr), $acc1
+ sbb 8*2($a_ptr), $acc2
+ mov $acc3, $acc7
+ sbb 8*3($a_ptr), $acc3
+ sbb \$0, %rdx
+
+ cmovc $acc4, $acc0
+ cmovnc $acc1, %rax
+ cmovnc $acc2, $acc6
+ cmovnc $acc3, $acc7
+
+ dec $b_ptr
+ jnz .Loop_ord_sqr
+
+ mov $acc0, 8*0($r_ptr)
+ mov %rax, 8*1($r_ptr)
+ pxor %xmm1, %xmm1
+ mov $acc6, 8*2($r_ptr)
+ pxor %xmm2, %xmm2
+ mov $acc7, 8*3($r_ptr)
+ pxor %xmm3, %xmm3
+
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lord_sqr_epilogue:
+ ret
+.cfi_endproc
+.size ecp_nistz256_ord_sqr_mont,.-ecp_nistz256_ord_sqr_mont
+___
+
+$code.=<<___ if ($addx);
+################################################################################
+.type ecp_nistz256_ord_mul_montx,\@function,3
+.align 32
+ecp_nistz256_ord_mul_montx:
+.cfi_startproc
+.Lecp_nistz256_ord_mul_montx:
+ 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
+.Lord_mulx_body:
+
+ mov $b_org, $b_ptr
+ mov 8*0($b_org), %rdx
+ mov 8*0($a_ptr), $acc1
+ mov 8*1($a_ptr), $acc2
+ mov 8*2($a_ptr), $acc3
+ mov 8*3($a_ptr), $acc4
+ lea -128($a_ptr), $a_ptr # control u-op density
+ lea .Lord-128(%rip), %r14
+ mov .LordK(%rip), %r15
+
+ ################################# Multiply by b[0]
+ mulx $acc1, $acc0, $acc1
+ mulx $acc2, $t0, $acc2
+ mulx $acc3, $t1, $acc3
+ add $t0, $acc1
+ mulx $acc4, $t0, $acc4
+ mov $acc0, %rdx
+ mulx %r15, %rdx, %rax
+ adc $t1, $acc2
+ adc $t0, $acc3
+ adc \$0, $acc4
+
+ ################################# reduction
+ xor $acc5, $acc5 # $acc5=0, cf=0, of=0
+ mulx 8*0+128(%r14), $t0, $t1
+ adcx $t0, $acc0 # guaranteed to be zero
+ adox $t1, $acc1
+
+ mulx 8*1+128(%r14), $t0, $t1
+ adcx $t0, $acc1
+ adox $t1, $acc2
+
+ mulx 8*2+128(%r14), $t0, $t1
+ adcx $t0, $acc2
+ adox $t1, $acc3
+
+ mulx 8*3+128(%r14), $t0, $t1
+ mov 8*1($b_ptr), %rdx
+ adcx $t0, $acc3
+ adox $t1, $acc4
+ adcx $acc0, $acc4
+ adox $acc0, $acc5
+ adc \$0, $acc5 # cf=0, of=0
+
+ ################################# Multiply by b[1]
+ mulx 8*0+128($a_ptr), $t0, $t1
+ adcx $t0, $acc1
+ adox $t1, $acc2
+
+ mulx 8*1+128($a_ptr), $t0, $t1
+ adcx $t0, $acc2
+ adox $t1, $acc3
+
+ mulx 8*2+128($a_ptr), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx 8*3+128($a_ptr), $t0, $t1
+ mov $acc1, %rdx
+ mulx %r15, %rdx, %rax
+ adcx $t0, $acc4
+ adox $t1, $acc5
+
+ adcx $acc0, $acc5
+ adox $acc0, $acc0
+ adc \$0, $acc0 # cf=0, of=0
+
+ ################################# reduction
+ mulx 8*0+128(%r14), $t0, $t1
+ adcx $t0, $acc1 # guaranteed to be zero
+ adox $t1, $acc2
+
+ mulx 8*1+128(%r14), $t0, $t1
+ adcx $t0, $acc2
+ adox $t1, $acc3
+
+ mulx 8*2+128(%r14), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx 8*3+128(%r14), $t0, $t1
+ mov 8*2($b_ptr), %rdx
+ adcx $t0, $acc4
+ adox $t1, $acc5
+ adcx $acc1, $acc5
+ adox $acc1, $acc0
+ adc \$0, $acc0 # cf=0, of=0
+
+ ################################# Multiply by b[2]
+ mulx 8*0+128($a_ptr), $t0, $t1
+ adcx $t0, $acc2
+ adox $t1, $acc3
+
+ mulx 8*1+128($a_ptr), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx 8*2+128($a_ptr), $t0, $t1
+ adcx $t0, $acc4
+ adox $t1, $acc5
+
+ mulx 8*3+128($a_ptr), $t0, $t1
+ mov $acc2, %rdx
+ mulx %r15, %rdx, %rax
+ adcx $t0, $acc5
+ adox $t1, $acc0
+
+ adcx $acc1, $acc0
+ adox $acc1, $acc1
+ adc \$0, $acc1 # cf=0, of=0
+
+ ################################# reduction
+ mulx 8*0+128(%r14), $t0, $t1
+ adcx $t0, $acc2 # guaranteed to be zero
+ adox $t1, $acc3
+
+ mulx 8*1+128(%r14), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx 8*2+128(%r14), $t0, $t1
+ adcx $t0, $acc4
+ adox $t1, $acc5
+
+ mulx 8*3+128(%r14), $t0, $t1
+ mov 8*3($b_ptr), %rdx
+ adcx $t0, $acc5
+ adox $t1, $acc0
+ adcx $acc2, $acc0
+ adox $acc2, $acc1
+ adc \$0, $acc1 # cf=0, of=0
+
+ ################################# Multiply by b[3]
+ mulx 8*0+128($a_ptr), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx 8*1+128($a_ptr), $t0, $t1
+ adcx $t0, $acc4
+ adox $t1, $acc5
+
+ mulx 8*2+128($a_ptr), $t0, $t1
+ adcx $t0, $acc5
+ adox $t1, $acc0
+
+ mulx 8*3+128($a_ptr), $t0, $t1
+ mov $acc3, %rdx
+ mulx %r15, %rdx, %rax
+ adcx $t0, $acc0
+ adox $t1, $acc1
+
+ adcx $acc2, $acc1
+ adox $acc2, $acc2
+ adc \$0, $acc2 # cf=0, of=0
+
+ ################################# reduction
+ mulx 8*0+128(%r14), $t0, $t1
+ adcx $t0, $acc3 # guranteed to be zero
+ adox $t1, $acc4
+
+ mulx 8*1+128(%r14), $t0, $t1
+ adcx $t0, $acc4
+ adox $t1, $acc5
+
+ mulx 8*2+128(%r14), $t0, $t1
+ adcx $t0, $acc5
+ adox $t1, $acc0
+
+ mulx 8*3+128(%r14), $t0, $t1
+ lea 128(%r14),%r14
+ mov $acc4, $t2
+ adcx $t0, $acc0
+ adox $t1, $acc1
+ mov $acc5, $t3
+ adcx $acc3, $acc1
+ adox $acc3, $acc2
+ adc \$0, $acc2
+
+ #################################
+ # Branch-less conditional subtraction of P
+ mov $acc0, $t0
+ sub 8*0(%r14), $acc4
+ sbb 8*1(%r14), $acc5
+ sbb 8*2(%r14), $acc0
+ mov $acc1, $t1
+ sbb 8*3(%r14), $acc1
+ sbb \$0, $acc2
+
+ cmovc $t2, $acc4
+ cmovc $t3, $acc5
+ cmovc $t0, $acc0
+ cmovc $t1, $acc1
+
+ mov $acc4, 8*0($r_ptr)
+ mov $acc5, 8*1($r_ptr)
+ mov $acc0, 8*2($r_ptr)
+ mov $acc1, 8*3($r_ptr)
+
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lord_mulx_epilogue:
+ ret
+.cfi_endproc
+.size ecp_nistz256_ord_mul_montx,.-ecp_nistz256_ord_mul_montx
+
+.type ecp_nistz256_ord_sqr_montx,\@function,3
+.align 32
+ecp_nistz256_ord_sqr_montx:
+.cfi_startproc
+.Lecp_nistz256_ord_sqr_montx:
+ 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
+.Lord_sqrx_body:
+
+ mov $b_org, $b_ptr
+ mov 8*0($a_ptr), %rdx
+ mov 8*1($a_ptr), $acc6
+ mov 8*2($a_ptr), $acc7
+ mov 8*3($a_ptr), $acc0
+ lea .Lord(%rip), $a_ptr
+ jmp .Loop_ord_sqrx
+
+.align 32
+.Loop_ord_sqrx:
+ mulx $acc6, $acc1, $acc2 # a[0]*a[1]
+ mulx $acc7, $t0, $acc3 # a[0]*a[2]
+ mov %rdx, %rax # offload a[0]
+ movq $acc6, %xmm1 # offload a[1]
+ mulx $acc0, $t1, $acc4 # a[0]*a[3]
+ mov $acc6, %rdx
+ add $t0, $acc2
+ movq $acc7, %xmm2 # offload a[2]
+ adc $t1, $acc3
+ adc \$0, $acc4
+ xor $acc5, $acc5 # $acc5=0,cf=0,of=0
+ #################################
+ mulx $acc7, $t0, $t1 # a[1]*a[2]
+ adcx $t0, $acc3
+ adox $t1, $acc4
+
+ mulx $acc0, $t0, $t1 # a[1]*a[3]
+ mov $acc7, %rdx
+ adcx $t0, $acc4
+ adox $t1, $acc5
+ adc \$0, $acc5
+ #################################
+ mulx $acc0, $t0, $acc6 # a[2]*a[3]
+ mov %rax, %rdx
+ movq $acc0, %xmm3 # offload a[3]
+ xor $acc7, $acc7 # $acc7=0,cf=0,of=0
+ adcx $acc1, $acc1 # acc1:6<<1
+ adox $t0, $acc5
+ adcx $acc2, $acc2
+ adox $acc7, $acc6 # of=0
+
+ ################################# a[i]*a[i]
+ mulx %rdx, $acc0, $t1
+ movq %xmm1, %rdx
+ adcx $acc3, $acc3
+ adox $t1, $acc1
+ adcx $acc4, $acc4
+ mulx %rdx, $t0, $t4
+ movq %xmm2, %rdx
+ adcx $acc5, $acc5
+ adox $t0, $acc2
+ adcx $acc6, $acc6
+ mulx %rdx, $t0, $t1
+ .byte 0x67
+ movq %xmm3, %rdx
+ adox $t4, $acc3
+ adcx $acc7, $acc7
+ adox $t0, $acc4
+ adox $t1, $acc5
+ mulx %rdx, $t0, $t4
+ adox $t0, $acc6
+ adox $t4, $acc7
+
+ ################################# reduction
+ mov $acc0, %rdx
+ mulx 8*4($a_ptr), %rdx, $t0
+
+ xor %rax, %rax # cf=0, of=0
+ mulx 8*0($a_ptr), $t0, $t1
+ adcx $t0, $acc0 # guaranteed to be zero
+ adox $t1, $acc1
+ mulx 8*1($a_ptr), $t0, $t1
+ adcx $t0, $acc1
+ adox $t1, $acc2
+ mulx 8*2($a_ptr), $t0, $t1
+ adcx $t0, $acc2
+ adox $t1, $acc3
+ mulx 8*3($a_ptr), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc0 # of=0
+ adcx %rax, $acc0 # cf=0
+
+ #################################
+ mov $acc1, %rdx
+ mulx 8*4($a_ptr), %rdx, $t0
+
+ mulx 8*0($a_ptr), $t0, $t1
+ adox $t0, $acc1 # guaranteed to be zero
+ adcx $t1, $acc2
+ mulx 8*1($a_ptr), $t0, $t1
+ adox $t0, $acc2
+ adcx $t1, $acc3
+ mulx 8*2($a_ptr), $t0, $t1
+ adox $t0, $acc3
+ adcx $t1, $acc0
+ mulx 8*3($a_ptr), $t0, $t1
+ adox $t0, $acc0
+ adcx $t1, $acc1 # cf=0
+ adox %rax, $acc1 # of=0
+
+ #################################
+ mov $acc2, %rdx
+ mulx 8*4($a_ptr), %rdx, $t0
+
+ mulx 8*0($a_ptr), $t0, $t1
+ adcx $t0, $acc2 # guaranteed to be zero
+ adox $t1, $acc3
+ mulx 8*1($a_ptr), $t0, $t1
+ adcx $t0, $acc3
+ adox $t1, $acc0
+ mulx 8*2($a_ptr), $t0, $t1
+ adcx $t0, $acc0
+ adox $t1, $acc1
+ mulx 8*3($a_ptr), $t0, $t1
+ adcx $t0, $acc1
+ adox $t1, $acc2 # of=0
+ adcx %rax, $acc2 # cf=0
+
+ #################################
+ mov $acc3, %rdx
+ mulx 8*4($a_ptr), %rdx, $t0
+
+ mulx 8*0($a_ptr), $t0, $t1
+ adox $t0, $acc3 # guaranteed to be zero
+ adcx $t1, $acc0
+ mulx 8*1($a_ptr), $t0, $t1
+ adox $t0, $acc0
+ adcx $t1, $acc1
+ mulx 8*2($a_ptr), $t0, $t1
+ adox $t0, $acc1
+ adcx $t1, $acc2
+ mulx 8*3($a_ptr), $t0, $t1
+ adox $t0, $acc2
+ adcx $t1, $acc3
+ adox %rax, $acc3
+
+ ################################# accumulate upper half
+ add $acc0, $acc4 # add $acc4, $acc0
+ adc $acc5, $acc1
+ mov $acc4, %rdx
+ adc $acc6, $acc2
+ adc $acc7, $acc3
+ mov $acc1, $acc6
+ adc \$0, %rax
+
+ ################################# compare to modulus
+ sub 8*0($a_ptr), $acc4
+ mov $acc2, $acc7
+ sbb 8*1($a_ptr), $acc1
+ sbb 8*2($a_ptr), $acc2
+ mov $acc3, $acc0
+ sbb 8*3($a_ptr), $acc3
+ sbb \$0, %rax
+
+ cmovnc $acc4, %rdx
+ cmovnc $acc1, $acc6
+ cmovnc $acc2, $acc7
+ cmovnc $acc3, $acc0
+
+ dec $b_ptr
+ jnz .Loop_ord_sqrx
+
+ mov %rdx, 8*0($r_ptr)
+ mov $acc6, 8*1($r_ptr)
+ pxor %xmm1, %xmm1
+ mov $acc7, 8*2($r_ptr)
+ pxor %xmm2, %xmm2
+ mov $acc0, 8*3($r_ptr)
+ pxor %xmm3, %xmm3
+
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lord_sqrx_epilogue:
+ ret
+.cfi_endproc
+.size ecp_nistz256_ord_sqr_montx,.-ecp_nistz256_ord_sqr_montx
+___
+
+$code.=<<___;
+################################################################################
# void ecp_nistz256_to_mont(
# uint64_t res[4],
# uint64_t in[4]);
@@ -470,6 +1599,7 @@ $code.=<<___;
.type ecp_nistz256_mul_mont,\@function,3
.align 32
ecp_nistz256_mul_mont:
+.cfi_startproc
___
$code.=<<___ if ($addx);
mov \$0x80100, %ecx
@@ -478,11 +1608,18 @@ ___
$code.=<<___;
.Lmul_mont:
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
+.Lmul_body:
___
$code.=<<___ if ($addx);
cmp \$0x80100, %ecx
@@ -515,13 +1652,23 @@ $code.=<<___ if ($addx);
___
$code.=<<___;
.Lmul_mont_done:
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %rbx
- pop %rbp
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lmul_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont
.type __ecp_nistz256_mul_montq,\@abi-omnipotent
@@ -611,7 +1758,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc0
########################################################################
- # Second reduction step
+ # Second reduction step
mov $acc1, $t1
shl \$32, $acc1
mulq $poly3
@@ -658,7 +1805,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc1
########################################################################
- # Third reduction step
+ # Third reduction step
mov $acc2, $t1
shl \$32, $acc2
mulq $poly3
@@ -705,7 +1852,7 @@ __ecp_nistz256_mul_montq:
adc \$0, $acc2
########################################################################
- # Final reduction step
+ # Final reduction step
mov $acc3, $t1
shl \$32, $acc3
mulq $poly3
@@ -718,7 +1865,7 @@ __ecp_nistz256_mul_montq:
mov $acc5, $t1
adc \$0, $acc2
- ########################################################################
+ ########################################################################
# Branch-less conditional subtraction of P
sub \$-1, $acc4 # .Lpoly[0]
mov $acc0, $t2
@@ -751,6 +1898,7 @@ __ecp_nistz256_mul_montq:
.type ecp_nistz256_sqr_mont,\@function,2
.align 32
ecp_nistz256_sqr_mont:
+.cfi_startproc
___
$code.=<<___ if ($addx);
mov \$0x80100, %ecx
@@ -758,11 +1906,18 @@ $code.=<<___ if ($addx);
___
$code.=<<___;
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
+.Lsqr_body:
___
$code.=<<___ if ($addx);
cmp \$0x80100, %ecx
@@ -791,13 +1946,23 @@ $code.=<<___ if ($addx);
___
$code.=<<___;
.Lsqr_mont_done:
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %rbx
- pop %rbp
+ mov 0(%rsp),%r15
+.cfi_restore %r15
+ mov 8(%rsp),%r14
+.cfi_restore %r14
+ mov 16(%rsp),%r13
+.cfi_restore %r13
+ mov 24(%rsp),%r12
+.cfi_restore %r12
+ mov 32(%rsp),%rbx
+.cfi_restore %rbx
+ mov 40(%rsp),%rbp
+.cfi_restore %rbp
+ lea 48(%rsp),%rsp
+.cfi_adjust_cfa_offset -48
+.Lsqr_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont
.type __ecp_nistz256_sqr_montq,\@abi-omnipotent
@@ -1278,8 +2443,12 @@ $code.=<<___;
.type ecp_nistz256_from_mont,\@function,2
.align 32
ecp_nistz256_from_mont:
+.cfi_startproc
push %r12
+.cfi_push %r12
push %r13
+.cfi_push %r13
+.Lfrom_body:
mov 8*0($in_ptr), %rax
mov .Lpoly+8*3(%rip), $t2
@@ -1360,9 +2529,15 @@ ecp_nistz256_from_mont:
mov $acc2, 8*2($r_ptr)
mov $acc3, 8*3($r_ptr)
- pop %r13
- pop %r12
+ mov 0(%rsp),%r13
+.cfi_restore %r13
+ mov 8(%rsp),%r12
+.cfi_restore %r12
+ lea 16(%rsp),%rsp
+.cfi_adjust_cfa_offset -16
+.Lfrom_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
___
}
@@ -1488,10 +2663,10 @@ $code.=<<___ if ($win64);
movaps 0x80(%rsp), %xmm14
movaps 0x90(%rsp), %xmm15
lea 0xa8(%rsp), %rsp
-.LSEH_end_ecp_nistz256_gather_w5:
___
$code.=<<___;
ret
+.LSEH_end_ecp_nistz256_gather_w5:
.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5
################################################################################
@@ -1593,10 +2768,10 @@ $code.=<<___ if ($win64);
movaps 0x80(%rsp), %xmm14
movaps 0x90(%rsp), %xmm15
lea 0xa8(%rsp), %rsp
-.LSEH_end_ecp_nistz256_gather_w7:
___
$code.=<<___;
ret
+.LSEH_end_ecp_nistz256_gather_w7:
.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7
___
}
@@ -1617,18 +2792,19 @@ ecp_nistz256_avx2_gather_w5:
___
$code.=<<___ if ($win64);
lea -0x88(%rsp), %rax
+ mov %rsp,%r11
.LSEH_begin_ecp_nistz256_avx2_gather_w5:
- .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp
- .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6, -0x20(%rax)
- .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7, -0x10(%rax)
- .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8, 8(%rax)
- .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9, 0x10(%rax)
- .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10, 0x20(%rax)
- .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11, 0x30(%rax)
- .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12, 0x40(%rax)
- .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13, 0x50(%rax)
- .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14, 0x60(%rax)
- .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15, 0x70(%rax)
+ .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax), %rsp
+ .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6, -0x20(%rax)
+ .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7, -0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8, 8(%rax)
+ .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9, 0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10, 0x20(%rax)
+ .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11, 0x30(%rax)
+ .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12, 0x40(%rax)
+ .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13, 0x50(%rax)
+ .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14, 0x60(%rax)
+ .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15, 0x70(%rax)
___
$code.=<<___;
vmovdqa .LTwo(%rip), $TWO
@@ -1694,11 +2870,11 @@ $code.=<<___ if ($win64);
movaps 0x70(%rsp), %xmm13
movaps 0x80(%rsp), %xmm14
movaps 0x90(%rsp), %xmm15
- lea 0xa8(%rsp), %rsp
-.LSEH_end_ecp_nistz256_avx2_gather_w5:
+ lea (%r11), %rsp
___
$code.=<<___;
ret
+.LSEH_end_ecp_nistz256_avx2_gather_w5:
.size ecp_nistz256_avx2_gather_w5,.-ecp_nistz256_avx2_gather_w5
___
}
@@ -1721,19 +2897,20 @@ ecp_nistz256_avx2_gather_w7:
vzeroupper
___
$code.=<<___ if ($win64);
+ mov %rsp,%r11
lea -0x88(%rsp), %rax
.LSEH_begin_ecp_nistz256_avx2_gather_w7:
- .byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax), %rsp
- .byte 0xc5,0xf8,0x29,0x70,0xe0 #vmovaps %xmm6, -0x20(%rax)
- .byte 0xc5,0xf8,0x29,0x78,0xf0 #vmovaps %xmm7, -0x10(%rax)
- .byte 0xc5,0x78,0x29,0x40,0x00 #vmovaps %xmm8, 8(%rax)
- .byte 0xc5,0x78,0x29,0x48,0x10 #vmovaps %xmm9, 0x10(%rax)
- .byte 0xc5,0x78,0x29,0x50,0x20 #vmovaps %xmm10, 0x20(%rax)
- .byte 0xc5,0x78,0x29,0x58,0x30 #vmovaps %xmm11, 0x30(%rax)
- .byte 0xc5,0x78,0x29,0x60,0x40 #vmovaps %xmm12, 0x40(%rax)
- .byte 0xc5,0x78,0x29,0x68,0x50 #vmovaps %xmm13, 0x50(%rax)
- .byte 0xc5,0x78,0x29,0x70,0x60 #vmovaps %xmm14, 0x60(%rax)
- .byte 0xc5,0x78,0x29,0x78,0x70 #vmovaps %xmm15, 0x70(%rax)
+ .byte 0x48,0x8d,0x60,0xe0 # lea -0x20(%rax), %rsp
+ .byte 0xc5,0xf8,0x29,0x70,0xe0 # vmovaps %xmm6, -0x20(%rax)
+ .byte 0xc5,0xf8,0x29,0x78,0xf0 # vmovaps %xmm7, -0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x40,0x00 # vmovaps %xmm8, 8(%rax)
+ .byte 0xc5,0x78,0x29,0x48,0x10 # vmovaps %xmm9, 0x10(%rax)
+ .byte 0xc5,0x78,0x29,0x50,0x20 # vmovaps %xmm10, 0x20(%rax)
+ .byte 0xc5,0x78,0x29,0x58,0x30 # vmovaps %xmm11, 0x30(%rax)
+ .byte 0xc5,0x78,0x29,0x60,0x40 # vmovaps %xmm12, 0x40(%rax)
+ .byte 0xc5,0x78,0x29,0x68,0x50 # vmovaps %xmm13, 0x50(%rax)
+ .byte 0xc5,0x78,0x29,0x70,0x60 # vmovaps %xmm14, 0x60(%rax)
+ .byte 0xc5,0x78,0x29,0x78,0x70 # vmovaps %xmm15, 0x70(%rax)
___
$code.=<<___;
vmovdqa .LThree(%rip), $THREE
@@ -1814,11 +2991,11 @@ $code.=<<___ if ($win64);
movaps 0x70(%rsp), %xmm13
movaps 0x80(%rsp), %xmm14
movaps 0x90(%rsp), %xmm15
- lea 0xa8(%rsp), %rsp
-.LSEH_end_ecp_nistz256_avx2_gather_w7:
+ lea (%r11), %rsp
___
$code.=<<___;
ret
+.LSEH_end_ecp_nistz256_avx2_gather_w7:
.size ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7
___
} else {
@@ -2022,6 +3199,7 @@ $code.=<<___;
.type ecp_nistz256_point_double,\@function,2
.align 32
ecp_nistz256_point_double:
+.cfi_startproc
___
$code.=<<___ if ($addx);
mov \$0x80100, %ecx
@@ -2038,17 +3216,26 @@ $code.=<<___;
.type ecp_nistz256_point_doublex,\@function,2
.align 32
ecp_nistz256_point_doublex:
+.cfi_startproc
.Lpoint_doublex:
___
}
$code.=<<___;
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
sub \$32*5+8, %rsp
+.cfi_adjust_cfa_offset 32*5+8
+.Lpoint_double${x}_body:
.Lpoint_double_shortcut$x:
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr.x
@@ -2114,7 +3301,7 @@ $code.=<<___;
movq %xmm1, $r_ptr
call __ecp_nistz256_sqr_mont$x # p256_sqr_mont(res_y, S);
___
-{
+{
######## ecp_nistz256_div_by_2(res_y, res_y); ##########################
# operate in 4-5-6-7 "name space" that matches squaring output
#
@@ -2203,7 +3390,7 @@ $code.=<<___;
lea $M(%rsp), $b_ptr
mov $acc4, $acc6 # harmonize sub output and mul input
xor %ecx, %ecx
- mov $acc4, $S+8*0(%rsp) # have to save:-(
+ mov $acc4, $S+8*0(%rsp) # have to save:-(
mov $acc5, $acc2
mov $acc5, $S+8*1(%rsp)
cmovz $acc0, $acc3
@@ -2219,14 +3406,25 @@ $code.=<<___;
movq %xmm1, $r_ptr
call __ecp_nistz256_sub_from$x # p256_sub(res_y, S, res_y);
- add \$32*5+8, %rsp
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %rbx
- pop %rbp
+ lea 32*5+56(%rsp), %rsi
+.cfi_def_cfa %rsi,8
+ mov -48(%rsi),%r15
+.cfi_restore %r15
+ mov -40(%rsi),%r14
+.cfi_restore %r14
+ mov -32(%rsi),%r13
+.cfi_restore %r13
+ mov -24(%rsi),%r12
+.cfi_restore %r12
+ mov -16(%rsi),%rbx
+.cfi_restore %rbx
+ mov -8(%rsi),%rbp
+.cfi_restore %rbp
+ lea (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lpoint_double${x}_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_point_double$sfx,.-ecp_nistz256_point_double$sfx
___
}
@@ -2252,6 +3450,7 @@ $code.=<<___;
.type ecp_nistz256_point_add,\@function,3
.align 32
ecp_nistz256_point_add:
+.cfi_startproc
___
$code.=<<___ if ($addx);
mov \$0x80100, %ecx
@@ -2268,17 +3467,26 @@ $code.=<<___;
.type ecp_nistz256_point_addx,\@function,3
.align 32
ecp_nistz256_point_addx:
+.cfi_startproc
.Lpoint_addx:
___
}
$code.=<<___;
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
sub \$32*18+8, %rsp
+.cfi_adjust_cfa_offset 32*18+8
+.Lpoint_add${x}_body:
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr
movdqu 0x10($a_ptr), %xmm1
@@ -2587,14 +3795,25 @@ $code.=<<___;
movdqu %xmm3, 0x30($r_ptr)
.Ladd_done$x:
- add \$32*18+8, %rsp
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %rbx
- pop %rbp
+ lea 32*18+56(%rsp), %rsi
+.cfi_def_cfa %rsi,8
+ mov -48(%rsi),%r15
+.cfi_restore %r15
+ mov -40(%rsi),%r14
+.cfi_restore %r14
+ mov -32(%rsi),%r13
+.cfi_restore %r13
+ mov -24(%rsi),%r12
+.cfi_restore %r12
+ mov -16(%rsi),%rbx
+.cfi_restore %rbx
+ mov -8(%rsi),%rbp
+.cfi_restore %rbp
+ lea (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Lpoint_add${x}_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_point_add$sfx,.-ecp_nistz256_point_add$sfx
___
}
@@ -2619,6 +3838,7 @@ $code.=<<___;
.type ecp_nistz256_point_add_affine,\@function,3
.align 32
ecp_nistz256_point_add_affine:
+.cfi_startproc
___
$code.=<<___ if ($addx);
mov \$0x80100, %ecx
@@ -2635,17 +3855,26 @@ $code.=<<___;
.type ecp_nistz256_point_add_affinex,\@function,3
.align 32
ecp_nistz256_point_add_affinex:
+.cfi_startproc
.Lpoint_add_affinex:
___
}
$code.=<<___;
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
sub \$32*15+8, %rsp
+.cfi_adjust_cfa_offset 32*15+8
+.Ladd_affine${x}_body:
movdqu 0x00($a_ptr), %xmm0 # copy *(P256_POINT *)$a_ptr
mov $b_org, $b_ptr # reassign
@@ -2890,14 +4119,25 @@ $code.=<<___;
movdqu %xmm2, 0x20($r_ptr)
movdqu %xmm3, 0x30($r_ptr)
- add \$32*15+8, %rsp
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- pop %rbx
- pop %rbp
+ lea 32*15+56(%rsp), %rsi
+.cfi_def_cfa %rsi,8
+ mov -48(%rsi),%r15
+.cfi_restore %r15
+ mov -40(%rsi),%r14
+.cfi_restore %r14
+ mov -32(%rsi),%r13
+.cfi_restore %r13
+ mov -24(%rsi),%r12
+.cfi_restore %r12
+ mov -16(%rsi),%rbx
+.cfi_restore %rbx
+ mov -8(%rsi),%rbp
+.cfi_restore %rbp
+ lea (%rsi),%rsp
+.cfi_def_cfa_register %rsp
+.Ladd_affine${x}_epilogue:
ret
+.cfi_endproc
.size ecp_nistz256_point_add_affine$sfx,.-ecp_nistz256_point_add_affine$sfx
___
}
@@ -3048,11 +4288,395 @@ ___
}
}}}
+# 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
+
+ mov 4(%r11),%r10d # HandlerData[1]
+ lea (%rsi,%r10),%r10 # epilogue label
+ cmp %r10,%rbx # context->Rip>=epilogue label
+ jae .Lcommon_seh_tail
+
+ lea 16(%rax),%rax
+
+ mov -8(%rax),%r12
+ mov -16(%rax),%r13
+ mov %r12,216($context) # restore context->R12
+ mov %r13,224($context) # restore context->R13
+
+ 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_ecp_nistz256_mul_by_2
+ .rva .LSEH_end_ecp_nistz256_mul_by_2
+ .rva .LSEH_info_ecp_nistz256_mul_by_2
+
+ .rva .LSEH_begin_ecp_nistz256_div_by_2
+ .rva .LSEH_end_ecp_nistz256_div_by_2
+ .rva .LSEH_info_ecp_nistz256_div_by_2
+
+ .rva .LSEH_begin_ecp_nistz256_mul_by_3
+ .rva .LSEH_end_ecp_nistz256_mul_by_3
+ .rva .LSEH_info_ecp_nistz256_mul_by_3
+
+ .rva .LSEH_begin_ecp_nistz256_add
+ .rva .LSEH_end_ecp_nistz256_add
+ .rva .LSEH_info_ecp_nistz256_add
+
+ .rva .LSEH_begin_ecp_nistz256_sub
+ .rva .LSEH_end_ecp_nistz256_sub
+ .rva .LSEH_info_ecp_nistz256_sub
+
+ .rva .LSEH_begin_ecp_nistz256_neg
+ .rva .LSEH_end_ecp_nistz256_neg
+ .rva .LSEH_info_ecp_nistz256_neg
+
+ .rva .LSEH_begin_ecp_nistz256_ord_mul_mont
+ .rva .LSEH_end_ecp_nistz256_ord_mul_mont
+ .rva .LSEH_info_ecp_nistz256_ord_mul_mont
+
+ .rva .LSEH_begin_ecp_nistz256_ord_sqr_mont
+ .rva .LSEH_end_ecp_nistz256_ord_sqr_mont
+ .rva .LSEH_info_ecp_nistz256_ord_sqr_mont
+___
+$code.=<<___ if ($addx);
+ .rva .LSEH_begin_ecp_nistz256_ord_mul_montx
+ .rva .LSEH_end_ecp_nistz256_ord_mul_montx
+ .rva .LSEH_info_ecp_nistz256_ord_mul_montx
+
+ .rva .LSEH_begin_ecp_nistz256_ord_sqr_montx
+ .rva .LSEH_end_ecp_nistz256_ord_sqr_montx
+ .rva .LSEH_info_ecp_nistz256_ord_sqr_montx
+___
+$code.=<<___;
+ .rva .LSEH_begin_ecp_nistz256_to_mont
+ .rva .LSEH_end_ecp_nistz256_to_mont
+ .rva .LSEH_info_ecp_nistz256_to_mont
+
+ .rva .LSEH_begin_ecp_nistz256_mul_mont
+ .rva .LSEH_end_ecp_nistz256_mul_mont
+ .rva .LSEH_info_ecp_nistz256_mul_mont
+
+ .rva .LSEH_begin_ecp_nistz256_sqr_mont
+ .rva .LSEH_end_ecp_nistz256_sqr_mont
+ .rva .LSEH_info_ecp_nistz256_sqr_mont
+
+ .rva .LSEH_begin_ecp_nistz256_from_mont
+ .rva .LSEH_end_ecp_nistz256_from_mont
+ .rva .LSEH_info_ecp_nistz256_from_mont
+
+ .rva .LSEH_begin_ecp_nistz256_gather_w5
+ .rva .LSEH_end_ecp_nistz256_gather_w5
+ .rva .LSEH_info_ecp_nistz256_gather_wX
+
+ .rva .LSEH_begin_ecp_nistz256_gather_w7
+ .rva .LSEH_end_ecp_nistz256_gather_w7
+ .rva .LSEH_info_ecp_nistz256_gather_wX
+___
+$code.=<<___ if ($avx>1);
+ .rva .LSEH_begin_ecp_nistz256_avx2_gather_w5
+ .rva .LSEH_end_ecp_nistz256_avx2_gather_w5
+ .rva .LSEH_info_ecp_nistz256_avx2_gather_wX
+
+ .rva .LSEH_begin_ecp_nistz256_avx2_gather_w7
+ .rva .LSEH_end_ecp_nistz256_avx2_gather_w7
+ .rva .LSEH_info_ecp_nistz256_avx2_gather_wX
+___
+$code.=<<___;
+ .rva .LSEH_begin_ecp_nistz256_point_double
+ .rva .LSEH_end_ecp_nistz256_point_double
+ .rva .LSEH_info_ecp_nistz256_point_double
+
+ .rva .LSEH_begin_ecp_nistz256_point_add
+ .rva .LSEH_end_ecp_nistz256_point_add
+ .rva .LSEH_info_ecp_nistz256_point_add
+
+ .rva .LSEH_begin_ecp_nistz256_point_add_affine
+ .rva .LSEH_end_ecp_nistz256_point_add_affine
+ .rva .LSEH_info_ecp_nistz256_point_add_affine
+___
+$code.=<<___ if ($addx);
+ .rva .LSEH_begin_ecp_nistz256_point_doublex
+ .rva .LSEH_end_ecp_nistz256_point_doublex
+ .rva .LSEH_info_ecp_nistz256_point_doublex
+
+ .rva .LSEH_begin_ecp_nistz256_point_addx
+ .rva .LSEH_end_ecp_nistz256_point_addx
+ .rva .LSEH_info_ecp_nistz256_point_addx
+
+ .rva .LSEH_begin_ecp_nistz256_point_add_affinex
+ .rva .LSEH_end_ecp_nistz256_point_add_affinex
+ .rva .LSEH_info_ecp_nistz256_point_add_affinex
+___
+$code.=<<___;
+
+.section .xdata
+.align 8
+.LSEH_info_ecp_nistz256_mul_by_2:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Lmul_by_2_body,.Lmul_by_2_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_div_by_2:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Ldiv_by_2_body,.Ldiv_by_2_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_mul_by_3:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Lmul_by_3_body,.Lmul_by_3_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_add:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Ladd_body,.Ladd_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_sub:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Lsub_body,.Lsub_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_neg:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Lneg_body,.Lneg_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_ord_mul_mont:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lord_mul_body,.Lord_mul_epilogue # HandlerData[]
+ .long 48,0
+.LSEH_info_ecp_nistz256_ord_sqr_mont:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lord_sqr_body,.Lord_sqr_epilogue # HandlerData[]
+ .long 48,0
+___
+$code.=<<___ if ($addx);
+.LSEH_info_ecp_nistz256_ord_mul_montx:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lord_mulx_body,.Lord_mulx_epilogue # HandlerData[]
+ .long 48,0
+.LSEH_info_ecp_nistz256_ord_sqr_montx:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lord_sqrx_body,.Lord_sqrx_epilogue # HandlerData[]
+ .long 48,0
+___
+$code.=<<___;
+.LSEH_info_ecp_nistz256_to_mont:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+ .long 48,0
+.LSEH_info_ecp_nistz256_mul_mont:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lmul_body,.Lmul_epilogue # HandlerData[]
+ .long 48,0
+.LSEH_info_ecp_nistz256_sqr_mont:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lsqr_body,.Lsqr_epilogue # HandlerData[]
+ .long 48,0
+.LSEH_info_ecp_nistz256_from_mont:
+ .byte 9,0,0,0
+ .rva short_handler
+ .rva .Lfrom_body,.Lfrom_epilogue # HandlerData[]
+.LSEH_info_ecp_nistz256_gather_wX:
+ .byte 0x01,0x33,0x16,0x00
+ .byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15
+ .byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14
+ .byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13
+ .byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12
+ .byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11
+ .byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10
+ .byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9
+ .byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8
+ .byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
+ .byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
+ .align 8
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_ecp_nistz256_avx2_gather_wX:
+ .byte 0x01,0x36,0x17,0x0b
+ .byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
+ .byte 0x31,0xe8,0x08,0x00 # vmovaps 0x80(rsp),xmm14
+ .byte 0x2c,0xd8,0x07,0x00 # vmovaps 0x70(rsp),xmm13
+ .byte 0x27,0xc8,0x06,0x00 # vmovaps 0x60(rsp),xmm12
+ .byte 0x22,0xb8,0x05,0x00 # vmovaps 0x50(rsp),xmm11
+ .byte 0x1d,0xa8,0x04,0x00 # vmovaps 0x40(rsp),xmm10
+ .byte 0x18,0x98,0x03,0x00 # vmovaps 0x30(rsp),xmm9
+ .byte 0x13,0x88,0x02,0x00 # vmovaps 0x20(rsp),xmm8
+ .byte 0x0e,0x78,0x01,0x00 # vmovaps 0x10(rsp),xmm7
+ .byte 0x09,0x68,0x00,0x00 # vmovaps 0x00(rsp),xmm6
+ .byte 0x04,0x01,0x15,0x00 # sub rsp,0xa8
+ .byte 0x00,0xb3,0x00,0x00 # set_frame r11
+ .align 8
+___
+$code.=<<___;
+.LSEH_info_ecp_nistz256_point_double:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lpoint_doubleq_body,.Lpoint_doubleq_epilogue # HandlerData[]
+ .long 32*5+56,0
+.LSEH_info_ecp_nistz256_point_add:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lpoint_addq_body,.Lpoint_addq_epilogue # HandlerData[]
+ .long 32*18+56,0
+.LSEH_info_ecp_nistz256_point_add_affine:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Ladd_affineq_body,.Ladd_affineq_epilogue # HandlerData[]
+ .long 32*15+56,0
+___
+$code.=<<___ if ($addx);
+.align 8
+.LSEH_info_ecp_nistz256_point_doublex:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lpoint_doublex_body,.Lpoint_doublex_epilogue # HandlerData[]
+ .long 32*5+56,0
+.LSEH_info_ecp_nistz256_point_addx:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Lpoint_addx_body,.Lpoint_addx_epilogue # HandlerData[]
+ .long 32*18+56,0
+.LSEH_info_ecp_nistz256_point_add_affinex:
+ .byte 9,0,0,0
+ .rva full_handler
+ .rva .Ladd_affinex_body,.Ladd_affinex_epilogue # HandlerData[]
+ .long 32*15+56,0
+___
+}
+
########################################################################
# Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7
#
-open TABLE,"<ecp_nistz256_table.c" or
-open TABLE,"<${dir}../ecp_nistz256_table.c" or
+open TABLE,"<ecp_nistz256_table.c" or
+open TABLE,"<${dir}../ecp_nistz256_table.c" or
die "failed to open ecp_nistz256_table.c:",$!;
use integer;
diff --git a/deps/openssl/openssl/crypto/ec/asm/x25519-ppc64.pl b/deps/openssl/openssl/crypto/ec/asm/x25519-ppc64.pl
new file mode 100755
index 0000000000..3773cb27cd
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/asm/x25519-ppc64.pl
@@ -0,0 +1,824 @@
+#! /usr/bin/env perl
+# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# X25519 lower-level primitives for PPC64.
+#
+# July 2018.
+#
+# Base 2^64 is faster than base 2^51 on pre-POWER8, most notably ~15%
+# faster on PPC970/G5. POWER8 on the other hand seems to trip on own
+# shoelaces when handling longer carry chains. As base 2^51 has just
+# single-carry pairs, it's 25% faster than base 2^64. Since PPC970 is
+# pretty old, base 2^64 implementation is not engaged. Comparison to
+# compiler-generated code is complicated by the fact that not all
+# compilers support 128-bit integers. When compiler doesn't, like xlc,
+# this module delivers more than 2x improvement, and when it does,
+# from 12% to 30% improvement was measured...
+
+$flavour = shift;
+while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my $sp = "r1";
+my ($rp,$ap,$bp) = map("r$_",3..5);
+
+####################################################### base 2^64
+if (0) {
+my ($bi,$a0,$a1,$a2,$a3,$t0,$t1, $t2,$t3,
+ $acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7) =
+ map("r$_",(6..12,22..31));
+my $zero = "r0";
+my $FRAME = 16*8;
+
+$code.=<<___;
+.text
+
+.globl x25519_fe64_mul
+.type x25519_fe64_mul,\@function
+.align 5
+x25519_fe64_mul:
+ stdu $sp,-$FRAME($sp)
+ std r22,`$FRAME-8*10`($sp)
+ std r23,`$FRAME-8*9`($sp)
+ std r24,`$FRAME-8*8`($sp)
+ std r25,`$FRAME-8*7`($sp)
+ std r26,`$FRAME-8*6`($sp)
+ std r27,`$FRAME-8*5`($sp)
+ std r28,`$FRAME-8*4`($sp)
+ std r29,`$FRAME-8*3`($sp)
+ std r30,`$FRAME-8*2`($sp)
+ std r31,`$FRAME-8*1`($sp)
+
+ ld $bi,0($bp)
+ ld $a0,0($ap)
+ xor $zero,$zero,$zero
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ mulld $acc0,$a0,$bi # a[0]*b[0]
+ mulhdu $t0,$a0,$bi
+ mulld $acc1,$a1,$bi # a[1]*b[0]
+ mulhdu $t1,$a1,$bi
+ mulld $acc2,$a2,$bi # a[2]*b[0]
+ mulhdu $t2,$a2,$bi
+ mulld $acc3,$a3,$bi # a[3]*b[0]
+ mulhdu $t3,$a3,$bi
+___
+for(my @acc=($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7),
+ my $i=1; $i<4; shift(@acc), $i++) {
+my $acc4 = $i==1? $zero : @acc[4];
+
+$code.=<<___;
+ ld $bi,`8*$i`($bp)
+ addc @acc[1],@acc[1],$t0 # accumulate high parts
+ mulld $t0,$a0,$bi
+ adde @acc[2],@acc[2],$t1
+ mulld $t1,$a1,$bi
+ adde @acc[3],@acc[3],$t2
+ mulld $t2,$a2,$bi
+ adde @acc[4],$acc4,$t3
+ mulld $t3,$a3,$bi
+ addc @acc[1],@acc[1],$t0 # accumulate low parts
+ mulhdu $t0,$a0,$bi
+ adde @acc[2],@acc[2],$t1
+ mulhdu $t1,$a1,$bi
+ adde @acc[3],@acc[3],$t2
+ mulhdu $t2,$a2,$bi
+ adde @acc[4],@acc[4],$t3
+ mulhdu $t3,$a3,$bi
+ adde @acc[5],$zero,$zero
+___
+}
+$code.=<<___;
+ li $bi,38
+ addc $acc4,$acc4,$t0
+ mulld $t0,$acc4,$bi
+ adde $acc5,$acc5,$t1
+ mulld $t1,$acc5,$bi
+ adde $acc6,$acc6,$t2
+ mulld $t2,$acc6,$bi
+ adde $acc7,$acc7,$t3
+ mulld $t3,$acc7,$bi
+
+ addc $acc0,$acc0,$t0
+ mulhdu $t0,$acc4,$bi
+ adde $acc1,$acc1,$t1
+ mulhdu $t1,$acc5,$bi
+ adde $acc2,$acc2,$t2
+ mulhdu $t2,$acc6,$bi
+ adde $acc3,$acc3,$t3
+ mulhdu $t3,$acc7,$bi
+ adde $acc4,$zero,$zero
+
+ addc $acc1,$acc1,$t0
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$t2
+ adde $acc4,$acc4,$t3
+
+ mulld $acc4,$acc4,$bi
+
+ addc $acc0,$acc0,$acc4
+ addze $acc1,$acc1
+ addze $acc2,$acc2
+ addze $acc3,$acc3
+
+ subfe $acc4,$acc4,$acc4 # carry -> ~mask
+ std $acc1,8($rp)
+ andc $acc4,$bi,$acc4
+ std $acc2,16($rp)
+ add $acc0,$acc0,$acc4
+ std $acc3,24($rp)
+ std $acc0,0($rp)
+
+ ld r22,`$FRAME-8*10`($sp)
+ ld r23,`$FRAME-8*9`($sp)
+ ld r24,`$FRAME-8*8`($sp)
+ ld r25,`$FRAME-8*7`($sp)
+ ld r26,`$FRAME-8*6`($sp)
+ ld r27,`$FRAME-8*5`($sp)
+ ld r28,`$FRAME-8*4`($sp)
+ ld r29,`$FRAME-8*3`($sp)
+ ld r30,`$FRAME-8*2`($sp)
+ ld r31,`$FRAME-8*1`($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,10,3,0
+ .long 0
+.size x25519_fe64_mul,.-x25519_fe64_mul
+
+.globl x25519_fe64_sqr
+.type x25519_fe64_sqr,\@function
+.align 5
+x25519_fe64_sqr:
+ stdu $sp,-$FRAME($sp)
+ std r22,`$FRAME-8*10`($sp)
+ std r23,`$FRAME-8*9`($sp)
+ std r24,`$FRAME-8*8`($sp)
+ std r25,`$FRAME-8*7`($sp)
+ std r26,`$FRAME-8*6`($sp)
+ std r27,`$FRAME-8*5`($sp)
+ std r28,`$FRAME-8*4`($sp)
+ std r29,`$FRAME-8*3`($sp)
+ std r30,`$FRAME-8*2`($sp)
+ std r31,`$FRAME-8*1`($sp)
+
+ ld $a0,0($ap)
+ xor $zero,$zero,$zero
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+
+ ################################
+ # | | | | | |a1*a0| |
+ # | | | | |a2*a0| | |
+ # | |a3*a2|a3*a0| | | |
+ # | | | |a2*a1| | | |
+ # | | |a3*a1| | | | |
+ # *| | | | | | | | 2|
+ # +|a3*a3|a2*a2|a1*a1|a0*a0|
+ # |--+--+--+--+--+--+--+--|
+ # |A7|A6|A5|A4|A3|A2|A1|A0|, where Ax is $accx, i.e. follow $accx
+ #
+ # "can't overflow" below mark carrying into high part of
+ # multiplication result, which can't overflow, because it
+ # can never be all ones.
+
+ mulld $acc1,$a1,$a0 # a[1]*a[0]
+ mulhdu $t1,$a1,$a0
+ mulld $acc2,$a2,$a0 # a[2]*a[0]
+ mulhdu $t2,$a2,$a0
+ mulld $acc3,$a3,$a0 # a[3]*a[0]
+ mulhdu $acc4,$a3,$a0
+
+ addc $acc2,$acc2,$t1 # accumulate high parts of multiplication
+ mulld $t0,$a2,$a1 # a[2]*a[1]
+ mulhdu $t1,$a2,$a1
+ adde $acc3,$acc3,$t2
+ mulld $t2,$a3,$a1 # a[3]*a[1]
+ mulhdu $t3,$a3,$a1
+ addze $acc4,$acc4 # can't overflow
+
+ mulld $acc5,$a3,$a2 # a[3]*a[2]
+ mulhdu $acc6,$a3,$a2
+
+ addc $t1,$t1,$t2 # accumulate high parts of multiplication
+ mulld $acc0,$a0,$a0 # a[0]*a[0]
+ addze $t2,$t3 # can't overflow
+
+ addc $acc3,$acc3,$t0 # accumulate low parts of multiplication
+ mulhdu $a0,$a0,$a0
+ adde $acc4,$acc4,$t1
+ mulld $t1,$a1,$a1 # a[1]*a[1]
+ adde $acc5,$acc5,$t2
+ mulhdu $a1,$a1,$a1
+ addze $acc6,$acc6 # can't overflow
+
+ addc $acc1,$acc1,$acc1 # acc[1-6]*=2
+ mulld $t2,$a2,$a2 # a[2]*a[2]
+ adde $acc2,$acc2,$acc2
+ mulhdu $a2,$a2,$a2
+ adde $acc3,$acc3,$acc3
+ mulld $t3,$a3,$a3 # a[3]*a[3]
+ adde $acc4,$acc4,$acc4
+ mulhdu $a3,$a3,$a3
+ adde $acc5,$acc5,$acc5
+ adde $acc6,$acc6,$acc6
+ addze $acc7,$zero
+
+ addc $acc1,$acc1,$a0 # +a[i]*a[i]
+ li $bi,38
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$a1
+ adde $acc4,$acc4,$t2
+ adde $acc5,$acc5,$a2
+ adde $acc6,$acc6,$t3
+ adde $acc7,$acc7,$a3
+
+ mulld $t0,$acc4,$bi
+ mulld $t1,$acc5,$bi
+ mulld $t2,$acc6,$bi
+ mulld $t3,$acc7,$bi
+
+ addc $acc0,$acc0,$t0
+ mulhdu $t0,$acc4,$bi
+ adde $acc1,$acc1,$t1
+ mulhdu $t1,$acc5,$bi
+ adde $acc2,$acc2,$t2
+ mulhdu $t2,$acc6,$bi
+ adde $acc3,$acc3,$t3
+ mulhdu $t3,$acc7,$bi
+ addze $acc4,$zero
+
+ addc $acc1,$acc1,$t0
+ adde $acc2,$acc2,$t1
+ adde $acc3,$acc3,$t2
+ adde $acc4,$acc4,$t3
+
+ mulld $acc4,$acc4,$bi
+
+ addc $acc0,$acc0,$acc4
+ addze $acc1,$acc1
+ addze $acc2,$acc2
+ addze $acc3,$acc3
+
+ subfe $acc4,$acc4,$acc4 # carry -> ~mask
+ std $acc1,8($rp)
+ andc $acc4,$bi,$acc4
+ std $acc2,16($rp)
+ add $acc0,$acc0,$acc4
+ std $acc3,24($rp)
+ std $acc0,0($rp)
+
+ ld r22,`$FRAME-8*10`($sp)
+ ld r23,`$FRAME-8*9`($sp)
+ ld r24,`$FRAME-8*8`($sp)
+ ld r25,`$FRAME-8*7`($sp)
+ ld r26,`$FRAME-8*6`($sp)
+ ld r27,`$FRAME-8*5`($sp)
+ ld r28,`$FRAME-8*4`($sp)
+ ld r29,`$FRAME-8*3`($sp)
+ ld r30,`$FRAME-8*2`($sp)
+ ld r31,`$FRAME-8*1`($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,10,2,0
+ .long 0
+.size x25519_fe64_sqr,.-x25519_fe64_sqr
+
+.globl x25519_fe64_mul121666
+.type x25519_fe64_mul121666,\@function
+.align 5
+x25519_fe64_mul121666:
+ lis $bi,`65536>>16`
+ ori $bi,$bi,`121666-65536`
+
+ ld $t0,0($ap)
+ ld $t1,8($ap)
+ ld $bp,16($ap)
+ ld $ap,24($ap)
+
+ mulld $a0,$t0,$bi
+ mulhdu $t0,$t0,$bi
+ mulld $a1,$t1,$bi
+ mulhdu $t1,$t1,$bi
+ mulld $a2,$bp,$bi
+ mulhdu $bp,$bp,$bi
+ mulld $a3,$ap,$bi
+ mulhdu $ap,$ap,$bi
+
+ addc $a1,$a1,$t0
+ adde $a2,$a2,$t1
+ adde $a3,$a3,$bp
+ addze $ap, $ap
+
+ mulli $ap,$ap,38
+
+ addc $a0,$a0,$ap
+ addze $a1,$a1
+ addze $a2,$a2
+ addze $a3,$a3
+
+ subfe $t1,$t1,$t1 # carry -> ~mask
+ std $a1,8($rp)
+ andc $t0,$t0,$t1
+ std $a2,16($rp)
+ add $a0,$a0,$t0
+ std $a3,24($rp)
+ std $a0,0($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,2,0
+ .long 0
+.size x25519_fe64_mul121666,.-x25519_fe64_mul121666
+
+.globl x25519_fe64_add
+.type x25519_fe64_add,\@function
+.align 5
+x25519_fe64_add:
+ ld $a0,0($ap)
+ ld $t0,0($bp)
+ ld $a1,8($ap)
+ ld $t1,8($bp)
+ ld $a2,16($ap)
+ ld $bi,16($bp)
+ ld $a3,24($ap)
+ ld $bp,24($bp)
+
+ addc $a0,$a0,$t0
+ adde $a1,$a1,$t1
+ adde $a2,$a2,$bi
+ adde $a3,$a3,$bp
+
+ li $t0,38
+ subfe $t1,$t1,$t1 # carry -> ~mask
+ andc $t1,$t0,$t1
+
+ addc $a0,$a0,$t1
+ addze $a1,$a1
+ addze $a2,$a2
+ addze $a3,$a3
+
+ subfe $t1,$t1,$t1 # carry -> ~mask
+ std $a1,8($rp)
+ andc $t0,$t0,$t1
+ std $a2,16($rp)
+ add $a0,$a0,$t0
+ std $a3,24($rp)
+ std $a0,0($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size x25519_fe64_add,.-x25519_fe64_add
+
+.globl x25519_fe64_sub
+.type x25519_fe64_sub,\@function
+.align 5
+x25519_fe64_sub:
+ ld $a0,0($ap)
+ ld $t0,0($bp)
+ ld $a1,8($ap)
+ ld $t1,8($bp)
+ ld $a2,16($ap)
+ ld $bi,16($bp)
+ ld $a3,24($ap)
+ ld $bp,24($bp)
+
+ subfc $a0,$t0,$a0
+ subfe $a1,$t1,$a1
+ subfe $a2,$bi,$a2
+ subfe $a3,$bp,$a3
+
+ li $t0,38
+ subfe $t1,$t1,$t1 # borrow -> mask
+ xor $zero,$zero,$zero
+ and $t1,$t0,$t1
+
+ subfc $a0,$t1,$a0
+ subfe $a1,$zero,$a1
+ subfe $a2,$zero,$a2
+ subfe $a3,$zero,$a3
+
+ subfe $t1,$t1,$t1 # borrow -> mask
+ std $a1,8($rp)
+ and $t0,$t0,$t1
+ std $a2,16($rp)
+ subf $a0,$t0,$a0
+ std $a3,24($rp)
+ std $a0,0($rp)
+
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,3,0
+ .long 0
+.size x25519_fe64_sub,.-x25519_fe64_sub
+
+.globl x25519_fe64_tobytes
+.type x25519_fe64_tobytes,\@function
+.align 5
+x25519_fe64_tobytes:
+ ld $a3,24($ap)
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+
+ sradi $t0,$a3,63 # most significant bit -> mask
+ li $t1,19
+ and $t0,$t0,$t1
+ sldi $a3,$a3,1
+ add $t0,$t0,$t1 # compare to modulus in the same go
+ srdi $a3,$a3,1 # most signifcant bit cleared
+
+ addc $a0,$a0,$t0
+ addze $a1,$a1
+ addze $a2,$a2
+ addze $a3,$a3
+
+ xor $zero,$zero,$zero
+ sradi $t0,$a3,63 # most significant bit -> mask
+ sldi $a3,$a3,1
+ andc $t0,$t1,$t0
+ srdi $a3,$a3,1 # most signifcant bit cleared
+
+ subi $rp,$rp,1
+ subfc $a0,$t0,$a0
+ subfe $a1,$zero,$a1
+ subfe $a2,$zero,$a2
+ subfe $a3,$zero,$a3
+
+___
+for (my @a=($a0,$a1,$a2,$a3), my $i=0; $i<4; shift(@a), $i++) {
+$code.=<<___;
+ srdi $t0,@a[0],8
+ stbu @a[0],1($rp)
+ srdi @a[0],@a[0],16
+ stbu $t0,1($rp)
+ srdi $t0,@a[0],8
+ stbu @a[0],1($rp)
+ srdi @a[0],@a[0],16
+ stbu $t0,1($rp)
+ srdi $t0,@a[0],8
+ stbu @a[0],1($rp)
+ srdi @a[0],@a[0],16
+ stbu $t0,1($rp)
+ srdi $t0,@a[0],8
+ stbu @a[0],1($rp)
+ stbu $t0,1($rp)
+___
+}
+$code.=<<___;
+ blr
+ .long 0
+ .byte 0,12,0x14,0,0,0,2,0
+ .long 0
+.size x25519_fe64_tobytes,.-x25519_fe64_tobytes
+___
+}
+####################################################### base 2^51
+{
+my ($bi,$a0,$a1,$a2,$a3,$a4,$t0, $t1,
+ $h0lo,$h0hi,$h1lo,$h1hi,$h2lo,$h2hi,$h3lo,$h3hi,$h4lo,$h4hi) =
+ map("r$_",(6..12,21..31));
+my $mask = "r0";
+my $FRAME = 18*8;
+
+$code.=<<___;
+.text
+
+.globl x25519_fe51_mul
+.type x25519_fe51_mul,\@function
+.align 5
+x25519_fe51_mul:
+ stdu $sp,-$FRAME($sp)
+ std r21,`$FRAME-8*11`($sp)
+ std r22,`$FRAME-8*10`($sp)
+ std r23,`$FRAME-8*9`($sp)
+ std r24,`$FRAME-8*8`($sp)
+ std r25,`$FRAME-8*7`($sp)
+ std r26,`$FRAME-8*6`($sp)
+ std r27,`$FRAME-8*5`($sp)
+ std r28,`$FRAME-8*4`($sp)
+ std r29,`$FRAME-8*3`($sp)
+ std r30,`$FRAME-8*2`($sp)
+ std r31,`$FRAME-8*1`($sp)
+
+ ld $bi,0($bp)
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+ ld $a4,32($ap)
+
+ mulld $h0lo,$a0,$bi # a[0]*b[0]
+ mulhdu $h0hi,$a0,$bi
+
+ mulld $h1lo,$a1,$bi # a[1]*b[0]
+ mulhdu $h1hi,$a1,$bi
+
+ mulld $h4lo,$a4,$bi # a[4]*b[0]
+ mulhdu $h4hi,$a4,$bi
+ ld $ap,8($bp)
+ mulli $a4,$a4,19
+
+ mulld $h2lo,$a2,$bi # a[2]*b[0]
+ mulhdu $h2hi,$a2,$bi
+
+ mulld $h3lo,$a3,$bi # a[3]*b[0]
+ mulhdu $h3hi,$a3,$bi
+___
+for(my @a=($a0,$a1,$a2,$a3,$a4),
+ my $i=1; $i<4; $i++) {
+ ($ap,$bi) = ($bi,$ap);
+$code.=<<___;
+ mulld $t0,@a[4],$bi
+ mulhdu $t1,@a[4],$bi
+ addc $h0lo,$h0lo,$t0
+ adde $h0hi,$h0hi,$t1
+
+ mulld $t0,@a[0],$bi
+ mulhdu $t1,@a[0],$bi
+ addc $h1lo,$h1lo,$t0
+ adde $h1hi,$h1hi,$t1
+
+ mulld $t0,@a[3],$bi
+ mulhdu $t1,@a[3],$bi
+ ld $ap,`8*($i+1)`($bp)
+ mulli @a[3],@a[3],19
+ addc $h4lo,$h4lo,$t0
+ adde $h4hi,$h4hi,$t1
+
+ mulld $t0,@a[1],$bi
+ mulhdu $t1,@a[1],$bi
+ addc $h2lo,$h2lo,$t0
+ adde $h2hi,$h2hi,$t1
+
+ mulld $t0,@a[2],$bi
+ mulhdu $t1,@a[2],$bi
+ addc $h3lo,$h3lo,$t0
+ adde $h3hi,$h3hi,$t1
+___
+ unshift(@a,pop(@a));
+}
+ ($ap,$bi) = ($bi,$ap);
+$code.=<<___;
+ mulld $t0,$a1,$bi
+ mulhdu $t1,$a1,$bi
+ addc $h0lo,$h0lo,$t0
+ adde $h0hi,$h0hi,$t1
+
+ mulld $t0,$a2,$bi
+ mulhdu $t1,$a2,$bi
+ addc $h1lo,$h1lo,$t0
+ adde $h1hi,$h1hi,$t1
+
+ mulld $t0,$a3,$bi
+ mulhdu $t1,$a3,$bi
+ addc $h2lo,$h2lo,$t0
+ adde $h2hi,$h2hi,$t1
+
+ mulld $t0,$a4,$bi
+ mulhdu $t1,$a4,$bi
+ addc $h3lo,$h3lo,$t0
+ adde $h3hi,$h3hi,$t1
+
+ mulld $t0,$a0,$bi
+ mulhdu $t1,$a0,$bi
+ addc $h4lo,$h4lo,$t0
+ adde $h4hi,$h4hi,$t1
+
+.Lfe51_reduce:
+ li $mask,-1
+ srdi $mask,$mask,13 # 0x7ffffffffffff
+
+ srdi $t0,$h2lo,51
+ and $a2,$h2lo,$mask
+ insrdi $t0,$h2hi,51,0 # h2>>51
+ srdi $t1,$h0lo,51
+ and $a0,$h0lo,$mask
+ insrdi $t1,$h0hi,51,0 # h0>>51
+ addc $h3lo,$h3lo,$t0
+ addze $h3hi,$h3hi
+ addc $h1lo,$h1lo,$t1
+ addze $h1hi,$h1hi
+
+ srdi $t0,$h3lo,51
+ and $a3,$h3lo,$mask
+ insrdi $t0,$h3hi,51,0 # h3>>51
+ srdi $t1,$h1lo,51
+ and $a1,$h1lo,$mask
+ insrdi $t1,$h1hi,51,0 # h1>>51
+ addc $h4lo,$h4lo,$t0
+ addze $h4hi,$h4hi
+ add $a2,$a2,$t1
+
+ srdi $t0,$h4lo,51
+ and $a4,$h4lo,$mask
+ insrdi $t0,$h4hi,51,0
+ mulli $t0,$t0,19 # (h4 >> 51) * 19
+
+ add $a0,$a0,$t0
+
+ srdi $t1,$a2,51
+ and $a2,$a2,$mask
+ add $a3,$a3,$t1
+
+ srdi $t0,$a0,51
+ and $a0,$a0,$mask
+ add $a1,$a1,$t0
+
+ std $a2,16($rp)
+ std $a3,24($rp)
+ std $a4,32($rp)
+ std $a0,0($rp)
+ std $a1,8($rp)
+
+ ld r21,`$FRAME-8*11`($sp)
+ ld r22,`$FRAME-8*10`($sp)
+ ld r23,`$FRAME-8*9`($sp)
+ ld r24,`$FRAME-8*8`($sp)
+ ld r25,`$FRAME-8*7`($sp)
+ ld r26,`$FRAME-8*6`($sp)
+ ld r27,`$FRAME-8*5`($sp)
+ ld r28,`$FRAME-8*4`($sp)
+ ld r29,`$FRAME-8*3`($sp)
+ ld r30,`$FRAME-8*2`($sp)
+ ld r31,`$FRAME-8*1`($sp)
+ addi $sp,$sp,$FRAME
+ blr
+ .long 0
+ .byte 0,12,4,0,0x80,11,3,0
+ .long 0
+.size x25519_fe51_mul,.-x25519_fe51_mul
+___
+{
+my ($a0,$a1,$a2,$a3,$a4,$t0,$t1) = ($a0,$a1,$a2,$a3,$a4,$t0,$t1);
+$code.=<<___;
+.globl x25519_fe51_sqr
+.type x25519_fe51_sqr,\@function
+.align 5
+x25519_fe51_sqr:
+ stdu $sp,-$FRAME($sp)
+ std r21,`$FRAME-8*11`($sp)
+ std r22,`$FRAME-8*10`($sp)
+ std r23,`$FRAME-8*9`($sp)
+ std r24,`$FRAME-8*8`($sp)
+ std r25,`$FRAME-8*7`($sp)
+ std r26,`$FRAME-8*6`($sp)
+ std r27,`$FRAME-8*5`($sp)
+ std r28,`$FRAME-8*4`($sp)
+ std r29,`$FRAME-8*3`($sp)
+ std r30,`$FRAME-8*2`($sp)
+ std r31,`$FRAME-8*1`($sp)
+
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+ ld $a4,32($ap)
+
+ add $bi,$a0,$a0 # a[0]*2
+ mulli $t1,$a4,19 # a[4]*19
+
+ mulld $h0lo,$a0,$a0
+ mulhdu $h0hi,$a0,$a0
+ mulld $h1lo,$a1,$bi
+ mulhdu $h1hi,$a1,$bi
+ mulld $h2lo,$a2,$bi
+ mulhdu $h2hi,$a2,$bi
+ mulld $h3lo,$a3,$bi
+ mulhdu $h3hi,$a3,$bi
+ mulld $h4lo,$a4,$bi
+ mulhdu $h4hi,$a4,$bi
+ add $bi,$a1,$a1 # a[1]*2
+___
+ ($a4,$t1) = ($t1,$a4);
+$code.=<<___;
+ mulld $t0,$t1,$a4
+ mulhdu $t1,$t1,$a4
+ addc $h3lo,$h3lo,$t0
+ adde $h3hi,$h3hi,$t1
+
+ mulli $bp,$a3,19 # a[3]*19
+
+ mulld $t0,$a1,$a1
+ mulhdu $t1,$a1,$a1
+ addc $h2lo,$h2lo,$t0
+ adde $h2hi,$h2hi,$t1
+ mulld $t0,$a2,$bi
+ mulhdu $t1,$a2,$bi
+ addc $h3lo,$h3lo,$t0
+ adde $h3hi,$h3hi,$t1
+ mulld $t0,$a3,$bi
+ mulhdu $t1,$a3,$bi
+ addc $h4lo,$h4lo,$t0
+ adde $h4hi,$h4hi,$t1
+ mulld $t0,$a4,$bi
+ mulhdu $t1,$a4,$bi
+ add $bi,$a3,$a3 # a[3]*2
+ addc $h0lo,$h0lo,$t0
+ adde $h0hi,$h0hi,$t1
+___
+ ($a3,$t1) = ($bp,$a3);
+$code.=<<___;
+ mulld $t0,$t1,$a3
+ mulhdu $t1,$t1,$a3
+ addc $h1lo,$h1lo,$t0
+ adde $h1hi,$h1hi,$t1
+ mulld $t0,$bi,$a4
+ mulhdu $t1,$bi,$a4
+ add $bi,$a2,$a2 # a[2]*2
+ addc $h2lo,$h2lo,$t0
+ adde $h2hi,$h2hi,$t1
+
+ mulld $t0,$a2,$a2
+ mulhdu $t1,$a2,$a2
+ addc $h4lo,$h4lo,$t0
+ adde $h4hi,$h4hi,$t1
+ mulld $t0,$a3,$bi
+ mulhdu $t1,$a3,$bi
+ addc $h0lo,$h0lo,$t0
+ adde $h0hi,$h0hi,$t1
+ mulld $t0,$a4,$bi
+ mulhdu $t1,$a4,$bi
+ addc $h1lo,$h1lo,$t0
+ adde $h1hi,$h1hi,$t1
+
+ b .Lfe51_reduce
+ .long 0
+ .byte 0,12,4,0,0x80,11,2,0
+ .long 0
+.size x25519_fe51_sqr,.-x25519_fe51_sqr
+___
+}
+$code.=<<___;
+.globl x25519_fe51_mul121666
+.type x25519_fe51_mul121666,\@function
+.align 5
+x25519_fe51_mul121666:
+ stdu $sp,-$FRAME($sp)
+ std r21,`$FRAME-8*11`($sp)
+ std r22,`$FRAME-8*10`($sp)
+ std r23,`$FRAME-8*9`($sp)
+ std r24,`$FRAME-8*8`($sp)
+ std r25,`$FRAME-8*7`($sp)
+ std r26,`$FRAME-8*6`($sp)
+ std r27,`$FRAME-8*5`($sp)
+ std r28,`$FRAME-8*4`($sp)
+ std r29,`$FRAME-8*3`($sp)
+ std r30,`$FRAME-8*2`($sp)
+ std r31,`$FRAME-8*1`($sp)
+
+ lis $bi,`65536>>16`
+ ori $bi,$bi,`121666-65536`
+ ld $a0,0($ap)
+ ld $a1,8($ap)
+ ld $a2,16($ap)
+ ld $a3,24($ap)
+ ld $a4,32($ap)
+
+ mulld $h0lo,$a0,$bi # a[0]*121666
+ mulhdu $h0hi,$a0,$bi
+ mulld $h1lo,$a1,$bi # a[1]*121666
+ mulhdu $h1hi,$a1,$bi
+ mulld $h2lo,$a2,$bi # a[2]*121666
+ mulhdu $h2hi,$a2,$bi
+ mulld $h3lo,$a3,$bi # a[3]*121666
+ mulhdu $h3hi,$a3,$bi
+ mulld $h4lo,$a4,$bi # a[4]*121666
+ mulhdu $h4hi,$a4,$bi
+
+ b .Lfe51_reduce
+ .long 0
+ .byte 0,12,4,0,0x80,11,2,0
+ .long 0
+.size x25519_fe51_mul121666,.-x25519_fe51_mul121666
+___
+}
+
+$code =~ s/\`([^\`]*)\`/eval $1/gem;
+print $code;
+close STDOUT;
diff --git a/deps/openssl/openssl/crypto/ec/asm/x25519-x86_64.pl b/deps/openssl/openssl/crypto/ec/asm/x25519-x86_64.pl
new file mode 100755
index 0000000000..18dc6af9fa
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/asm/x25519-x86_64.pl
@@ -0,0 +1,1117 @@
+#!/usr/bin/env perl
+# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# X25519 lower-level primitives for x86_64.
+#
+# February 2018.
+#
+# This module implements radix 2^51 multiplication and squaring, and
+# radix 2^64 multiplication, squaring, addition, subtraction and final
+# reduction. Latter radix is used on ADCX/ADOX-capable processors such
+# as Broadwell. On related note one should mention that there are
+# vector implementations that provide significantly better performance
+# on some processors(*), but they are large and overly complex. Which
+# in combination with them being effectively processor-specific makes
+# the undertaking hard to justify. The goal for this implementation
+# is rather versatility and simplicity [and ultimately formal
+# verification].
+#
+# (*) For example sandy2x should provide ~30% improvement on Sandy
+# Bridge, but only nominal ~5% on Haswell [and big loss on
+# Broadwell and successors].
+#
+######################################################################
+# Improvement coefficients:
+#
+# amd64-51(*) gcc-5.x(**)
+#
+# P4 +22% +40%
+# Sandy Bridge -3% +11%
+# Haswell -1% +13%
+# Broadwell(***) +30% +35%
+# Skylake(***) +33% +47%
+# Silvermont +20% +26%
+# Goldmont +40% +50%
+# Bulldozer +20% +9%
+# Ryzen(***) +43% +40%
+# VIA +170% +120%
+#
+# (*) amd64-51 is popular assembly implementation with 2^51 radix,
+# only multiplication and squaring subroutines were linked
+# for comparison, but not complete ladder step; gain on most
+# processors is because this module refrains from shld, and
+# minor regression on others is because this does result in
+# higher instruction count;
+# (**) compiler is free to inline functions, in assembly one would
+# need to implement ladder step to do that, and it will improve
+# performance by several percent;
+# (***) ADCX/ADOX result for 2^64 radix, there is no corresponding
+# C implementation, so that comparison is always against
+# 2^51 radix;
+
+$flavour = shift;
+$output = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+*STDOUT=*OUT;
+
+if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.23);
+}
+
+if (!$addx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
+ $addx = ($1>=2.10);
+}
+
+if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
+ $addx = ($1>=12);
+}
+
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
+ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
+ $addx = ($ver>=3.03);
+}
+
+$code.=<<___;
+.text
+
+.globl x25519_fe51_mul
+.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]
+ mov 8*1(%rdx),%r12
+ mov 8*2(%rdx),%r13
+ mov 8*3(%rdx),%rbp
+ mov 8*4(%rdx),%r14
+
+ mov %rdi,8*4(%rsp) # offload 1st argument
+ mov %rax,%rdi
+ mulq %r11 # f[0]*g[0]
+ mov %r11,8*0(%rsp) # offload g[0]
+ mov %rax,%rbx # %rbx:%rcx = h0
+ mov %rdi,%rax
+ mov %rdx,%rcx
+ mulq %r12 # f[0]*g[1]
+ mov %r12,8*1(%rsp) # offload g[1]
+ mov %rax,%r8 # %r8:%r9 = h1
+ mov %rdi,%rax
+ lea (%r14,%r14,8),%r15
+ mov %rdx,%r9
+ mulq %r13 # f[0]*g[2]
+ mov %r13,8*2(%rsp) # offload g[2]
+ mov %rax,%r10 # %r10:%r11 = h2
+ mov %rdi,%rax
+ lea (%r14,%r15,2),%rdi # g[4]*19
+ mov %rdx,%r11
+ mulq %rbp # f[0]*g[3]
+ mov %rax,%r12 # %r12:%r13 = h3
+ mov 8*0(%rsi),%rax # f[0]
+ mov %rdx,%r13
+ mulq %r14 # f[0]*g[4]
+ mov %rax,%r14 # %r14:%r15 = h4
+ mov 8*1(%rsi),%rax # f[1]
+ mov %rdx,%r15
+
+ mulq %rdi # f[1]*g[4]*19
+ add %rax,%rbx
+ mov 8*2(%rsi),%rax # f[2]
+ adc %rdx,%rcx
+ mulq %rdi # f[2]*g[4]*19
+ add %rax,%r8
+ mov 8*3(%rsi),%rax # f[3]
+ adc %rdx,%r9
+ mulq %rdi # f[3]*g[4]*19
+ add %rax,%r10
+ mov 8*4(%rsi),%rax # f[4]
+ adc %rdx,%r11
+ mulq %rdi # f[4]*g[4]*19
+ imulq \$19,%rbp,%rdi # g[3]*19
+ add %rax,%r12
+ mov 8*1(%rsi),%rax # f[1]
+ adc %rdx,%r13
+ mulq %rbp # f[1]*g[3]
+ mov 8*2(%rsp),%rbp # g[2]
+ add %rax,%r14
+ mov 8*2(%rsi),%rax # f[2]
+ adc %rdx,%r15
+
+ mulq %rdi # f[2]*g[3]*19
+ add %rax,%rbx
+ mov 8*3(%rsi),%rax # f[3]
+ adc %rdx,%rcx
+ mulq %rdi # f[3]*g[3]*19
+ add %rax,%r8
+ mov 8*4(%rsi),%rax # f[4]
+ adc %rdx,%r9
+ mulq %rdi # f[4]*g[3]*19
+ imulq \$19,%rbp,%rdi # g[2]*19
+ add %rax,%r10
+ mov 8*1(%rsi),%rax # f[1]
+ adc %rdx,%r11
+ mulq %rbp # f[1]*g[2]
+ add %rax,%r12
+ mov 8*2(%rsi),%rax # f[2]
+ adc %rdx,%r13
+ mulq %rbp # f[2]*g[2]
+ mov 8*1(%rsp),%rbp # g[1]
+ add %rax,%r14
+ mov 8*3(%rsi),%rax # f[3]
+ adc %rdx,%r15
+
+ mulq %rdi # f[3]*g[2]*19
+ add %rax,%rbx
+ mov 8*4(%rsi),%rax # f[3]
+ adc %rdx,%rcx
+ mulq %rdi # f[4]*g[2]*19
+ add %rax,%r8
+ mov 8*1(%rsi),%rax # f[1]
+ adc %rdx,%r9
+ mulq %rbp # f[1]*g[1]
+ imulq \$19,%rbp,%rdi
+ add %rax,%r10
+ mov 8*2(%rsi),%rax # f[2]
+ adc %rdx,%r11
+ mulq %rbp # f[2]*g[1]
+ add %rax,%r12
+ mov 8*3(%rsi),%rax # f[3]
+ adc %rdx,%r13
+ mulq %rbp # f[3]*g[1]
+ mov 8*0(%rsp),%rbp # g[0]
+ add %rax,%r14
+ mov 8*4(%rsi),%rax # f[4]
+ adc %rdx,%r15
+
+ mulq %rdi # f[4]*g[1]*19
+ add %rax,%rbx
+ mov 8*1(%rsi),%rax # f[1]
+ adc %rdx,%rcx
+ mul %rbp # f[1]*g[0]
+ add %rax,%r8
+ mov 8*2(%rsi),%rax # f[2]
+ adc %rdx,%r9
+ mul %rbp # f[2]*g[0]
+ add %rax,%r10
+ mov 8*3(%rsi),%rax # f[3]
+ adc %rdx,%r11
+ mul %rbp # f[3]*g[0]
+ add %rax,%r12
+ mov 8*4(%rsi),%rax # f[4]
+ adc %rdx,%r13
+ mulq %rbp # f[4]*g[0]
+ add %rax,%r14
+ adc %rdx,%r15
+
+ 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]
+ mov 8*4(%rsi),%rbp # g[4]
+
+ mov %rdi,8*4(%rsp) # offload 1st argument
+ lea (%rax,%rax),%r14
+ mulq %rax # g[0]*g[0]
+ mov %rax,%rbx
+ mov 8*1(%rsi),%rax # g[1]
+ mov %rdx,%rcx
+ mulq %r14 # 2*g[0]*g[1]
+ mov %rax,%r8
+ mov %r15,%rax
+ mov %r15,8*0(%rsp) # offload g[2]
+ mov %rdx,%r9
+ mulq %r14 # 2*g[0]*g[2]
+ mov %rax,%r10
+ mov 8*3(%rsi),%rax
+ mov %rdx,%r11
+ imulq \$19,%rbp,%rdi # g[4]*19
+ mulq %r14 # 2*g[0]*g[3]
+ mov %rax,%r12
+ mov %rbp,%rax
+ mov %rdx,%r13
+ mulq %r14 # 2*g[0]*g[4]
+ mov %rax,%r14
+ mov %rbp,%rax
+ mov %rdx,%r15
+
+ mulq %rdi # g[4]*g[4]*19
+ add %rax,%r12
+ mov 8*1(%rsi),%rax # g[1]
+ adc %rdx,%r13
+
+ mov 8*3(%rsi),%rsi # g[3]
+ lea (%rax,%rax),%rbp
+ mulq %rax # g[1]*g[1]
+ add %rax,%r10
+ mov 8*0(%rsp),%rax # g[2]
+ adc %rdx,%r11
+ mulq %rbp # 2*g[1]*g[2]
+ add %rax,%r12
+ mov %rbp,%rax
+ adc %rdx,%r13
+ mulq %rsi # 2*g[1]*g[3]
+ add %rax,%r14
+ mov %rbp,%rax
+ adc %rdx,%r15
+ imulq \$19,%rsi,%rbp # g[3]*19
+ mulq %rdi # 2*g[1]*g[4]*19
+ add %rax,%rbx
+ lea (%rsi,%rsi),%rax
+ adc %rdx,%rcx
+
+ mulq %rdi # 2*g[3]*g[4]*19
+ add %rax,%r10
+ mov %rsi,%rax
+ adc %rdx,%r11
+ mulq %rbp # g[3]*g[3]*19
+ add %rax,%r8
+ mov 8*0(%rsp),%rax # g[2]
+ adc %rdx,%r9
+
+ lea (%rax,%rax),%rsi
+ mulq %rax # g[2]*g[2]
+ add %rax,%r14
+ mov %rbp,%rax
+ adc %rdx,%r15
+ mulq %rsi # 2*g[2]*g[3]*19
+ add %rax,%rbx
+ mov %rsi,%rax
+ adc %rdx,%rcx
+ mulq %rdi # 2*g[2]*g[4]*19
+ add %rax,%r8
+ adc %rdx,%r9
+
+ mov 8*4(%rsp),%rdi # restore 1st argument
+ jmp .Lreduce51
+
+.align 32
+.Lreduce51:
+ mov \$0x7ffffffffffff,%rbp
+
+ mov %r10,%rdx
+ shr \$51,%r10
+ shl \$13,%r11
+ and %rbp,%rdx # %rdx = g2 = h2 & mask
+ or %r10,%r11 # h2>>51
+ add %r11,%r12
+ adc \$0,%r13 # h3 += h2>>51
+
+ mov %rbx,%rax
+ shr \$51,%rbx
+ shl \$13,%rcx
+ and %rbp,%rax # %rax = g0 = h0 & mask
+ or %rbx,%rcx # h0>>51
+ add %rcx,%r8 # h1 += h0>>51
+ adc \$0,%r9
+
+ mov %r12,%rbx
+ shr \$51,%r12
+ shl \$13,%r13
+ and %rbp,%rbx # %rbx = g3 = h3 & mask
+ or %r12,%r13 # h3>>51
+ add %r13,%r14 # h4 += h3>>51
+ adc \$0,%r15
+
+ mov %r8,%rcx
+ shr \$51,%r8
+ shl \$13,%r9
+ and %rbp,%rcx # %rcx = g1 = h1 & mask
+ or %r8,%r9
+ add %r9,%rdx # g2 += h1>>51
+
+ mov %r14,%r10
+ shr \$51,%r14
+ shl \$13,%r15
+ and %rbp,%r10 # %r10 = g4 = h0 & mask
+ or %r14,%r15 # h0>>51
+
+ lea (%r15,%r15,8),%r14
+ lea (%r15,%r14,2),%r15
+ add %r15,%rax # g0 += (h0>>51)*19
+
+ mov %rdx,%r8
+ and %rbp,%rdx # g2 &= mask
+ shr \$51,%r8
+ add %r8,%rbx # g3 += g2>>51
+
+ mov %rax,%r9
+ and %rbp,%rax # g0 &= mask
+ shr \$51,%r9
+ add %r9,%rcx # g1 += g0>>51
+
+ mov %rax,8*0(%rdi) # save the result
+ mov %rcx,8*1(%rdi)
+ mov %rdx,8*2(%rdi)
+ mov %rbx,8*3(%rdi)
+ 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
+.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
+ mov \$121666,%eax
+ mov %rdx,%rcx
+ mulq 8*1(%rsi)
+ mov %rax,%r8 # %r8:%r9 = h1
+ mov \$121666,%eax
+ mov %rdx,%r9
+ mulq 8*2(%rsi)
+ mov %rax,%r10 # %r10:%r11 = h2
+ mov \$121666,%eax
+ mov %rdx,%r11
+ mulq 8*3(%rsi)
+ mov %rax,%r12 # %r12:%r13 = h3
+ mov \$121666,%eax # f[0]
+ mov %rdx,%r13
+ mulq 8*4(%rsi)
+ mov %rax,%r14 # %r14:%r15 = h4
+ mov %rdx,%r15
+
+ jmp .Lreduce51
+.Lfe51_mul121666_epilogue:
+.cfi_endproc
+.size x25519_fe51_mul121666,.-x25519_fe51_mul121666
+___
+########################################################################
+# Base 2^64 subroutines modulo 2*(2^255-19)
+#
+if ($addx) {
+my ($acc0,$acc1,$acc2,$acc3,$acc4,$acc5,$acc6,$acc7) = map("%r$_",(8..15));
+
+$code.=<<___;
+.extern OPENSSL_ia32cap_P
+.globl x25519_fe64_eligible
+.type x25519_fe64_eligible,\@abi-omnipotent
+.align 32
+x25519_fe64_eligible:
+ mov OPENSSL_ia32cap_P+8(%rip),%ecx
+ xor %eax,%eax
+ and \$0x80100,%ecx
+ cmp \$0x80100,%ecx
+ cmove %ecx,%eax
+ ret
+.size x25519_fe64_eligible,.-x25519_fe64_eligible
+
+.globl x25519_fe64_mul
+.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]
+ mov 8*0(%rsi),%rdx # a[0]
+ mov 8*1(%rax),%rcx # b[1]
+ mov 8*2(%rax),$acc6 # b[2]
+ mov 8*3(%rax),$acc7 # b[3]
+
+ mulx %rbp,$acc0,%rax # a[0]*b[0]
+ xor %edi,%edi # cf=0,of=0
+ mulx %rcx,$acc1,%rbx # a[0]*b[1]
+ adcx %rax,$acc1
+ mulx $acc6,$acc2,%rax # a[0]*b[2]
+ adcx %rbx,$acc2
+ mulx $acc7,$acc3,$acc4 # a[0]*b[3]
+ mov 8*1(%rsi),%rdx # a[1]
+ adcx %rax,$acc3
+ mov $acc6,(%rsp) # offload b[2]
+ adcx %rdi,$acc4 # cf=0
+
+ mulx %rbp,%rax,%rbx # a[1]*b[0]
+ adox %rax,$acc1
+ adcx %rbx,$acc2
+ mulx %rcx,%rax,%rbx # a[1]*b[1]
+ adox %rax,$acc2
+ adcx %rbx,$acc3
+ mulx $acc6,%rax,%rbx # a[1]*b[2]
+ adox %rax,$acc3
+ adcx %rbx,$acc4
+ mulx $acc7,%rax,$acc5 # a[1]*b[3]
+ mov 8*2(%rsi),%rdx # a[2]
+ adox %rax,$acc4
+ adcx %rdi,$acc5 # cf=0
+ adox %rdi,$acc5 # of=0
+
+ mulx %rbp,%rax,%rbx # a[2]*b[0]
+ adcx %rax,$acc2
+ adox %rbx,$acc3
+ mulx %rcx,%rax,%rbx # a[2]*b[1]
+ adcx %rax,$acc3
+ adox %rbx,$acc4
+ mulx $acc6,%rax,%rbx # a[2]*b[2]
+ adcx %rax,$acc4
+ adox %rbx,$acc5
+ mulx $acc7,%rax,$acc6 # a[2]*b[3]
+ mov 8*3(%rsi),%rdx # a[3]
+ adcx %rax,$acc5
+ adox %rdi,$acc6 # of=0
+ adcx %rdi,$acc6 # cf=0
+
+ mulx %rbp,%rax,%rbx # a[3]*b[0]
+ adox %rax,$acc3
+ adcx %rbx,$acc4
+ mulx %rcx,%rax,%rbx # a[3]*b[1]
+ adox %rax,$acc4
+ adcx %rbx,$acc5
+ mulx (%rsp),%rax,%rbx # a[3]*b[2]
+ adox %rax,$acc5
+ adcx %rbx,$acc6
+ mulx $acc7,%rax,$acc7 # a[3]*b[3]
+ mov \$38,%edx
+ adox %rax,$acc6
+ adcx %rdi,$acc7 # cf=0
+ 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]
+ mov 8*2(%rsi),%rbp # a[2]
+ mov 8*3(%rsi),%rsi # a[3]
+
+ ################################################################
+ mulx %rdx,$acc0,$acc7 # a[0]*a[0]
+ mulx %rcx,$acc1,%rax # a[0]*a[1]
+ xor %edi,%edi # cf=0,of=0
+ mulx %rbp,$acc2,%rbx # a[0]*a[2]
+ adcx %rax,$acc2
+ mulx %rsi,$acc3,$acc4 # a[0]*a[3]
+ mov %rcx,%rdx # a[1]
+ adcx %rbx,$acc3
+ adcx %rdi,$acc4 # cf=0
+
+ ################################################################
+ mulx %rbp,%rax,%rbx # a[1]*a[2]
+ adox %rax,$acc3
+ adcx %rbx,$acc4
+ mulx %rsi,%rax,$acc5 # a[1]*a[3]
+ mov %rbp,%rdx # a[2]
+ adox %rax,$acc4
+ adcx %rdi,$acc5
+
+ ################################################################
+ mulx %rsi,%rax,$acc6 # a[2]*a[3]
+ mov %rcx,%rdx # a[1]
+ adox %rax,$acc5
+ adcx %rdi,$acc6 # cf=0
+ adox %rdi,$acc6 # of=0
+
+ adcx $acc1,$acc1 # acc1:6<<1
+ adox $acc7,$acc1
+ adcx $acc2,$acc2
+ mulx %rdx,%rax,%rbx # a[1]*a[1]
+ mov %rbp,%rdx # a[2]
+ adcx $acc3,$acc3
+ adox %rax,$acc2
+ adcx $acc4,$acc4
+ adox %rbx,$acc3
+ mulx %rdx,%rax,%rbx # a[2]*a[2]
+ mov %rsi,%rdx # a[3]
+ adcx $acc5,$acc5
+ adox %rax,$acc4
+ adcx $acc6,$acc6
+ adox %rbx,$acc5
+ mulx %rdx,%rax,$acc7 # a[3]*a[3]
+ mov \$38,%edx
+ adox %rax,$acc6
+ adcx %rdi,$acc7 # cf=0
+ adox %rdi,$acc7 # of=0
+ jmp .Lreduce64
+
+.align 32
+.Lreduce64:
+ mulx $acc4,%rax,%rbx
+ adcx %rax,$acc0
+ adox %rbx,$acc1
+ mulx $acc5,%rax,%rbx
+ adcx %rax,$acc1
+ adox %rbx,$acc2
+ mulx $acc6,%rax,%rbx
+ adcx %rax,$acc2
+ adox %rbx,$acc3
+ mulx $acc7,%rax,$acc4
+ adcx %rax,$acc3
+ adox %rdi,$acc4
+ adcx %rdi,$acc4
+
+ mov 8*2(%rsp),%rdi # restore dst
+ imulq %rdx,$acc4
+
+ add $acc4,$acc0
+ adc \$0,$acc1
+ adc \$0,$acc2
+ adc \$0,$acc3
+
+ sbb %rax,%rax # cf -> mask
+ and \$38,%rax
+
+ add %rax,$acc0
+ mov $acc1,8*1(%rdi)
+ mov $acc2,8*2(%rdi)
+ mov $acc3,8*3(%rdi)
+ 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
+ add %rcx,$acc1
+ mulx 8*2(%rsi),$acc2,%rcx
+ adc %rax,$acc2
+ mulx 8*3(%rsi),$acc3,%rax
+ adc %rcx,$acc3
+ adc \$0,%rax
+
+ imulq \$38,%rax,%rax
+
+ add %rax,$acc0
+ adc \$0,$acc1
+ adc \$0,$acc2
+ adc \$0,$acc3
+
+ sbb %rax,%rax # cf -> mask
+ and \$38,%rax
+
+ add %rax,$acc0
+ mov $acc1,8*1(%rdi)
+ mov $acc2,8*2(%rdi)
+ mov $acc3,8*3(%rdi)
+ mov $acc0,8*0(%rdi)
+
+.Lfe64_mul121666_epilogue:
+ ret
+.size x25519_fe64_mul121666,.-x25519_fe64_mul121666
+
+.globl x25519_fe64_add
+.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
+ mov 8*3(%rsi),$acc3
+
+ add 8*0(%rdx),$acc0
+ adc 8*1(%rdx),$acc1
+ adc 8*2(%rdx),$acc2
+ adc 8*3(%rdx),$acc3
+
+ sbb %rax,%rax # cf -> mask
+ and \$38,%rax
+
+ add %rax,$acc0
+ adc \$0,$acc1
+ 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
+
+.globl x25519_fe64_sub
+.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
+ mov 8*3(%rsi),$acc3
+
+ sub 8*0(%rdx),$acc0
+ sbb 8*1(%rdx),$acc1
+ sbb 8*2(%rdx),$acc2
+ sbb 8*3(%rdx),$acc3
+
+ sbb %rax,%rax # cf -> mask
+ and \$38,%rax
+
+ sub %rax,$acc0
+ sbb \$0,$acc1
+ 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
+
+.globl x25519_fe64_tobytes
+.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
+ mov 8*3(%rsi),$acc3
+
+ ################################# reduction modulo 2^255-19
+ lea ($acc3,$acc3),%rax
+ 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
+ adc \$0,$acc2
+ adc \$0,%rax
+
+ lea (%rax,%rax),$acc3
+ sar \$63,%rax # most significant bit -> mask
+ shr \$1,$acc3 # most significant bit cleared
+ not %rax
+ and \$19,%rax
+
+ 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)
+
+.Lfe64_to_epilogue:
+ ret
+.size x25519_fe64_tobytes,.-x25519_fe64_tobytes
+___
+} else {
+$code.=<<___;
+.globl x25519_fe64_eligible
+.type x25519_fe64_eligible,\@abi-omnipotent
+.align 32
+x25519_fe64_eligible:
+ xor %eax,%eax
+ ret
+.size x25519_fe64_eligible,.-x25519_fe64_eligible
+
+.globl x25519_fe64_mul
+.type x25519_fe64_mul,\@abi-omnipotent
+.globl x25519_fe64_sqr
+.globl x25519_fe64_mul121666
+.globl x25519_fe64_add
+.globl x25519_fe64_sub
+.globl x25519_fe64_tobytes
+x25519_fe64_mul:
+x25519_fe64_sqr:
+x25519_fe64_mul121666:
+x25519_fe64_add:
+x25519_fe64_sub:
+x25519_fe64_tobytes:
+ .byte 0x0f,0x0b # ud2
+ ret
+.size x25519_fe64_mul,.-x25519_fe64_mul
+___
+}
+$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;
diff --git a/deps/openssl/openssl/crypto/ec/build.info b/deps/openssl/openssl/crypto/ec/build.info
index 970c2922cc..a1e673e347 100644
--- a/deps/openssl/openssl/crypto/ec/build.info
+++ b/deps/openssl/openssl/crypto/ec/build.info
@@ -2,13 +2,16 @@ LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \
- ec2_smpl.c ec2_mult.c ec_ameth.c ec_pmeth.c eck_prn.c \
+ ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \
ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \
ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \
ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \
+ curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
+ curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
{- $target{ec_asm_src} -}
-GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl $(PERLASM_SCHEME) $(CFLAGS) $(LIB_CFLAGS) $(PROCESSOR)
+GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl \
+ $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl $(PERLASM_SCHEME)
@@ -21,8 +24,19 @@ GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl $(PERLASM_SCHEME)
INCLUDE[ecp_nistz256-armv4.o]=..
GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl $(PERLASM_SCHEME)
INCLUDE[ecp_nistz256-armv8.o]=..
+GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl $(PERLASM_SCHEME)
+
+GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl $(PERLASM_SCHEME)
+GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl $(PERLASM_SCHEME)
BEGINRAW[Makefile]
{- $builddir -}/ecp_nistz256-%.S: {- $sourcedir -}/asm/ecp_nistz256-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
ENDRAW[Makefile]
+
+INCLUDE[curve448/arch_32/f_impl.o]=curve448/arch_32 curve448
+INCLUDE[curve448/f_generic.o]=curve448/arch_32 curve448
+INCLUDE[curve448/scalar.o]=curve448/arch_32 curve448
+INCLUDE[curve448/curve448_tables.o]=curve448/arch_32 curve448
+INCLUDE[curve448/eddsa.o]=curve448/arch_32 curve448
+INCLUDE[curve448/curve448.o]=curve448/arch_32 curve448
diff --git a/deps/openssl/openssl/crypto/ec/curve25519.c b/deps/openssl/openssl/crypto/ec/curve25519.c
index c8aa9aa6d5..abe9b9cbf6 100644
--- a/deps/openssl/openssl/crypto/ec/curve25519.c
+++ b/deps/openssl/openssl/crypto/ec/curve25519.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,14 +7,750 @@
* https://www.openssl.org/source/license.html
*/
-/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
- * 20141124 (http://bench.cr.yp.to/supercop.html).
- *
- * The field functions are shared by Ed25519 and X25519 where possible. */
-
#include <string.h>
#include "ec_lcl.h"
+#include <openssl/sha.h>
+
+#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64))
+
+# define BASE_2_64_IMPLEMENTED
+
+typedef uint64_t fe64[4];
+
+int x25519_fe64_eligible(void);
+
+/*
+ * 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);
+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
+
+static uint64_t load_8(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;
+ result |= ((uint64_t)in[7]) << 56;
+
+ return result;
+}
+
+static void fe64_frombytes(fe64 h, const uint8_t *s)
+{
+ h[0] = load_8(s);
+ h[1] = load_8(s + 8);
+ h[2] = load_8(s + 16);
+ h[3] = load_8(s + 24) & 0x7fffffffffffffff;
+}
+
+static void fe64_0(fe64 h)
+{
+ h[0] = 0;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+}
+
+static void fe64_1(fe64 h)
+{
+ h[0] = 1;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+}
+
+static void fe64_copy(fe64 h, const fe64 f)
+{
+ h[0] = f[0];
+ h[1] = f[1];
+ h[2] = f[2];
+ h[3] = f[3];
+}
+
+static void fe64_cswap(fe64 f, fe64 g, unsigned int b)
+{
+ int i;
+ uint64_t mask = 0 - (uint64_t)b;
+
+ for (i = 0; i < 4; i++) {
+ uint64_t x = f[i] ^ g[i];
+ x &= mask;
+ f[i] ^= x;
+ g[i] ^= x;
+ }
+}
+
+static void fe64_invert(fe64 out, const fe64 z)
+{
+ fe64 t0;
+ fe64 t1;
+ fe64 t2;
+ fe64 t3;
+ int i;
+ /*
+ * Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as
+ * 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11.
+ */
+
+ /* t0 = z ** 2 */
+ fe64_sqr(t0, z);
+
+ /* t1 = t0 ** (2 ** 2) = z ** 8 */
+ fe64_sqr(t1, t0);
+ fe64_sqr(t1, t1);
+
+ /* t1 = z * t1 = z ** 9 */
+ fe64_mul(t1, z, t1);
+ /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */
+ fe64_mul(t0, t0, t1);
+
+ /* t2 = t0 ** 2 = z ** 22 */
+ fe64_sqr(t2, t0);
+
+ /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */
+ fe64_mul(t1, t1, t2);
+
+ /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */
+ fe64_sqr(t2, t1);
+ for (i = 1; i < 5; ++i)
+ fe64_sqr(t2, t2);
+
+ /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */
+ fe64_mul(t1, t2, t1);
+
+ /* Continuing similarly... */
+
+ /* t2 = z ** (2 ** 20 - 1) */
+ fe64_sqr(t2, t1);
+ for (i = 1; i < 10; ++i)
+ fe64_sqr(t2, t2);
+
+ fe64_mul(t2, t2, t1);
+
+ /* t2 = z ** (2 ** 40 - 1) */
+ fe64_sqr(t3, t2);
+ for (i = 1; i < 20; ++i)
+ fe64_sqr(t3, t3);
+
+ fe64_mul(t2, t3, t2);
+
+ /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */
+ for (i = 0; i < 10; ++i)
+ fe64_sqr(t2, t2);
+
+ /* t1 = z ** (2 ** 50 - 1) */
+ fe64_mul(t1, t2, t1);
+
+ /* t2 = z ** (2 ** 100 - 1) */
+ fe64_sqr(t2, t1);
+ for (i = 1; i < 50; ++i)
+ fe64_sqr(t2, t2);
+
+ fe64_mul(t2, t2, t1);
+
+ /* t2 = z ** (2 ** 200 - 1) */
+ fe64_sqr(t3, t2);
+ for (i = 1; i < 100; ++i)
+ fe64_sqr(t3, t3);
+
+ fe64_mul(t2, t3, t2);
+
+ /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */
+ for (i = 0; i < 50; ++i)
+ fe64_sqr(t2, t2);
+
+ /* t1 = z ** (2 ** 250 - 1) */
+ fe64_mul(t1, t2, t1);
+
+ /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */
+ for (i = 0; i < 5; ++i)
+ fe64_sqr(t1, t1);
+
+ /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */
+ fe64_mul(out, t1, t0);
+}
+
+/*
+ * Duplicate of original x25519_scalar_mult_generic, but using
+ * fe64_* subroutines.
+ */
+static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
+ const uint8_t point[32])
+{
+ fe64 x1, x2, z2, x3, z3, tmp0, tmp1;
+ uint8_t e[32];
+ unsigned swap = 0;
+ int pos;
+
+ memcpy(e, scalar, 32);
+ e[0] &= 0xf8;
+ e[31] &= 0x7f;
+ e[31] |= 0x40;
+ fe64_frombytes(x1, point);
+ fe64_1(x2);
+ fe64_0(z2);
+ fe64_copy(x3, x1);
+ fe64_1(z3);
+
+ for (pos = 254; pos >= 0; --pos) {
+ unsigned int b = 1 & (e[pos / 8] >> (pos & 7));
+
+ swap ^= b;
+ fe64_cswap(x2, x3, swap);
+ fe64_cswap(z2, z3, swap);
+ swap = b;
+ fe64_sub(tmp0, x3, z3);
+ fe64_sub(tmp1, x2, z2);
+ fe64_add(x2, x2, z2);
+ fe64_add(z2, x3, z3);
+ fe64_mul(z3, x2, tmp0);
+ fe64_mul(z2, z2, tmp1);
+ fe64_sqr(tmp0, tmp1);
+ fe64_sqr(tmp1, x2);
+ fe64_add(x3, z3, z2);
+ fe64_sub(z2, z3, z2);
+ fe64_mul(x2, tmp1, tmp0);
+ fe64_sub(tmp1, tmp1, tmp0);
+ fe64_sqr(z2, z2);
+ fe64_mul121666(z3, tmp1);
+ fe64_sqr(x3, x3);
+ fe64_add(tmp0, tmp0, z3);
+ fe64_mul(z3, x1, z2);
+ fe64_mul(z2, tmp1, tmp0);
+ }
+
+ fe64_invert(z2, z2);
+ fe64_mul(x2, x2, z2);
+ fe64_tobytes(out, x2);
+
+ OPENSSL_cleanse(e, sizeof(e));
+}
+#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;
+ uint64_t f_i, g0, g1, g2, g3, g4;
+
+ f_i = f[0];
+ h0 = (u128)f_i * (g0 = g[0]);
+ h1 = (u128)f_i * (g1 = g[1]);
+ h2 = (u128)f_i * (g2 = g[2]);
+ h3 = (u128)f_i * (g3 = g[3]);
+ h4 = (u128)f_i * (g4 = g[4]);
+
+ f_i = f[1];
+ h0 += (u128)f_i * (g4 *= 19);
+ h1 += (u128)f_i * g0;
+ h2 += (u128)f_i * g1;
+ h3 += (u128)f_i * g2;
+ h4 += (u128)f_i * g3;
+
+ f_i = f[2];
+ h0 += (u128)f_i * (g3 *= 19);
+ h1 += (u128)f_i * g4;
+ h2 += (u128)f_i * g0;
+ h3 += (u128)f_i * g1;
+ h4 += (u128)f_i * g2;
+
+ f_i = f[3];
+ h0 += (u128)f_i * (g2 *= 19);
+ h1 += (u128)f_i * g3;
+ h2 += (u128)f_i * g4;
+ h3 += (u128)f_i * g0;
+ h4 += (u128)f_i * g1;
+
+ f_i = f[4];
+ h0 += (u128)f_i * (g1 *= 19);
+ h1 += (u128)f_i * g2;
+ h2 += (u128)f_i * g3;
+ h3 += (u128)f_i * g4;
+ h4 += (u128)f_i * g0;
+
+ /* partial [lazy] reduction */
+ h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
+ h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
+
+ h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
+ g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
+
+ g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
+ g3 += g2 >> 51; g2 &= MASK51;
+ g1 += g0 >> 51; g0 &= MASK51;
+
+ h[0] = g0;
+ h[1] = g1;
+ h[2] = g2;
+ h[3] = g3;
+ h[4] = g4;
+}
+
+static void fe51_sq(fe51 h, const fe51 f)
+{
+# if defined(OPENSSL_SMALL_FOOTPRINT)
+ fe51_mul(h, f, f);
+# else
+ /* dedicated squaring gives 16-25% overall improvement */
+ uint64_t g0 = f[0];
+ uint64_t g1 = f[1];
+ uint64_t g2 = f[2];
+ uint64_t g3 = f[3];
+ uint64_t g4 = f[4];
+ u128 h0, h1, h2, h3, h4;
+
+ h0 = (u128)g0 * g0; g0 *= 2;
+ h1 = (u128)g0 * g1;
+ h2 = (u128)g0 * g2;
+ h3 = (u128)g0 * g3;
+ h4 = (u128)g0 * g4;
+
+ g0 = g4; /* borrow g0 */
+ h3 += (u128)g0 * (g4 *= 19);
+
+ h2 += (u128)g1 * g1; g1 *= 2;
+ h3 += (u128)g1 * g2;
+ h4 += (u128)g1 * g3;
+ h0 += (u128)g1 * g4;
+
+ g0 = g3; /* borrow g0 */
+ h1 += (u128)g0 * (g3 *= 19);
+ h2 += (u128)(g0 * 2) * g4;
+
+ h4 += (u128)g2 * g2; g2 *= 2;
+ h0 += (u128)g2 * g3;
+ h1 += (u128)g2 * g4;
+
+ /* partial [lazy] reduction */
+ h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
+ h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
+
+ h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
+ g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
+
+ g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
+ g3 += g2 >> 51; g2 &= MASK51;
+ g1 += g0 >> 51; g0 &= MASK51;
+
+ h[0] = g0;
+ h[1] = g1;
+ h[2] = g2;
+ h[3] = g3;
+ h[4] = g4;
+# endif
+}
+
+static void fe51_mul121666(fe51 h, fe51 f)
+{
+ u128 h0 = f[0] * (u128)121666;
+ u128 h1 = f[1] * (u128)121666;
+ u128 h2 = f[2] * (u128)121666;
+ u128 h3 = f[3] * (u128)121666;
+ u128 h4 = f[4] * (u128)121666;
+ uint64_t g0, g1, g2, g3, g4;
+
+ h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
+ h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
+
+ h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
+ g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
+
+ g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
+ g3 += g2 >> 51; g2 &= MASK51;
+ g1 += g0 >> 51; g0 &= MASK51;
+
+ h[0] = g0;
+ h[1] = g1;
+ h[2] = g2;
+ h[3] = g3;
+ h[4] = g4;
+}
+# endif
+
+static void fe51_add(fe51 h, const fe51 f, const fe51 g)
+{
+ h[0] = f[0] + g[0];
+ h[1] = f[1] + g[1];
+ h[2] = f[2] + g[2];
+ h[3] = f[3] + g[3];
+ h[4] = f[4] + g[4];
+}
+
+static void fe51_sub(fe51 h, const fe51 f, const fe51 g)
+{
+ /*
+ * Add 2*modulus to ensure that result remains positive
+ * even if subtrahend is partially reduced.
+ */
+ h[0] = (f[0] + 0xfffffffffffda) - g[0];
+ h[1] = (f[1] + 0xffffffffffffe) - g[1];
+ h[2] = (f[2] + 0xffffffffffffe) - g[2];
+ h[3] = (f[3] + 0xffffffffffffe) - g[3];
+ h[4] = (f[4] + 0xffffffffffffe) - g[4];
+}
+
+static void fe51_0(fe51 h)
+{
+ h[0] = 0;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+}
+
+static void fe51_1(fe51 h)
+{
+ h[0] = 1;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+}
+
+static void fe51_copy(fe51 h, const fe51 f)
+{
+ h[0] = f[0];
+ h[1] = f[1];
+ h[2] = f[2];
+ h[3] = f[3];
+ h[4] = f[4];
+}
+
+static void fe51_cswap(fe51 f, fe51 g, unsigned int b)
+{
+ int i;
+ uint64_t mask = 0 - (uint64_t)b;
+
+ for (i = 0; i < 5; i++) {
+ int64_t x = f[i] ^ g[i];
+ x &= mask;
+ f[i] ^= x;
+ g[i] ^= x;
+ }
+}
+
+static void fe51_invert(fe51 out, const fe51 z)
+{
+ fe51 t0;
+ fe51 t1;
+ fe51 t2;
+ fe51 t3;
+ int i;
+
+ /*
+ * Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as
+ * 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11.
+ */
+
+ /* t0 = z ** 2 */
+ fe51_sq(t0, z);
+
+ /* t1 = t0 ** (2 ** 2) = z ** 8 */
+ fe51_sq(t1, t0);
+ fe51_sq(t1, t1);
+
+ /* t1 = z * t1 = z ** 9 */
+ fe51_mul(t1, z, t1);
+ /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */
+ fe51_mul(t0, t0, t1);
+
+ /* t2 = t0 ** 2 = z ** 22 */
+ fe51_sq(t2, t0);
+
+ /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */
+ fe51_mul(t1, t1, t2);
+
+ /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */
+ fe51_sq(t2, t1);
+ for (i = 1; i < 5; ++i)
+ fe51_sq(t2, t2);
+
+ /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */
+ fe51_mul(t1, t2, t1);
+
+ /* Continuing similarly... */
+
+ /* t2 = z ** (2 ** 20 - 1) */
+ fe51_sq(t2, t1);
+ for (i = 1; i < 10; ++i)
+ fe51_sq(t2, t2);
+
+ fe51_mul(t2, t2, t1);
+
+ /* t2 = z ** (2 ** 40 - 1) */
+ fe51_sq(t3, t2);
+ for (i = 1; i < 20; ++i)
+ fe51_sq(t3, t3);
+
+ fe51_mul(t2, t3, t2);
+
+ /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */
+ for (i = 0; i < 10; ++i)
+ fe51_sq(t2, t2);
+
+ /* t1 = z ** (2 ** 50 - 1) */
+ fe51_mul(t1, t2, t1);
+
+ /* t2 = z ** (2 ** 100 - 1) */
+ fe51_sq(t2, t1);
+ for (i = 1; i < 50; ++i)
+ fe51_sq(t2, t2);
+
+ fe51_mul(t2, t2, t1);
+
+ /* t2 = z ** (2 ** 200 - 1) */
+ fe51_sq(t3, t2);
+ for (i = 1; i < 100; ++i)
+ fe51_sq(t3, t3);
+
+ fe51_mul(t2, t3, t2);
+
+ /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */
+ for (i = 0; i < 50; ++i)
+ fe51_sq(t2, t2);
+
+ /* t1 = z ** (2 ** 250 - 1) */
+ fe51_mul(t1, t2, t1);
+
+ /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */
+ for (i = 0; i < 5; ++i)
+ fe51_sq(t1, t1);
+
+ /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */
+ fe51_mul(out, t1, t0);
+}
+
+/*
+ * Duplicate of original x25519_scalar_mult_generic, but using
+ * fe51_* subroutines.
+ */
+static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
+ const uint8_t point[32])
+{
+ fe51 x1, x2, z2, x3, z3, tmp0, tmp1;
+ uint8_t e[32];
+ unsigned swap = 0;
+ int pos;
+
+# ifdef BASE_2_64_IMPLEMENTED
+ if (x25519_fe64_eligible()) {
+ x25519_scalar_mulx(out, scalar, point);
+ return;
+ }
+# endif
+
+ memcpy(e, scalar, 32);
+ e[0] &= 0xf8;
+ e[31] &= 0x7f;
+ e[31] |= 0x40;
+ fe51_frombytes(x1, point);
+ fe51_1(x2);
+ fe51_0(z2);
+ fe51_copy(x3, x1);
+ fe51_1(z3);
+
+ for (pos = 254; pos >= 0; --pos) {
+ unsigned int b = 1 & (e[pos / 8] >> (pos & 7));
+
+ swap ^= b;
+ fe51_cswap(x2, x3, swap);
+ fe51_cswap(z2, z3, swap);
+ swap = b;
+ fe51_sub(tmp0, x3, z3);
+ fe51_sub(tmp1, x2, z2);
+ fe51_add(x2, x2, z2);
+ fe51_add(z2, x3, z3);
+ fe51_mul(z3, tmp0, x2);
+ fe51_mul(z2, z2, tmp1);
+ fe51_sq(tmp0, tmp1);
+ fe51_sq(tmp1, x2);
+ fe51_add(x3, z3, z2);
+ fe51_sub(z2, z3, z2);
+ fe51_mul(x2, tmp1, tmp0);
+ fe51_sub(tmp1, tmp1, tmp0);
+ fe51_sq(z2, z2);
+ fe51_mul121666(z3, tmp1);
+ fe51_sq(x3, x3);
+ fe51_add(tmp0, tmp0, z3);
+ fe51_mul(z3, x1, z2);
+ fe51_mul(z2, tmp1, tmp0);
+ }
+
+ fe51_invert(z2, z2);
+ fe51_mul(x2, x2, z2);
+ fe51_tobytes(out, x2);
+
+ OPENSSL_cleanse(e, sizeof(e));
+}
+#endif
+
+/*
+ * Reference base 2^25.5 implementation.
+ */
+/*
+ * This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
+ * 20141124 (http://bench.cr.yp.to/supercop.html).
+ *
+ * The field functions are shared by Ed25519 and X25519 where possible.
+ */
/* fe means field element. Here the field is \Z/(2^255-19). An element t,
* entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
@@ -79,16 +815,16 @@ static void fe_frombytes(fe h, const uint8_t *s) {
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- h[5] = h5;
- h[6] = h6;
- h[7] = h7;
- h[8] = h8;
- h[9] = h9;
+ h[0] = (int32_t)h0;
+ h[1] = (int32_t)h1;
+ h[2] = (int32_t)h2;
+ h[3] = (int32_t)h3;
+ h[4] = (int32_t)h4;
+ h[5] = (int32_t)h5;
+ h[6] = (int32_t)h6;
+ h[7] = (int32_t)h7;
+ h[8] = (int32_t)h8;
+ h[9] = (int32_t)h9;
}
/* Preconditions:
@@ -159,38 +895,38 @@ static void fe_tobytes(uint8_t *s, const fe h) {
* evidently 2^255 h10-2^255 q = 0.
* Goal: Output h0+...+2^230 h9. */
- s[0] = h0 >> 0;
- s[1] = h0 >> 8;
- s[2] = h0 >> 16;
- s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
- s[4] = h1 >> 6;
- s[5] = h1 >> 14;
- s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
- s[7] = h2 >> 5;
- s[8] = h2 >> 13;
- s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
- s[10] = h3 >> 3;
- s[11] = h3 >> 11;
- s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
- s[13] = h4 >> 2;
- s[14] = h4 >> 10;
- s[15] = h4 >> 18;
- s[16] = h5 >> 0;
- s[17] = h5 >> 8;
- s[18] = h5 >> 16;
- s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
- s[20] = h6 >> 7;
- s[21] = h6 >> 15;
- s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
- s[23] = h7 >> 5;
- s[24] = h7 >> 13;
- s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
- s[26] = h8 >> 4;
- s[27] = h8 >> 12;
- s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
- s[29] = h9 >> 2;
- s[30] = h9 >> 10;
- s[31] = h9 >> 18;
+ s[0] = (uint8_t)(h0 >> 0);
+ s[1] = (uint8_t)(h0 >> 8);
+ s[2] = (uint8_t)(h0 >> 16);
+ s[3] = (uint8_t)((h0 >> 24) | ((uint32_t)(h1) << 2));
+ s[4] = (uint8_t)(h1 >> 6);
+ s[5] = (uint8_t)(h1 >> 14);
+ s[6] = (uint8_t)((h1 >> 22) | ((uint32_t)(h2) << 3));
+ s[7] = (uint8_t)(h2 >> 5);
+ s[8] = (uint8_t)(h2 >> 13);
+ s[9] = (uint8_t)((h2 >> 21) | ((uint32_t)(h3) << 5));
+ s[10] = (uint8_t)(h3 >> 3);
+ s[11] = (uint8_t)(h3 >> 11);
+ s[12] = (uint8_t)((h3 >> 19) | ((uint32_t)(h4) << 6));
+ s[13] = (uint8_t)(h4 >> 2);
+ s[14] = (uint8_t)(h4 >> 10);
+ s[15] = (uint8_t)(h4 >> 18);
+ s[16] = (uint8_t)(h5 >> 0);
+ s[17] = (uint8_t)(h5 >> 8);
+ s[18] = (uint8_t)(h5 >> 16);
+ s[19] = (uint8_t)((h5 >> 24) | ((uint32_t)(h6) << 1));
+ s[20] = (uint8_t)(h6 >> 7);
+ s[21] = (uint8_t)(h6 >> 15);
+ s[22] = (uint8_t)((h6 >> 23) | ((uint32_t)(h7) << 3));
+ s[23] = (uint8_t)(h7 >> 5);
+ s[24] = (uint8_t)(h7 >> 13);
+ s[25] = (uint8_t)((h7 >> 21) | ((uint32_t)(h8) << 4));
+ s[26] = (uint8_t)(h8 >> 4);
+ s[27] = (uint8_t)(h8 >> 12);
+ s[28] = (uint8_t)((h8 >> 20) | ((uint32_t)(h9) << 6));
+ s[29] = (uint8_t)(h9 >> 2);
+ s[30] = (uint8_t)(h9 >> 10);
+ s[31] = (uint8_t)(h9 >> 18);
}
/* h = f */
@@ -470,16 +1206,16 @@ static void fe_mul(fe h, const fe f, const fe g) {
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- h[5] = h5;
- h[6] = h6;
- h[7] = h7;
- h[8] = h8;
- h[9] = h9;
+ h[0] = (int32_t)h0;
+ h[1] = (int32_t)h1;
+ h[2] = (int32_t)h2;
+ h[3] = (int32_t)h3;
+ h[4] = (int32_t)h4;
+ h[5] = (int32_t)h5;
+ h[6] = (int32_t)h6;
+ h[7] = (int32_t)h7;
+ h[8] = (int32_t)h8;
+ h[9] = (int32_t)h9;
}
/* h = f * f
@@ -611,16 +1347,16 @@ static void fe_sq(fe h, const fe f) {
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- h[5] = h5;
- h[6] = h6;
- h[7] = h7;
- h[8] = h8;
- h[9] = h9;
+ h[0] = (int32_t)h0;
+ h[1] = (int32_t)h1;
+ h[2] = (int32_t)h2;
+ h[3] = (int32_t)h3;
+ h[4] = (int32_t)h4;
+ h[5] = (int32_t)h5;
+ h[6] = (int32_t)h6;
+ h[7] = (int32_t)h7;
+ h[8] = (int32_t)h8;
+ h[9] = (int32_t)h9;
}
static void fe_invert(fe out, const fe z) {
@@ -746,6 +1482,30 @@ static void fe_cmov(fe f, const fe g, unsigned b) {
}
}
+/* return 0 if f == 0
+ * return 1 if f != 0
+ *
+ * Preconditions:
+ * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static int fe_isnonzero(const fe f) {
+ uint8_t s[32];
+ static const uint8_t zero[32] = {0};
+ fe_tobytes(s, f);
+
+ return CRYPTO_memcmp(s, zero, sizeof(zero)) != 0;
+}
+
+/* return 1 if f is in {1,3,5,...,q-2}
+ * return 0 if f is in {0,2,4,...,q-1}
+ *
+ * Preconditions:
+ * |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static int fe_isnegative(const fe f) {
+ uint8_t s[32];
+ fe_tobytes(s, f);
+ return s[0] & 1;
+}
+
/* h = 2 * f * f
* Can overlap h with f.
*
@@ -886,16 +1646,73 @@ static void fe_sq2(fe h, const fe f) {
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- h[5] = h5;
- h[6] = h6;
- h[7] = h7;
- h[8] = h8;
- h[9] = h9;
+ h[0] = (int32_t)h0;
+ h[1] = (int32_t)h1;
+ h[2] = (int32_t)h2;
+ h[3] = (int32_t)h3;
+ h[4] = (int32_t)h4;
+ h[5] = (int32_t)h5;
+ h[6] = (int32_t)h6;
+ h[7] = (int32_t)h7;
+ h[8] = (int32_t)h8;
+ h[9] = (int32_t)h9;
+}
+
+static void fe_pow22523(fe out, const fe z) {
+ fe t0;
+ fe t1;
+ fe t2;
+ int i;
+
+ fe_sq(t0, z);
+ fe_sq(t1, t0);
+ for (i = 1; i < 2; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t1, z, t1);
+ fe_mul(t0, t0, t1);
+ fe_sq(t0, t0);
+ fe_mul(t0, t1, t0);
+ fe_sq(t1, t0);
+ for (i = 1; i < 5; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t0, t1, t0);
+ fe_sq(t1, t0);
+ for (i = 1; i < 10; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t1, t1, t0);
+ fe_sq(t2, t1);
+ for (i = 1; i < 20; ++i) {
+ fe_sq(t2, t2);
+ }
+ fe_mul(t1, t2, t1);
+ fe_sq(t1, t1);
+ for (i = 1; i < 10; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t0, t1, t0);
+ fe_sq(t1, t0);
+ for (i = 1; i < 50; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t1, t1, t0);
+ fe_sq(t2, t1);
+ for (i = 1; i < 100; ++i) {
+ fe_sq(t2, t2);
+ }
+ fe_mul(t1, t2, t1);
+ fe_sq(t1, t1);
+ for (i = 1; i < 50; ++i) {
+ fe_sq(t1, t1);
+ }
+ fe_mul(t0, t1, t0);
+ fe_sq(t0, t0);
+ for (i = 1; i < 2; ++i) {
+ fe_sq(t0, t0);
+ }
+ fe_mul(out, t0, z);
}
/* ge means group element.
@@ -943,6 +1760,85 @@ typedef struct {
fe T2d;
} ge_cached;
+static void ge_tobytes(uint8_t *s, const ge_p2 *h) {
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip, h->Z);
+ fe_mul(x, h->X, recip);
+ fe_mul(y, h->Y, recip);
+ fe_tobytes(s, y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
+
+static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) {
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip, h->Z);
+ fe_mul(x, h->X, recip);
+ fe_mul(y, h->Y, recip);
+ fe_tobytes(s, y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
+
+static const fe d = {-10913610, 13857413, -15372611, 6949391, 114729,
+ -8787816, -6275908, -3247719, -18696448, -12055116};
+
+static const fe sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472,
+ -272473, -25146209, -2005654, 326686, 11406482};
+
+static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
+ fe u;
+ fe v;
+ fe v3;
+ fe vxx;
+ fe check;
+
+ fe_frombytes(h->Y, s);
+ fe_1(h->Z);
+ fe_sq(u, h->Y);
+ fe_mul(v, u, d);
+ fe_sub(u, u, h->Z); /* u = y^2-1 */
+ fe_add(v, v, h->Z); /* v = dy^2+1 */
+
+ fe_sq(v3, v);
+ fe_mul(v3, v3, v); /* v3 = v^3 */
+ fe_sq(h->X, v3);
+ fe_mul(h->X, h->X, v);
+ fe_mul(h->X, h->X, u); /* x = uv^7 */
+
+ fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+ fe_mul(h->X, h->X, v3);
+ fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe_sq(vxx, h->X);
+ fe_mul(vxx, vxx, v);
+ fe_sub(check, vxx, u); /* vx^2-u */
+ if (fe_isnonzero(check)) {
+ fe_add(check, vxx, u); /* vx^2+u */
+ if (fe_isnonzero(check)) {
+ return -1;
+ }
+ fe_mul(h->X, h->X, sqrtm1);
+ }
+
+ if (fe_isnegative(h->X) != (s[31] >> 7)) {
+ fe_neg(h->X, h->X);
+ }
+
+ fe_mul(h->T, h->X, h->Y);
+ return 0;
+}
+
+static void ge_p2_0(ge_p2 *h) {
+ fe_0(h->X);
+ fe_1(h->Y);
+ fe_1(h->Z);
+}
+
static void ge_p3_0(ge_p3 *h) {
fe_0(h->X);
fe_1(h->Y);
@@ -963,6 +1859,17 @@ static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
fe_copy(r->Z, p->Z);
}
+static const fe d2 = {-21827239, -5839606, -30745221, 13898782, 229458,
+ 15978800, -12551817, -6495438, 29715968, 9444199};
+
+/* r = p */
+static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
+ fe_add(r->YplusX, p->Y, p->X);
+ fe_sub(r->YminusX, p->Y, p->X);
+ fe_copy(r->Z, p->Z);
+ fe_mul(r->T2d, p->T, d2);
+}
+
/* r = p */
static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
@@ -1016,6 +1923,56 @@ static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe_sub(r->T, t0, r->T);
}
+/* r = p - q */
+static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
+ fe t0;
+
+ fe_add(r->X, p->Y, p->X);
+ fe_sub(r->Y, p->Y, p->X);
+ fe_mul(r->Z, r->X, q->yminusx);
+ fe_mul(r->Y, r->Y, q->yplusx);
+ fe_mul(r->T, q->xy2d, p->T);
+ fe_add(t0, p->Z, p->Z);
+ fe_sub(r->X, r->Z, r->Y);
+ fe_add(r->Y, r->Z, r->Y);
+ fe_sub(r->Z, t0, r->T);
+ fe_add(r->T, t0, r->T);
+}
+
+/* r = p + q */
+static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+ fe t0;
+
+ fe_add(r->X, p->Y, p->X);
+ fe_sub(r->Y, p->Y, p->X);
+ fe_mul(r->Z, r->X, q->YplusX);
+ fe_mul(r->Y, r->Y, q->YminusX);
+ fe_mul(r->T, q->T2d, p->T);
+ fe_mul(r->X, p->Z, q->Z);
+ fe_add(t0, r->X, r->X);
+ fe_sub(r->X, r->Z, r->Y);
+ fe_add(r->Y, r->Z, r->Y);
+ fe_add(r->Z, t0, r->T);
+ fe_sub(r->T, t0, r->T);
+}
+
+/* r = p - q */
+static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+ fe t0;
+
+ fe_add(r->X, p->Y, p->X);
+ fe_sub(r->Y, p->Y, p->X);
+ fe_mul(r->Z, r->X, q->YminusX);
+ fe_mul(r->Y, r->Y, q->YplusX);
+ fe_mul(r->T, q->T2d, p->T);
+ fe_mul(r->X, p->Z, q->Z);
+ fe_add(t0, r->X, r->X);
+ fe_sub(r->X, r->Z, r->Y);
+ fe_add(r->Y, r->Z, r->Y);
+ fe_sub(r->Z, t0, r->T);
+ fe_add(r->T, t0, r->T);
+}
+
static uint8_t equal(signed char b, signed char c) {
uint8_t ub = b;
uint8_t uc = c;
@@ -3230,6 +4187,7 @@ static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
OPENSSL_cleanse(e, sizeof(e));
}
+#if !defined(BASE_2_51_IMPLEMENTED)
/* Replace (f,g) with (g,f) if b == 1;
* replace (f,g) with (f,g) if b == 0.
*
@@ -3297,16 +4255,16 @@ static void fe_mul121666(fe h, fe f) {
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
- h[0] = h0;
- h[1] = h1;
- h[2] = h2;
- h[3] = h3;
- h[4] = h4;
- h[5] = h5;
- h[6] = h6;
- h[7] = h7;
- h[8] = h8;
- h[9] = h9;
+ h[0] = (int32_t)h0;
+ h[1] = (int32_t)h1;
+ h[2] = (int32_t)h2;
+ h[3] = (int32_t)h3;
+ h[4] = (int32_t)h4;
+ h[5] = (int32_t)h5;
+ h[6] = (int32_t)h6;
+ h[7] = (int32_t)h7;
+ h[8] = (int32_t)h8;
+ h[9] = (int32_t)h9;
}
static void x25519_scalar_mult_generic(uint8_t out[32],
@@ -3352,8 +4310,6 @@ static void x25519_scalar_mult_generic(uint8_t out[32],
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
- fe_cswap(x2, x3, swap);
- fe_cswap(z2, z3, swap);
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
@@ -3366,6 +4322,1107 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]) {
x25519_scalar_mult_generic(out, scalar, point);
}
+#endif
+
+static void slide(signed char *r, const uint8_t *a) {
+ int i;
+ int b;
+ int k;
+
+ for (i = 0; i < 256; ++i) {
+ r[i] = 1 & (a[i >> 3] >> (i & 7));
+ }
+
+ for (i = 0; i < 256; ++i) {
+ if (r[i]) {
+ for (b = 1; b <= 6 && i + b < 256; ++b) {
+ if (r[i + b]) {
+ if (r[i] + (r[i + b] << b) <= 15) {
+ r[i] += r[i + b] << b;
+ r[i + b] = 0;
+ } else if (r[i] - (r[i + b] << b) >= -15) {
+ r[i] -= r[i + b] << b;
+ for (k = i + b; k < 256; ++k) {
+ if (!r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static const ge_precomp Bi[8] = {
+ {
+ {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
+ -11754271, -6079156, 2047605},
+ {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
+ 5043384, 19500929, -15469378},
+ {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919,
+ 11864899, -24514362, -4438546},
+ },
+ {
+ {15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600,
+ -14772189, 28944400, -1550024},
+ {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577,
+ -11775962, 7689662, 11199574},
+ {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774,
+ 10017326, -17749093, -9920357},
+ },
+ {
+ {10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885,
+ 14515107, -15438304, 10819380},
+ {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
+ 12483688, -12668491, 5581306},
+ {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350,
+ 13850243, -23678021, -15815942},
+ },
+ {
+ {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
+ 5230134, -23952439, -15175766},
+ {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025,
+ 16520125, 30598449, 7715701},
+ {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660,
+ 1370708, 29794553, -1409300},
+ },
+ {
+ {-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211,
+ -1361450, -13062696, 13821877},
+ {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028,
+ -7212327, 18853322, -14220951},
+ {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358,
+ -10431137, 2207753, -3209784},
+ },
+ {
+ {-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364,
+ -663000, -31111463, -16132436},
+ {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789,
+ 15725684, 171356, 6466918},
+ {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339,
+ -14088058, -30714912, 16193877},
+ },
+ {
+ {-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398,
+ 4729455, -18074513, 9256800},
+ {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405,
+ 9761698, -19827198, 630305},
+ {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551,
+ -15960994, -2449256, -14291300},
+ },
+ {
+ {-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575,
+ 15033784, 25105118, -7894876},
+ {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925,
+ 1573892, -2625887, 2198790, -15804619},
+ {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022,
+ -16236442, -32461234, -12290683},
+ },
+};
+
+/* r = a * A + b * B
+ * where a = a[0]+256*a[1]+...+256^31 a[31].
+ * and b = b[0]+256*b[1]+...+256^31 b[31].
+ * B is the Ed25519 base point (x,4/5) with x positive. */
+static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
+ const ge_p3 *A, const uint8_t *b) {
+ signed char aslide[256];
+ signed char bslide[256];
+ ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+ ge_p1p1 t;
+ ge_p3 u;
+ ge_p3 A2;
+ int i;
+
+ slide(aslide, a);
+ slide(bslide, b);
+
+ ge_p3_to_cached(&Ai[0], A);
+ ge_p3_dbl(&t, A);
+ ge_p1p1_to_p3(&A2, &t);
+ ge_add(&t, &A2, &Ai[0]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[1], &u);
+ ge_add(&t, &A2, &Ai[1]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[2], &u);
+ ge_add(&t, &A2, &Ai[2]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[3], &u);
+ ge_add(&t, &A2, &Ai[3]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[4], &u);
+ ge_add(&t, &A2, &Ai[4]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[5], &u);
+ ge_add(&t, &A2, &Ai[5]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[6], &u);
+ ge_add(&t, &A2, &Ai[6]);
+ ge_p1p1_to_p3(&u, &t);
+ ge_p3_to_cached(&Ai[7], &u);
+
+ ge_p2_0(r);
+
+ for (i = 255; i >= 0; --i) {
+ if (aslide[i] || bslide[i]) {
+ break;
+ }
+ }
+
+ for (; i >= 0; --i) {
+ ge_p2_dbl(&t, r);
+
+ if (aslide[i] > 0) {
+ ge_p1p1_to_p3(&u, &t);
+ ge_add(&t, &u, &Ai[aslide[i] / 2]);
+ } else if (aslide[i] < 0) {
+ ge_p1p1_to_p3(&u, &t);
+ ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+ }
+
+ if (bslide[i] > 0) {
+ ge_p1p1_to_p3(&u, &t);
+ ge_madd(&t, &u, &Bi[bslide[i] / 2]);
+ } else if (bslide[i] < 0) {
+ ge_p1p1_to_p3(&u, &t);
+ ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
+ }
+
+ ge_p1p1_to_p2(r, &t);
+ }
+}
+
+/* The set of scalars is \Z/l
+ * where l = 2^252 + 27742317777372353535851937790883648493. */
+
+/* Input:
+ * s[0]+256*s[1]+...+256^63*s[63] = s
+ *
+ * Output:
+ * s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ * where l = 2^252 + 27742317777372353535851937790883648493.
+ * Overwrites s in place. */
+static void x25519_sc_reduce(uint8_t *s) {
+ int64_t s0 = 2097151 & load_3(s);
+ int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
+ int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
+ int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
+ int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
+ int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
+ int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
+ int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
+ int64_t s8 = 2097151 & load_3(s + 21);
+ int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
+ int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
+ int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
+ int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
+ int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
+ int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
+ int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
+ int64_t s16 = 2097151 & load_3(s + 42);
+ int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
+ int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
+ int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
+ int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
+ int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
+ int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
+ int64_t s23 = (load_4(s + 60) >> 3);
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+ int64_t carry10;
+ int64_t carry11;
+ int64_t carry12;
+ int64_t carry13;
+ int64_t carry14;
+ int64_t carry15;
+ int64_t carry16;
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1 << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry8 = (s8 + (1 << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry10 = (s10 + (1 << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+ carry12 = (s12 + (1 << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * (1 << 21);
+ carry14 = (s14 + (1 << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * (1 << 21);
+ carry16 = (s16 + (1 << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * (1 << 21);
+
+ carry7 = (s7 + (1 << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry9 = (s9 + (1 << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry11 = (s11 + (1 << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+ carry13 = (s13 + (1 << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * (1 << 21);
+ carry15 = (s15 + (1 << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * (1 << 21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1 << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry2 = (s2 + (1 << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry4 = (s4 + (1 << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry6 = (s6 + (1 << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry8 = (s8 + (1 << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry10 = (s10 + (1 << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+
+ carry1 = (s1 + (1 << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry3 = (s3 + (1 << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry5 = (s5 + (1 << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry7 = (s7 + (1 << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry9 = (s9 + (1 << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry11 = (s11 + (1 << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+ carry11 = s11 >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+
+ s[0] = (uint8_t)(s0 >> 0);
+ s[1] = (uint8_t)(s0 >> 8);
+ s[2] = (uint8_t)((s0 >> 16) | (s1 << 5));
+ s[3] = (uint8_t)(s1 >> 3);
+ s[4] = (uint8_t)(s1 >> 11);
+ s[5] = (uint8_t)((s1 >> 19) | (s2 << 2));
+ s[6] = (uint8_t)(s2 >> 6);
+ s[7] = (uint8_t)((s2 >> 14) | (s3 << 7));
+ s[8] = (uint8_t)(s3 >> 1);
+ s[9] = (uint8_t)(s3 >> 9);
+ s[10] = (uint8_t)((s3 >> 17) | (s4 << 4));
+ s[11] = (uint8_t)(s4 >> 4);
+ s[12] = (uint8_t)(s4 >> 12);
+ s[13] = (uint8_t)((s4 >> 20) | (s5 << 1));
+ s[14] = (uint8_t)(s5 >> 7);
+ s[15] = (uint8_t)((s5 >> 15) | (s6 << 6));
+ s[16] = (uint8_t)(s6 >> 2);
+ s[17] = (uint8_t)(s6 >> 10);
+ s[18] = (uint8_t)((s6 >> 18) | (s7 << 3));
+ s[19] = (uint8_t)(s7 >> 5);
+ s[20] = (uint8_t)(s7 >> 13);
+ s[21] = (uint8_t)(s8 >> 0);
+ s[22] = (uint8_t)(s8 >> 8);
+ s[23] = (uint8_t)((s8 >> 16) | (s9 << 5));
+ s[24] = (uint8_t)(s9 >> 3);
+ s[25] = (uint8_t)(s9 >> 11);
+ s[26] = (uint8_t)((s9 >> 19) | (s10 << 2));
+ s[27] = (uint8_t)(s10 >> 6);
+ s[28] = (uint8_t)((s10 >> 14) | (s11 << 7));
+ s[29] = (uint8_t)(s11 >> 1);
+ s[30] = (uint8_t)(s11 >> 9);
+ s[31] = (uint8_t)(s11 >> 17);
+}
+
+/* Input:
+ * a[0]+256*a[1]+...+256^31*a[31] = a
+ * b[0]+256*b[1]+...+256^31*b[31] = b
+ * c[0]+256*c[1]+...+256^31*c[31] = c
+ *
+ * Output:
+ * s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ * where l = 2^252 + 27742317777372353535851937790883648493. */
+static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
+ const uint8_t *c) {
+ int64_t a0 = 2097151 & load_3(a);
+ int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
+ int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
+ int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
+ int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
+ int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
+ int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
+ int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
+ int64_t a8 = 2097151 & load_3(a + 21);
+ int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
+ int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
+ int64_t a11 = (load_4(a + 28) >> 7);
+ int64_t b0 = 2097151 & load_3(b);
+ int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
+ int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
+ int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
+ int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
+ int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
+ int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
+ int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
+ int64_t b8 = 2097151 & load_3(b + 21);
+ int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
+ int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
+ int64_t b11 = (load_4(b + 28) >> 7);
+ int64_t c0 = 2097151 & load_3(c);
+ int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
+ int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
+ int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
+ int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
+ int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
+ int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
+ int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
+ int64_t c8 = 2097151 & load_3(c + 21);
+ int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
+ int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
+ int64_t c11 = (load_4(c + 28) >> 7);
+ int64_t s0;
+ int64_t s1;
+ int64_t s2;
+ int64_t s3;
+ int64_t s4;
+ int64_t s5;
+ int64_t s6;
+ int64_t s7;
+ int64_t s8;
+ int64_t s9;
+ int64_t s10;
+ int64_t s11;
+ int64_t s12;
+ int64_t s13;
+ int64_t s14;
+ int64_t s15;
+ int64_t s16;
+ int64_t s17;
+ int64_t s18;
+ int64_t s19;
+ int64_t s20;
+ int64_t s21;
+ int64_t s22;
+ int64_t s23;
+ int64_t carry0;
+ int64_t carry1;
+ int64_t carry2;
+ int64_t carry3;
+ int64_t carry4;
+ int64_t carry5;
+ int64_t carry6;
+ int64_t carry7;
+ int64_t carry8;
+ int64_t carry9;
+ int64_t carry10;
+ int64_t carry11;
+ int64_t carry12;
+ int64_t carry13;
+ int64_t carry14;
+ int64_t carry15;
+ int64_t carry16;
+ int64_t carry17;
+ int64_t carry18;
+ int64_t carry19;
+ int64_t carry20;
+ int64_t carry21;
+ int64_t carry22;
+
+ s0 = c0 + a0 * b0;
+ s1 = c1 + a0 * b1 + a1 * b0;
+ s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
+ s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
+ s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
+ s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
+ s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
+ s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
+ a6 * b1 + a7 * b0;
+ s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
+ a6 * b2 + a7 * b1 + a8 * b0;
+ s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
+ a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
+ s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
+ a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
+ s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
+ a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
+ s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 +
+ a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
+ s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 +
+ a9 * b4 + a10 * b3 + a11 * b2;
+ s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 +
+ a10 * b4 + a11 * b3;
+ s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 +
+ a11 * b4;
+ s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
+ s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
+ s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
+ s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
+ s20 = a9 * b11 + a10 * b10 + a11 * b9;
+ s21 = a10 * b11 + a11 * b10;
+ s22 = a11 * b11;
+ s23 = 0;
+
+ carry0 = (s0 + (1 << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry2 = (s2 + (1 << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry4 = (s4 + (1 << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry6 = (s6 + (1 << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry8 = (s8 + (1 << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry10 = (s10 + (1 << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+ carry12 = (s12 + (1 << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * (1 << 21);
+ carry14 = (s14 + (1 << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * (1 << 21);
+ carry16 = (s16 + (1 << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * (1 << 21);
+ carry18 = (s18 + (1 << 20)) >> 21;
+ s19 += carry18;
+ s18 -= carry18 * (1 << 21);
+ carry20 = (s20 + (1 << 20)) >> 21;
+ s21 += carry20;
+ s20 -= carry20 * (1 << 21);
+ carry22 = (s22 + (1 << 20)) >> 21;
+ s23 += carry22;
+ s22 -= carry22 * (1 << 21);
+
+ carry1 = (s1 + (1 << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry3 = (s3 + (1 << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry5 = (s5 + (1 << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry7 = (s7 + (1 << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry9 = (s9 + (1 << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry11 = (s11 + (1 << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+ carry13 = (s13 + (1 << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * (1 << 21);
+ carry15 = (s15 + (1 << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * (1 << 21);
+ carry17 = (s17 + (1 << 20)) >> 21;
+ s18 += carry17;
+ s17 -= carry17 * (1 << 21);
+ carry19 = (s19 + (1 << 20)) >> 21;
+ s20 += carry19;
+ s19 -= carry19 * (1 << 21);
+ carry21 = (s21 + (1 << 20)) >> 21;
+ s22 += carry21;
+ s21 -= carry21 * (1 << 21);
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1 << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry8 = (s8 + (1 << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry10 = (s10 + (1 << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+ carry12 = (s12 + (1 << 20)) >> 21;
+ s13 += carry12;
+ s12 -= carry12 * (1 << 21);
+ carry14 = (s14 + (1 << 20)) >> 21;
+ s15 += carry14;
+ s14 -= carry14 * (1 << 21);
+ carry16 = (s16 + (1 << 20)) >> 21;
+ s17 += carry16;
+ s16 -= carry16 * (1 << 21);
+
+ carry7 = (s7 + (1 << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry9 = (s9 + (1 << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry11 = (s11 + (1 << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+ carry13 = (s13 + (1 << 20)) >> 21;
+ s14 += carry13;
+ s13 -= carry13 * (1 << 21);
+ carry15 = (s15 + (1 << 20)) >> 21;
+ s16 += carry15;
+ s15 -= carry15 * (1 << 21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1 << 20)) >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry2 = (s2 + (1 << 20)) >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry4 = (s4 + (1 << 20)) >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry6 = (s6 + (1 << 20)) >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry8 = (s8 + (1 << 20)) >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry10 = (s10 + (1 << 20)) >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+
+ carry1 = (s1 + (1 << 20)) >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry3 = (s3 + (1 << 20)) >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry5 = (s5 + (1 << 20)) >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry7 = (s7 + (1 << 20)) >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry9 = (s9 + (1 << 20)) >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry11 = (s11 + (1 << 20)) >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+ carry11 = s11 >> 21;
+ s12 += carry11;
+ s11 -= carry11 * (1 << 21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21;
+ s1 += carry0;
+ s0 -= carry0 * (1 << 21);
+ carry1 = s1 >> 21;
+ s2 += carry1;
+ s1 -= carry1 * (1 << 21);
+ carry2 = s2 >> 21;
+ s3 += carry2;
+ s2 -= carry2 * (1 << 21);
+ carry3 = s3 >> 21;
+ s4 += carry3;
+ s3 -= carry3 * (1 << 21);
+ carry4 = s4 >> 21;
+ s5 += carry4;
+ s4 -= carry4 * (1 << 21);
+ carry5 = s5 >> 21;
+ s6 += carry5;
+ s5 -= carry5 * (1 << 21);
+ carry6 = s6 >> 21;
+ s7 += carry6;
+ s6 -= carry6 * (1 << 21);
+ carry7 = s7 >> 21;
+ s8 += carry7;
+ s7 -= carry7 * (1 << 21);
+ carry8 = s8 >> 21;
+ s9 += carry8;
+ s8 -= carry8 * (1 << 21);
+ carry9 = s9 >> 21;
+ s10 += carry9;
+ s9 -= carry9 * (1 << 21);
+ carry10 = s10 >> 21;
+ s11 += carry10;
+ s10 -= carry10 * (1 << 21);
+
+ s[0] = (uint8_t)(s0 >> 0);
+ s[1] = (uint8_t)(s0 >> 8);
+ s[2] = (uint8_t)((s0 >> 16) | (s1 << 5));
+ s[3] = (uint8_t)(s1 >> 3);
+ s[4] = (uint8_t)(s1 >> 11);
+ s[5] = (uint8_t)((s1 >> 19) | (s2 << 2));
+ s[6] = (uint8_t)(s2 >> 6);
+ s[7] = (uint8_t)((s2 >> 14) | (s3 << 7));
+ s[8] = (uint8_t)(s3 >> 1);
+ s[9] = (uint8_t)(s3 >> 9);
+ s[10] = (uint8_t)((s3 >> 17) | (s4 << 4));
+ s[11] = (uint8_t)(s4 >> 4);
+ s[12] = (uint8_t)(s4 >> 12);
+ s[13] = (uint8_t)((s4 >> 20) | (s5 << 1));
+ s[14] = (uint8_t)(s5 >> 7);
+ s[15] = (uint8_t)((s5 >> 15) | (s6 << 6));
+ s[16] = (uint8_t)(s6 >> 2);
+ s[17] = (uint8_t)(s6 >> 10);
+ s[18] = (uint8_t)((s6 >> 18) | (s7 << 3));
+ s[19] = (uint8_t)(s7 >> 5);
+ s[20] = (uint8_t)(s7 >> 13);
+ s[21] = (uint8_t)(s8 >> 0);
+ s[22] = (uint8_t)(s8 >> 8);
+ s[23] = (uint8_t)((s8 >> 16) | (s9 << 5));
+ s[24] = (uint8_t)(s9 >> 3);
+ s[25] = (uint8_t)(s9 >> 11);
+ s[26] = (uint8_t)((s9 >> 19) | (s10 << 2));
+ s[27] = (uint8_t)(s10 >> 6);
+ s[28] = (uint8_t)((s10 >> 14) | (s11 << 7));
+ s[29] = (uint8_t)(s11 >> 1);
+ s[30] = (uint8_t)(s11 >> 9);
+ s[31] = (uint8_t)(s11 >> 17);
+}
+
+int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[32], const uint8_t private_key[32]) {
+ uint8_t az[SHA512_DIGEST_LENGTH];
+ uint8_t nonce[SHA512_DIGEST_LENGTH];
+ ge_p3 R;
+ uint8_t hram[SHA512_DIGEST_LENGTH];
+ SHA512_CTX hash_ctx;
+
+ SHA512_Init(&hash_ctx);
+ SHA512_Update(&hash_ctx, private_key, 32);
+ SHA512_Final(az, &hash_ctx);
+
+ az[0] &= 248;
+ az[31] &= 63;
+ az[31] |= 64;
+
+ SHA512_Init(&hash_ctx);
+ SHA512_Update(&hash_ctx, az + 32, 32);
+ SHA512_Update(&hash_ctx, message, message_len);
+ SHA512_Final(nonce, &hash_ctx);
+
+ x25519_sc_reduce(nonce);
+ ge_scalarmult_base(&R, nonce);
+ ge_p3_tobytes(out_sig, &R);
+
+ SHA512_Init(&hash_ctx);
+ SHA512_Update(&hash_ctx, out_sig, 32);
+ SHA512_Update(&hash_ctx, public_key, 32);
+ SHA512_Update(&hash_ctx, message, message_len);
+ SHA512_Final(hram, &hash_ctx);
+
+ x25519_sc_reduce(hram);
+ sc_muladd(out_sig + 32, hram, az, nonce);
+
+ OPENSSL_cleanse(&hash_ctx, sizeof(hash_ctx));
+ OPENSSL_cleanse(nonce, sizeof(nonce));
+ OPENSSL_cleanse(az, sizeof(az));
+
+ return 1;
+}
+
+int ED25519_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[64], const uint8_t public_key[32]) {
+ ge_p3 A;
+ uint8_t rcopy[32];
+ uint8_t scopy[32];
+ SHA512_CTX hash_ctx;
+ ge_p2 R;
+ uint8_t rcheck[32];
+ uint8_t h[SHA512_DIGEST_LENGTH];
+
+ if ((signature[63] & 224) != 0 ||
+ ge_frombytes_vartime(&A, public_key) != 0) {
+ return 0;
+ }
+
+ fe_neg(A.X, A.X);
+ fe_neg(A.T, A.T);
+
+ memcpy(rcopy, signature, 32);
+ memcpy(scopy, signature + 32, 32);
+
+ SHA512_Init(&hash_ctx);
+ SHA512_Update(&hash_ctx, signature, 32);
+ SHA512_Update(&hash_ctx, public_key, 32);
+ SHA512_Update(&hash_ctx, message, message_len);
+ SHA512_Final(h, &hash_ctx);
+
+ x25519_sc_reduce(h);
+
+ ge_double_scalarmult_vartime(&R, h, &A, scopy);
+
+ ge_tobytes(rcheck, &R);
+
+ return CRYPTO_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
+}
+
+void ED25519_public_from_private(uint8_t out_public_key[32],
+ const uint8_t private_key[32]) {
+ uint8_t az[SHA512_DIGEST_LENGTH];
+ ge_p3 A;
+
+ SHA512(private_key, 32, az);
+
+ az[0] &= 248;
+ az[31] &= 63;
+ az[31] |= 64;
+
+ ge_scalarmult_base(&A, az);
+ ge_p3_tobytes(out_public_key, &A);
+
+ OPENSSL_cleanse(az, sizeof(az));
+}
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32]) {
diff --git a/deps/openssl/openssl/crypto/ec/curve448/arch_32/arch_intrinsics.h b/deps/openssl/openssl/crypto/ec/curve448/arch_32/arch_intrinsics.h
new file mode 100644
index 0000000000..48081c7717
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/arch_32/arch_intrinsics.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_ARCH_32_ARCH_INTRINSICS_H
+# define HEADER_ARCH_32_ARCH_INTRINSICS_H
+
+#include "internal/constant_time_locl.h"
+
+# define ARCH_WORD_BITS 32
+
+#define word_is_zero(a) constant_time_is_zero_32(a)
+
+static ossl_inline uint64_t widemul(uint32_t a, uint32_t b)
+{
+ return ((uint64_t)a) * b;
+}
+
+#endif /* HEADER_ARCH_32_ARCH_INTRINSICS_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.c b/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.c
new file mode 100644
index 0000000000..8a89d276ed
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#include "field.h"
+
+void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs)
+{
+ const uint32_t *a = as->limb, *b = bs->limb;
+ uint32_t *c = cs->limb;
+ uint64_t accum0 = 0, accum1 = 0, accum2 = 0;
+ uint32_t mask = (1 << 28) - 1;
+ uint32_t aa[8], bb[8];
+ int i, j;
+
+ for (i = 0; i < 8; i++) {
+ aa[i] = a[i] + a[i + 8];
+ bb[i] = b[i] + b[i + 8];
+ }
+
+ for (j = 0; j < 8; j++) {
+ accum2 = 0;
+ for (i = 0; i < j + 1; i++) {
+ accum2 += widemul(a[j - i], b[i]);
+ accum1 += widemul(aa[j - i], bb[i]);
+ accum0 += widemul(a[8 + j - i], b[8 + i]);
+ }
+ accum1 -= accum2;
+ accum0 += accum2;
+ accum2 = 0;
+ for (i = j + 1; i < 8; i++) {
+ accum0 -= widemul(a[8 + j - i], b[i]);
+ accum2 += widemul(aa[8 + j - i], bb[i]);
+ accum1 += widemul(a[16 + j - i], b[8 + i]);
+ }
+ accum1 += accum2;
+ accum0 += accum2;
+ c[j] = ((uint32_t)(accum0)) & mask;
+ c[j + 8] = ((uint32_t)(accum1)) & mask;
+ accum0 >>= 28;
+ accum1 >>= 28;
+ }
+
+ accum0 += accum1;
+ accum0 += c[8];
+ accum1 += c[0];
+ c[8] = ((uint32_t)(accum0)) & mask;
+ c[0] = ((uint32_t)(accum1)) & mask;
+
+ accum0 >>= 28;
+ accum1 >>= 28;
+ c[9] += ((uint32_t)(accum0));
+ c[1] += ((uint32_t)(accum1));
+}
+
+void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b)
+{
+ const uint32_t *a = as->limb;
+ uint32_t *c = cs->limb;
+ uint64_t accum0 = 0, accum8 = 0;
+ uint32_t mask = (1 << 28) - 1;
+ int i;
+
+ assert(b <= mask);
+
+ for (i = 0; i < 8; i++) {
+ accum0 += widemul(b, a[i]);
+ accum8 += widemul(b, a[i + 8]);
+ c[i] = accum0 & mask;
+ accum0 >>= 28;
+ c[i + 8] = accum8 & mask;
+ accum8 >>= 28;
+ }
+
+ accum0 += accum8 + c[8];
+ c[8] = ((uint32_t)accum0) & mask;
+ c[9] += (uint32_t)(accum0 >> 28);
+
+ accum8 += c[0];
+ c[0] = ((uint32_t)accum8) & mask;
+ c[1] += (uint32_t)(accum8 >> 28);
+}
+
+void gf_sqr(gf_s * RESTRICT cs, const gf as)
+{
+ gf_mul(cs, as, as); /* Performs better with a dedicated square */
+}
diff --git a/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.h b/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.h
new file mode 100644
index 0000000000..bbde84a038
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/arch_32/f_impl.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_ARCH_32_F_IMPL_H
+# define HEADER_ARCH_32_F_IMPL_H
+
+# define GF_HEADROOM 2
+# define LIMB(x) ((x) & ((1 << 28) - 1)), ((x) >> 28)
+# define FIELD_LITERAL(a, b, c, d, e, f, g, h) \
+ {{LIMB(a), LIMB(b), LIMB(c), LIMB(d), LIMB(e), LIMB(f), LIMB(g), LIMB(h)}}
+
+# define LIMB_PLACE_VALUE(i) 28
+
+void gf_add_RAW(gf out, const gf a, const gf b)
+{
+ unsigned int i;
+
+ for (i = 0; i < NLIMBS; i++)
+ out->limb[i] = a->limb[i] + b->limb[i];
+}
+
+void gf_sub_RAW(gf out, const gf a, const gf b)
+{
+ unsigned int i;
+
+ for (i = 0; i < NLIMBS; i++)
+ out->limb[i] = a->limb[i] - b->limb[i];
+}
+
+void gf_bias(gf a, int amt)
+{
+ unsigned int i;
+ uint32_t co1 = ((1 << 28) - 1) * amt, co2 = co1 - amt;
+
+ for (i = 0; i < NLIMBS; i++)
+ a->limb[i] += (i == NLIMBS / 2) ? co2 : co1;
+}
+
+void gf_weak_reduce(gf a)
+{
+ uint32_t mask = (1 << 28) - 1;
+ uint32_t tmp = a->limb[NLIMBS - 1] >> 28;
+ unsigned int i;
+
+ a->limb[NLIMBS / 2] += tmp;
+ for (i = NLIMBS - 1; i > 0; i--)
+ a->limb[i] = (a->limb[i] & mask) + (a->limb[i - 1] >> 28);
+ a->limb[0] = (a->limb[0] & mask) + tmp;
+}
+
+#endif /* HEADER_ARCH_32_F_IMPL_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/curve448.c b/deps/openssl/openssl/crypto/ec/curve448/curve448.c
new file mode 100644
index 0000000000..7dc68c8853
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/curve448.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+#include <openssl/crypto.h>
+#include "word.h"
+#include "field.h"
+
+#include "point_448.h"
+#include "ed448.h"
+#include "curve448_lcl.h"
+
+#define COFACTOR 4
+
+#define C448_WNAF_FIXED_TABLE_BITS 5
+#define C448_WNAF_VAR_TABLE_BITS 3
+
+#define EDWARDS_D (-39081)
+
+static const curve448_scalar_t precomputed_scalarmul_adjustment = {
+ {
+ {
+ SC_LIMB(0xc873d6d54a7bb0cf), SC_LIMB(0xe933d8d723a70aad),
+ SC_LIMB(0xbb124b65129c96fd), SC_LIMB(0x00000008335dc163)
+ }
+ }
+};
+
+#define TWISTED_D (EDWARDS_D - 1)
+
+#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
+
+/* Inverse. */
+static void gf_invert(gf y, const gf x, int assert_nonzero)
+{
+ mask_t ret;
+ gf t1, t2;
+
+ gf_sqr(t1, x); /* o^2 */
+ ret = gf_isr(t2, t1); /* +-1/sqrt(o^2) = +-1/o */
+ (void)ret;
+ if (assert_nonzero)
+ assert(ret);
+ gf_sqr(t1, t2);
+ gf_mul(t2, t1, x); /* not direct to y in case of alias. */
+ gf_copy(y, t2);
+}
+
+/** identity = (0,1) */
+const curve448_point_t curve448_point_identity =
+ { {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} };
+
+static void point_double_internal(curve448_point_t p, const curve448_point_t q,
+ int before_double)
+{
+ gf a, b, c, d;
+
+ gf_sqr(c, q->x);
+ gf_sqr(a, q->y);
+ gf_add_nr(d, c, a); /* 2+e */
+ gf_add_nr(p->t, q->y, q->x); /* 2+e */
+ gf_sqr(b, p->t);
+ gf_subx_nr(b, b, d, 3); /* 4+e */
+ gf_sub_nr(p->t, a, c); /* 3+e */
+ gf_sqr(p->x, q->z);
+ gf_add_nr(p->z, p->x, p->x); /* 2+e */
+ gf_subx_nr(a, p->z, p->t, 4); /* 6+e */
+ if (GF_HEADROOM == 5)
+ gf_weak_reduce(a); /* or 1+e */
+ gf_mul(p->x, a, b);
+ gf_mul(p->z, p->t, a);
+ gf_mul(p->y, p->t, d);
+ if (!before_double)
+ gf_mul(p->t, b, d);
+}
+
+void curve448_point_double(curve448_point_t p, const curve448_point_t q)
+{
+ point_double_internal(p, q, 0);
+}
+
+/* Operations on [p]niels */
+static ossl_inline void cond_neg_niels(niels_t n, mask_t neg)
+{
+ gf_cond_swap(n->a, n->b, neg);
+ gf_cond_neg(n->c, neg);
+}
+
+static void pt_to_pniels(pniels_t b, const curve448_point_t a)
+{
+ gf_sub(b->n->a, a->y, a->x);
+ gf_add(b->n->b, a->x, a->y);
+ gf_mulw(b->n->c, a->t, 2 * TWISTED_D);
+ gf_add(b->z, a->z, a->z);
+}
+
+static void pniels_to_pt(curve448_point_t e, const pniels_t d)
+{
+ gf eu;
+
+ gf_add(eu, d->n->b, d->n->a);
+ gf_sub(e->y, d->n->b, d->n->a);
+ gf_mul(e->t, e->y, eu);
+ gf_mul(e->x, d->z, e->y);
+ gf_mul(e->y, d->z, eu);
+ gf_sqr(e->z, d->z);
+}
+
+static void niels_to_pt(curve448_point_t e, const niels_t n)
+{
+ gf_add(e->y, n->b, n->a);
+ gf_sub(e->x, n->b, n->a);
+ gf_mul(e->t, e->y, e->x);
+ gf_copy(e->z, ONE);
+}
+
+static void add_niels_to_pt(curve448_point_t d, const niels_t e,
+ int before_double)
+{
+ gf a, b, c;
+
+ gf_sub_nr(b, d->y, d->x); /* 3+e */
+ gf_mul(a, e->a, b);
+ gf_add_nr(b, d->x, d->y); /* 2+e */
+ gf_mul(d->y, e->b, b);
+ gf_mul(d->x, e->c, d->t);
+ gf_add_nr(c, a, d->y); /* 2+e */
+ gf_sub_nr(b, d->y, a); /* 3+e */
+ gf_sub_nr(d->y, d->z, d->x); /* 3+e */
+ gf_add_nr(a, d->x, d->z); /* 2+e */
+ gf_mul(d->z, a, d->y);
+ gf_mul(d->x, d->y, b);
+ gf_mul(d->y, a, c);
+ if (!before_double)
+ gf_mul(d->t, b, c);
+}
+
+static void sub_niels_from_pt(curve448_point_t d, const niels_t e,
+ int before_double)
+{
+ gf a, b, c;
+
+ gf_sub_nr(b, d->y, d->x); /* 3+e */
+ gf_mul(a, e->b, b);
+ gf_add_nr(b, d->x, d->y); /* 2+e */
+ gf_mul(d->y, e->a, b);
+ gf_mul(d->x, e->c, d->t);
+ gf_add_nr(c, a, d->y); /* 2+e */
+ gf_sub_nr(b, d->y, a); /* 3+e */
+ gf_add_nr(d->y, d->z, d->x); /* 2+e */
+ gf_sub_nr(a, d->z, d->x); /* 3+e */
+ gf_mul(d->z, a, d->y);
+ gf_mul(d->x, d->y, b);
+ gf_mul(d->y, a, c);
+ if (!before_double)
+ gf_mul(d->t, b, c);
+}
+
+static void add_pniels_to_pt(curve448_point_t p, const pniels_t pn,
+ int before_double)
+{
+ gf L0;
+
+ gf_mul(L0, p->z, pn->z);
+ gf_copy(p->z, L0);
+ add_niels_to_pt(p, pn->n, before_double);
+}
+
+static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn,
+ int before_double)
+{
+ gf L0;
+
+ gf_mul(L0, p->z, pn->z);
+ gf_copy(p->z, L0);
+ sub_niels_from_pt(p, pn->n, before_double);
+}
+
+c448_bool_t curve448_point_eq(const curve448_point_t p,
+ const curve448_point_t q)
+{
+ mask_t succ;
+ gf a, b;
+
+ /* equality mod 2-torsion compares x/y */
+ gf_mul(a, p->y, q->x);
+ gf_mul(b, q->y, p->x);
+ succ = gf_eq(a, b);
+
+ return mask_to_bool(succ);
+}
+
+c448_bool_t curve448_point_valid(const curve448_point_t p)
+{
+ mask_t out;
+ gf a, b, c;
+
+ gf_mul(a, p->x, p->y);
+ gf_mul(b, p->z, p->t);
+ out = gf_eq(a, b);
+ gf_sqr(a, p->x);
+ gf_sqr(b, p->y);
+ gf_sub(a, b, a);
+ gf_sqr(b, p->t);
+ gf_mulw(c, b, TWISTED_D);
+ gf_sqr(b, p->z);
+ gf_add(b, b, c);
+ out &= gf_eq(a, b);
+ out &= ~gf_eq(p->z, ZERO);
+ return mask_to_bool(out);
+}
+
+static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni,
+ const niels_t * table,
+ int nelts, int idx)
+{
+ constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx);
+}
+
+void curve448_precomputed_scalarmul(curve448_point_t out,
+ const curve448_precomputed_s * table,
+ const curve448_scalar_t scalar)
+{
+ unsigned int i, j, k;
+ const unsigned int n = COMBS_N, t = COMBS_T, s = COMBS_S;
+ niels_t ni;
+ curve448_scalar_t scalar1x;
+
+ curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment);
+ curve448_scalar_halve(scalar1x, scalar1x);
+
+ for (i = s; i > 0; i--) {
+ if (i != s)
+ point_double_internal(out, out, 0);
+
+ for (j = 0; j < n; j++) {
+ int tab = 0;
+ mask_t invert;
+
+ for (k = 0; k < t; k++) {
+ unsigned int bit = (i - 1) + s * (k + j * t);
+
+ if (bit < C448_SCALAR_BITS)
+ tab |=
+ (scalar1x->limb[bit / WBITS] >> (bit % WBITS) & 1) << k;
+ }
+
+ invert = (tab >> (t - 1)) - 1;
+ tab ^= invert;
+ tab &= (1 << (t - 1)) - 1;
+
+ constant_time_lookup_niels(ni, &table->table[j << (t - 1)],
+ 1 << (t - 1), tab);
+
+ cond_neg_niels(ni, invert);
+ if ((i != s) || j != 0)
+ add_niels_to_pt(out, ni, j == n - 1 && i != 1);
+ else
+ niels_to_pt(out, ni);
+ }
+ }
+
+ OPENSSL_cleanse(ni, sizeof(ni));
+ OPENSSL_cleanse(scalar1x, sizeof(scalar1x));
+}
+
+void curve448_point_mul_by_ratio_and_encode_like_eddsa(
+ uint8_t enc[EDDSA_448_PUBLIC_BYTES],
+ const curve448_point_t p)
+{
+ gf x, y, z, t;
+ curve448_point_t q;
+
+ /* The point is now on the twisted curve. Move it to untwisted. */
+ curve448_point_copy(q, p);
+
+ {
+ /* 4-isogeny: 2xy/(y^+x^2), (y^2-x^2)/(2z^2-y^2+x^2) */
+ gf u;
+
+ gf_sqr(x, q->x);
+ gf_sqr(t, q->y);
+ gf_add(u, x, t);
+ gf_add(z, q->y, q->x);
+ gf_sqr(y, z);
+ gf_sub(y, y, u);
+ gf_sub(z, t, x);
+ gf_sqr(x, q->z);
+ gf_add(t, x, x);
+ gf_sub(t, t, z);
+ gf_mul(x, t, y);
+ gf_mul(y, z, u);
+ gf_mul(z, u, t);
+ OPENSSL_cleanse(u, sizeof(u));
+ }
+
+ /* Affinize */
+ gf_invert(z, z, 1);
+ gf_mul(t, x, z);
+ gf_mul(x, y, z);
+
+ /* Encode */
+ enc[EDDSA_448_PRIVATE_BYTES - 1] = 0;
+ gf_serialize(enc, x, 1);
+ enc[EDDSA_448_PRIVATE_BYTES - 1] |= 0x80 & gf_lobit(t);
+
+ OPENSSL_cleanse(x, sizeof(x));
+ OPENSSL_cleanse(y, sizeof(y));
+ OPENSSL_cleanse(z, sizeof(z));
+ OPENSSL_cleanse(t, sizeof(t));
+ curve448_point_destroy(q);
+}
+
+c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
+ curve448_point_t p,
+ const uint8_t enc[EDDSA_448_PUBLIC_BYTES])
+{
+ uint8_t enc2[EDDSA_448_PUBLIC_BYTES];
+ mask_t low;
+ mask_t succ;
+
+ memcpy(enc2, enc, sizeof(enc2));
+
+ low = ~word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1] & 0x80);
+ enc2[EDDSA_448_PRIVATE_BYTES - 1] &= ~0x80;
+
+ succ = gf_deserialize(p->y, enc2, 1, 0);
+ succ &= word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1]);
+
+ gf_sqr(p->x, p->y);
+ gf_sub(p->z, ONE, p->x); /* num = 1-y^2 */
+ gf_mulw(p->t, p->x, EDWARDS_D); /* dy^2 */
+ gf_sub(p->t, ONE, p->t); /* denom = 1-dy^2 or 1-d + dy^2 */
+
+ gf_mul(p->x, p->z, p->t);
+ succ &= gf_isr(p->t, p->x); /* 1/sqrt(num * denom) */
+
+ gf_mul(p->x, p->t, p->z); /* sqrt(num / denom) */
+ gf_cond_neg(p->x, gf_lobit(p->x) ^ low);
+ gf_copy(p->z, ONE);
+
+ {
+ gf a, b, c, d;
+
+ /* 4-isogeny 2xy/(y^2-ax^2), (y^2+ax^2)/(2-y^2-ax^2) */
+ gf_sqr(c, p->x);
+ gf_sqr(a, p->y);
+ gf_add(d, c, a);
+ gf_add(p->t, p->y, p->x);
+ gf_sqr(b, p->t);
+ gf_sub(b, b, d);
+ gf_sub(p->t, a, c);
+ gf_sqr(p->x, p->z);
+ gf_add(p->z, p->x, p->x);
+ gf_sub(a, p->z, d);
+ gf_mul(p->x, a, b);
+ gf_mul(p->z, p->t, a);
+ gf_mul(p->y, p->t, d);
+ gf_mul(p->t, b, d);
+ OPENSSL_cleanse(a, sizeof(a));
+ OPENSSL_cleanse(b, sizeof(b));
+ OPENSSL_cleanse(c, sizeof(c));
+ OPENSSL_cleanse(d, sizeof(d));
+ }
+
+ OPENSSL_cleanse(enc2, sizeof(enc2));
+ assert(curve448_point_valid(p) || ~succ);
+
+ return c448_succeed_if(mask_to_bool(succ));
+}
+
+c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES],
+ const uint8_t base[X_PUBLIC_BYTES],
+ const uint8_t scalar[X_PRIVATE_BYTES])
+{
+ gf x1, x2, z2, x3, z3, t1, t2;
+ int t;
+ mask_t swap = 0;
+ mask_t nz;
+
+ (void)gf_deserialize(x1, base, 1, 0);
+ gf_copy(x2, ONE);
+ gf_copy(z2, ZERO);
+ gf_copy(x3, x1);
+ gf_copy(z3, ONE);
+
+ for (t = X_PRIVATE_BITS - 1; t >= 0; t--) {
+ uint8_t sb = scalar[t / 8];
+ mask_t k_t;
+
+ /* Scalar conditioning */
+ if (t / 8 == 0)
+ sb &= -(uint8_t)COFACTOR;
+ else if (t == X_PRIVATE_BITS - 1)
+ sb = -1;
+
+ k_t = (sb >> (t % 8)) & 1;
+ k_t = 0 - k_t; /* set to all 0s or all 1s */
+
+ swap ^= k_t;
+ gf_cond_swap(x2, x3, swap);
+ gf_cond_swap(z2, z3, swap);
+ swap = k_t;
+
+ /*
+ * The "_nr" below skips coefficient reduction. In the following
+ * comments, "2+e" is saying that the coefficients are at most 2+epsilon
+ * times the reduction limit.
+ */
+ gf_add_nr(t1, x2, z2); /* A = x2 + z2 */ /* 2+e */
+ gf_sub_nr(t2, x2, z2); /* B = x2 - z2 */ /* 3+e */
+ gf_sub_nr(z2, x3, z3); /* D = x3 - z3 */ /* 3+e */
+ gf_mul(x2, t1, z2); /* DA */
+ gf_add_nr(z2, z3, x3); /* C = x3 + z3 */ /* 2+e */
+ gf_mul(x3, t2, z2); /* CB */
+ gf_sub_nr(z3, x2, x3); /* DA-CB */ /* 3+e */
+ gf_sqr(z2, z3); /* (DA-CB)^2 */
+ gf_mul(z3, x1, z2); /* z3 = x1(DA-CB)^2 */
+ gf_add_nr(z2, x2, x3); /* (DA+CB) */ /* 2+e */
+ gf_sqr(x3, z2); /* x3 = (DA+CB)^2 */
+
+ gf_sqr(z2, t1); /* AA = A^2 */
+ gf_sqr(t1, t2); /* BB = B^2 */
+ gf_mul(x2, z2, t1); /* x2 = AA*BB */
+ gf_sub_nr(t2, z2, t1); /* E = AA-BB */ /* 3+e */
+
+ gf_mulw(t1, t2, -EDWARDS_D); /* E*-d = a24*E */
+ gf_add_nr(t1, t1, z2); /* AA + a24*E */ /* 2+e */
+ gf_mul(z2, t2, t1); /* z2 = E(AA+a24*E) */
+ }
+
+ /* Finish */
+ gf_cond_swap(x2, x3, swap);
+ gf_cond_swap(z2, z3, swap);
+ gf_invert(z2, z2, 0);
+ gf_mul(x1, x2, z2);
+ gf_serialize(out, x1, 1);
+ nz = ~gf_eq(x1, ZERO);
+
+ OPENSSL_cleanse(x1, sizeof(x1));
+ OPENSSL_cleanse(x2, sizeof(x2));
+ OPENSSL_cleanse(z2, sizeof(z2));
+ OPENSSL_cleanse(x3, sizeof(x3));
+ OPENSSL_cleanse(z3, sizeof(z3));
+ OPENSSL_cleanse(t1, sizeof(t1));
+ OPENSSL_cleanse(t2, sizeof(t2));
+
+ return c448_succeed_if(mask_to_bool(nz));
+}
+
+void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t
+ out[X_PUBLIC_BYTES],
+ const curve448_point_t p)
+{
+ curve448_point_t q;
+
+ curve448_point_copy(q, p);
+ gf_invert(q->t, q->x, 0); /* 1/x */
+ gf_mul(q->z, q->t, q->y); /* y/x */
+ gf_sqr(q->y, q->z); /* (y/x)^2 */
+ gf_serialize(out, q->y, 1);
+ curve448_point_destroy(q);
+}
+
+void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES],
+ const uint8_t scalar[X_PRIVATE_BYTES])
+{
+ /* Scalar conditioning */
+ uint8_t scalar2[X_PRIVATE_BYTES];
+ curve448_scalar_t the_scalar;
+ curve448_point_t p;
+ unsigned int i;
+
+ memcpy(scalar2, scalar, sizeof(scalar2));
+ scalar2[0] &= -(uint8_t)COFACTOR;
+
+ scalar2[X_PRIVATE_BYTES - 1] &= ~((0u - 1u) << ((X_PRIVATE_BITS + 7) % 8));
+ scalar2[X_PRIVATE_BYTES - 1] |= 1 << ((X_PRIVATE_BITS + 7) % 8);
+
+ curve448_scalar_decode_long(the_scalar, scalar2, sizeof(scalar2));
+
+ /* Compensate for the encoding ratio */
+ for (i = 1; i < X448_ENCODE_RATIO; i <<= 1)
+ curve448_scalar_halve(the_scalar, the_scalar);
+
+ curve448_precomputed_scalarmul(p, curve448_precomputed_base, the_scalar);
+ curve448_point_mul_by_ratio_and_encode_like_x448(out, p);
+ curve448_point_destroy(p);
+}
+
+/* Control for variable-time scalar multiply algorithms. */
+struct smvt_control {
+ int power, addend;
+};
+
+#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
+# define NUMTRAILINGZEROS __builtin_ctz
+#else
+# define NUMTRAILINGZEROS numtrailingzeros
+static uint32_t numtrailingzeros(uint32_t i)
+{
+ uint32_t tmp;
+ uint32_t num = 31;
+
+ if (i == 0)
+ return 32;
+
+ tmp = i << 16;
+ if (tmp != 0) {
+ i = tmp;
+ num -= 16;
+ }
+ tmp = i << 8;
+ if (tmp != 0) {
+ i = tmp;
+ num -= 8;
+ }
+ tmp = i << 4;
+ if (tmp != 0) {
+ i = tmp;
+ num -= 4;
+ }
+ tmp = i << 2;
+ if (tmp != 0) {
+ i = tmp;
+ num -= 2;
+ }
+ tmp = i << 1;
+ if (tmp != 0)
+ num--;
+
+ return num;
+}
+#endif
+
+static int recode_wnaf(struct smvt_control *control,
+ /* [nbits/(table_bits + 1) + 3] */
+ const curve448_scalar_t scalar,
+ unsigned int table_bits)
+{
+ unsigned int table_size = C448_SCALAR_BITS / (table_bits + 1) + 3;
+ int position = table_size - 1; /* at the end */
+ uint64_t current = scalar->limb[0] & 0xFFFF;
+ uint32_t mask = (1 << (table_bits + 1)) - 1;
+ unsigned int w;
+ const unsigned int B_OVER_16 = sizeof(scalar->limb[0]) / 2;
+ unsigned int n, i;
+
+ /* place the end marker */
+ control[position].power = -1;
+ control[position].addend = 0;
+ position--;
+
+ /*
+ * PERF: Could negate scalar if it's large. But then would need more cases
+ * in the actual code that uses it, all for an expected reduction of like
+ * 1/5 op. Probably not worth it.
+ */
+
+ for (w = 1; w < (C448_SCALAR_BITS - 1) / 16 + 3; w++) {
+ if (w < (C448_SCALAR_BITS - 1) / 16 + 1) {
+ /* Refill the 16 high bits of current */
+ current += (uint32_t)((scalar->limb[w / B_OVER_16]
+ >> (16 * (w % B_OVER_16))) << 16);
+ }
+
+ while (current & 0xFFFF) {
+ uint32_t pos = NUMTRAILINGZEROS((uint32_t)current);
+ uint32_t odd = (uint32_t)current >> pos;
+ int32_t delta = odd & mask;
+
+ assert(position >= 0);
+ if (odd & (1 << (table_bits + 1)))
+ delta -= (1 << (table_bits + 1));
+ current -= delta * (1 << pos);
+ control[position].power = pos + 16 * (w - 1);
+ control[position].addend = delta;
+ position--;
+ }
+ current >>= 16;
+ }
+ assert(current == 0);
+
+ position++;
+ n = table_size - position;
+ for (i = 0; i < n; i++)
+ control[i] = control[i + position];
+
+ return n - 1;
+}
+
+static void prepare_wnaf_table(pniels_t * output,
+ const curve448_point_t working,
+ unsigned int tbits)
+{
+ curve448_point_t tmp;
+ int i;
+ pniels_t twop;
+
+ pt_to_pniels(output[0], working);
+
+ if (tbits == 0)
+ return;
+
+ curve448_point_double(tmp, working);
+ pt_to_pniels(twop, tmp);
+
+ add_pniels_to_pt(tmp, output[0], 0);
+ pt_to_pniels(output[1], tmp);
+
+ for (i = 2; i < 1 << tbits; i++) {
+ add_pniels_to_pt(tmp, twop, 0);
+ pt_to_pniels(output[i], tmp);
+ }
+
+ curve448_point_destroy(tmp);
+ OPENSSL_cleanse(twop, sizeof(twop));
+}
+
+void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
+ const curve448_scalar_t scalar1,
+ const curve448_point_t base2,
+ const curve448_scalar_t scalar2)
+{
+ const int table_bits_var = C448_WNAF_VAR_TABLE_BITS;
+ const int table_bits_pre = C448_WNAF_FIXED_TABLE_BITS;
+ struct smvt_control control_var[C448_SCALAR_BITS /
+ (C448_WNAF_VAR_TABLE_BITS + 1) + 3];
+ struct smvt_control control_pre[C448_SCALAR_BITS /
+ (C448_WNAF_FIXED_TABLE_BITS + 1) + 3];
+ int ncb_pre = recode_wnaf(control_pre, scalar1, table_bits_pre);
+ int ncb_var = recode_wnaf(control_var, scalar2, table_bits_var);
+ pniels_t precmp_var[1 << C448_WNAF_VAR_TABLE_BITS];
+ int contp = 0, contv = 0, i;
+
+ prepare_wnaf_table(precmp_var, base2, table_bits_var);
+ i = control_var[0].power;
+
+ if (i < 0) {
+ curve448_point_copy(combo, curve448_point_identity);
+ return;
+ }
+ if (i > control_pre[0].power) {
+ pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]);
+ contv++;
+ } else if (i == control_pre[0].power && i >= 0) {
+ pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]);
+ add_niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1],
+ i);
+ contv++;
+ contp++;
+ } else {
+ i = control_pre[0].power;
+ niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1]);
+ contp++;
+ }
+
+ for (i--; i >= 0; i--) {
+ int cv = (i == control_var[contv].power);
+ int cp = (i == control_pre[contp].power);
+
+ point_double_internal(combo, combo, i && !(cv || cp));
+
+ if (cv) {
+ assert(control_var[contv].addend);
+
+ if (control_var[contv].addend > 0)
+ add_pniels_to_pt(combo,
+ precmp_var[control_var[contv].addend >> 1],
+ i && !cp);
+ else
+ sub_pniels_from_pt(combo,
+ precmp_var[(-control_var[contv].addend)
+ >> 1], i && !cp);
+ contv++;
+ }
+
+ if (cp) {
+ assert(control_pre[contp].addend);
+
+ if (control_pre[contp].addend > 0)
+ add_niels_to_pt(combo,
+ curve448_wnaf_base[control_pre[contp].addend
+ >> 1], i);
+ else
+ sub_niels_from_pt(combo,
+ curve448_wnaf_base[(-control_pre
+ [contp].addend) >> 1], i);
+ contp++;
+ }
+ }
+
+ /* This function is non-secret, but whatever this is cheap. */
+ OPENSSL_cleanse(control_var, sizeof(control_var));
+ OPENSSL_cleanse(control_pre, sizeof(control_pre));
+ OPENSSL_cleanse(precmp_var, sizeof(precmp_var));
+
+ assert(contv == ncb_var);
+ (void)ncb_var;
+ assert(contp == ncb_pre);
+ (void)ncb_pre;
+}
+
+void curve448_point_destroy(curve448_point_t point)
+{
+ OPENSSL_cleanse(point, sizeof(curve448_point_t));
+}
+
+int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
+ const uint8_t peer_public_value[56])
+{
+ return x448_int(out_shared_key, peer_public_value, private_key)
+ == C448_SUCCESS;
+}
+
+void X448_public_from_private(uint8_t out_public_value[56],
+ const uint8_t private_key[56])
+{
+ x448_derive_public_key(out_public_value, private_key);
+}
diff --git a/deps/openssl/openssl/crypto/ec/curve448/curve448_lcl.h b/deps/openssl/openssl/crypto/ec/curve448/curve448_lcl.h
new file mode 100644
index 0000000000..2bc3bd84c8
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/curve448_lcl.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+#ifndef HEADER_CURVE448_LCL_H
+# define HEADER_CURVE448_LCL_H
+# include "curve448utils.h"
+
+int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
+ const uint8_t peer_public_value[56]);
+
+void X448_public_from_private(uint8_t out_public_value[56],
+ const uint8_t private_key[56]);
+
+int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len);
+
+int ED448_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len);
+
+int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len);
+
+int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
+ const uint8_t public_key[57], const uint8_t *context,
+ size_t context_len);
+
+int ED448_public_from_private(uint8_t out_public_key[57],
+ const uint8_t private_key[57]);
+
+#endif /* HEADER_CURVE448_LCL_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/curve448_tables.c b/deps/openssl/openssl/crypto/ec/curve448/curve448_tables.c
new file mode 100644
index 0000000000..a1185b1eee
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/curve448_tables.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+#include "field.h"
+
+#include "point_448.h"
+
+static const curve448_precomputed_s curve448_precomputed_base_table = {
+ {
+ {{
+ {FIELD_LITERAL(0x00cc3b062366f4cc,0x003d6e34e314aa3c,0x00d51c0a7521774d,0x0094e060eec6ab8b,0x00d21291b4d80082,0x00befed12b55ef1e,0x00c3dd2df5c94518,0x00e0a7b112b8d4e6)},
+ {FIELD_LITERAL(0x0019eb5608d8723a,0x00d1bab52fb3aedb,0x00270a7311ebc90c,0x0037c12b91be7f13,0x005be16cd8b5c704,0x003e181acda888e1,0x00bc1f00fc3fc6d0,0x00d3839bfa319e20)},
+ {FIELD_LITERAL(0x003caeb88611909f,0x00ea8b378c4df3d4,0x00b3295b95a5a19a,0x00a65f97514bdfb5,0x00b39efba743cab1,0x0016ba98b862fd2d,0x0001508812ee71d7,0x000a75740eea114a)},
+ }}, {{
+ {FIELD_LITERAL(0x00ebcf0eb649f823,0x00166d332e98ea03,0x0059ddf64f5cd5f6,0x0047763123d9471b,0x00a64065c53ef62f,0x00978e44c480153d,0x000b5b2a0265f194,0x0046a24b9f32965a)},
+ {FIELD_LITERAL(0x00b9eef787034df0,0x0020bc24de3390cd,0x000022160bae99bb,0x00ae66e886e97946,0x0048d4bbe02cbb8b,0x0072ba97b34e38d4,0x00eae7ec8f03e85a,0x005ba92ecf808b2c)},
+ {FIELD_LITERAL(0x00c9cfbbe74258fd,0x00843a979ea9eaa7,0x000cbb4371cfbe90,0x0059bac8f7f0a628,0x004b3dff882ff530,0x0011869df4d90733,0x00595aa71f4abfc2,0x0070e2d38990c2e6)},
+ }}, {{
+ {FIELD_LITERAL(0x00de2010c0a01733,0x00c739a612e24297,0x00a7212643141d7c,0x00f88444f6b67c11,0x00484b7b16ec28f2,0x009c1b8856af9c68,0x00ff4669591fe9d6,0x0054974be08a32c8)},
+ {FIELD_LITERAL(0x0010de3fd682ceed,0x008c07642d83ca4e,0x0013bb064e00a1cc,0x009411ae27870e11,0x00ea8e5b4d531223,0x0032fe7d2aaece2e,0x00d989e243e7bb41,0x000fe79a508e9b8b)},
+ {FIELD_LITERAL(0x005e0426b9bfc5b1,0x0041a5b1d29ee4fa,0x0015b0def7774391,0x00bc164f1f51af01,0x00d543b0942797b9,0x003c129b6398099c,0x002b114c6e5adf18,0x00b4e630e4018a7b)},
+ }}, {{
+ {FIELD_LITERAL(0x00d490afc95f8420,0x00b096bf50c1d9b9,0x00799fd707679866,0x007c74d9334afbea,0x00efaa8be80ff4ed,0x0075c4943bb81694,0x00c21c2fca161f36,0x00e77035d492bfee)},
+ {FIELD_LITERAL(0x006658a190dd6661,0x00e0e9bab38609a6,0x0028895c802237ed,0x006a0229c494f587,0x002dcde96c9916b7,0x00d158822de16218,0x00173b917a06856f,0x00ca78a79ae07326)},
+ {FIELD_LITERAL(0x00e35bfc79caced4,0x0087238a3e1fe3bb,0x00bcbf0ff4ceff5b,0x00a19c1c94099b91,0x0071e102b49db976,0x0059e3d004eada1e,0x008da78afa58a47e,0x00579c8ebf269187)},
+ }}, {{
+ {FIELD_LITERAL(0x00a16c2905eee75f,0x009d4bcaea2c7e1d,0x00d3bd79bfad19df,0x0050da745193342c,0x006abdb8f6b29ab1,0x00a24fe0a4fef7ef,0x0063730da1057dfb,0x00a08c312c8eb108)},
+ {FIELD_LITERAL(0x00b583be005375be,0x00a40c8f8a4e3df4,0x003fac4a8f5bdbf7,0x00d4481d872cd718,0x004dc8749cdbaefe,0x00cce740d5e5c975,0x000b1c1f4241fd21,0x00a76de1b4e1cd07)},
+ {FIELD_LITERAL(0x007a076500d30b62,0x000a6e117b7f090f,0x00c8712ae7eebd9a,0x000fbd6c1d5f6ff7,0x003a7977246ebf11,0x00166ed969c6600e,0x00aa42e469c98bec,0x00dc58f307cf0666)},
+ }}, {{
+ {FIELD_LITERAL(0x004b491f65a9a28b,0x006a10309e8a55b7,0x00b67210185187ef,0x00cf6497b12d9b8f,0x0085778c56e2b1ba,0x0015b4c07a814d85,0x00686479e62da561,0x008de5d88f114916)},
+ {FIELD_LITERAL(0x00e37c88d6bba7b1,0x003e4577e1b8d433,0x0050d8ea5f510ec0,0x0042fc9f2da9ef59,0x003bd074c1141420,0x00561b8b7b68774e,0x00232e5e5d1013a3,0x006b7f2cb3d7e73f)},
+ {FIELD_LITERAL(0x004bdd0f0b41e6a0,0x001773057c405d24,0x006029f99915bd97,0x006a5ba70a17fe2f,0x0046111977df7e08,0x004d8124c89fb6b7,0x00580983b2bb2724,0x00207bf330d6f3fe)},
+ }}, {{
+ {FIELD_LITERAL(0x007efdc93972a48b,0x002f5e50e78d5fee,0x0080dc11d61c7fe5,0x0065aa598707245b,0x009abba2300641be,0x000c68787656543a,0x00ffe0fef2dc0a17,0x00007ffbd6cb4f3a)},
+ {FIELD_LITERAL(0x0036012f2b836efc,0x00458c126d6b5fbc,0x00a34436d719ad1e,0x0097be6167117dea,0x0009c219c879cff3,0x0065564493e60755,0x00993ac94a8cdec0,0x002d4885a4d0dbaf)},
+ {FIELD_LITERAL(0x00598b60b4c068ba,0x00c547a0be7f1afd,0x009582164acf12af,0x00af4acac4fbbe40,0x005f6ca7c539121a,0x003b6e752ebf9d66,0x00f08a30d5cac5d4,0x00e399bb5f97c5a9)},
+ }}, {{
+ {FIELD_LITERAL(0x007445a0409c0a66,0x00a65c369f3829c0,0x0031d248a4f74826,0x006817f34defbe8e,0x00649741d95ebf2e,0x00d46466ab16b397,0x00fdc35703bee414,0x00343b43334525f8)},
+ {FIELD_LITERAL(0x001796bea93f6401,0x00090c5a42e85269,0x00672412ba1252ed,0x001201d47b6de7de,0x006877bccfe66497,0x00b554fd97a4c161,0x009753f42dbac3cf,0x00e983e3e378270a)},
+ {FIELD_LITERAL(0x00ac3eff18849872,0x00f0eea3bff05690,0x00a6d72c21dd505d,0x001b832642424169,0x00a6813017b540e5,0x00a744bd71b385cd,0x0022a7d089130a7b,0x004edeec9a133486)},
+ }}, {{
+ {FIELD_LITERAL(0x00b2d6729196e8a9,0x0088a9bb2031cef4,0x00579e7787dc1567,0x0030f49feb059190,0x00a0b1d69c7f7d8f,0x0040bdcc6d9d806f,0x00d76c4037edd095,0x00bbf24376415dd7)},
+ {FIELD_LITERAL(0x00240465ff5a7197,0x00bb97e76caf27d0,0x004b4edbf8116d39,0x001d8586f708cbaa,0x000f8ee8ff8e4a50,0x00dde5a1945dd622,0x00e6fc1c0957e07c,0x0041c9cdabfd88a0)},
+ {FIELD_LITERAL(0x005344b0bf5b548c,0x002957d0b705cc99,0x00f586a70390553d,0x0075b3229f583cc3,0x00a1aa78227490e4,0x001bf09cf7957717,0x00cf6bf344325f52,0x0065bd1c23ca3ecf)},
+ }}, {{
+ {FIELD_LITERAL(0x009bff3b3239363c,0x00e17368796ef7c0,0x00528b0fe0971f3a,0x0008014fc8d4a095,0x00d09f2e8a521ec4,0x006713ab5dde5987,0x0003015758e0dbb1,0x00215999f1ba212d)},
+ {FIELD_LITERAL(0x002c88e93527da0e,0x0077c78f3456aad5,0x0071087a0a389d1c,0x00934dac1fb96dbd,0x008470e801162697,0x005bc2196cd4ad49,0x00e535601d5087c3,0x00769888700f497f)},
+ {FIELD_LITERAL(0x00da7a4b557298ad,0x0019d2589ea5df76,0x00ef3e38be0c6497,0x00a9644e1312609a,0x004592f61b2558da,0x0082c1df510d7e46,0x0042809a535c0023,0x00215bcb5afd7757)},
+ }}, {{
+ {FIELD_LITERAL(0x002b9df55a1a4213,0x00dcfc3b464a26be,0x00c4f9e07a8144d5,0x00c8e0617a92b602,0x008e3c93accafae0,0x00bf1bcb95b2ca60,0x004ce2426a613bf3,0x00266cac58e40921)},
+ {FIELD_LITERAL(0x008456d5db76e8f0,0x0032ca9cab2ce163,0x0059f2b8bf91abcf,0x0063c2a021712788,0x00f86155af22f72d,0x00db98b2a6c005a0,0x00ac6e416a693ac4,0x007a93572af53226)},
+ {FIELD_LITERAL(0x0087767520f0de22,0x0091f64012279fb5,0x001050f1f0644999,0x004f097a2477ad3c,0x006b37913a9947bd,0x001a3d78645af241,0x0057832bbb3008a7,0x002c1d902b80dc20)},
+ }}, {{
+ {FIELD_LITERAL(0x001a6002bf178877,0x009bce168aa5af50,0x005fc318ff04a7f5,0x0052818f55c36461,0x008768f5d4b24afb,0x0037ffbae7b69c85,0x0018195a4b61edc0,0x001e12ea088434b2)},
+ {FIELD_LITERAL(0x0047d3f804e7ab07,0x00a809ab5f905260,0x00b3ffc7cdaf306d,0x00746e8ec2d6e509,0x00d0dade8887a645,0x00acceeebde0dd37,0x009bc2579054686b,0x0023804f97f1c2bf)},
+ {FIELD_LITERAL(0x0043e2e2e50b80d7,0x00143aafe4427e0f,0x005594aaecab855b,0x008b12ccaaecbc01,0x002deeb091082bc3,0x009cca4be2ae7514,0x00142b96e696d047,0x00ad2a2b1c05256a)},
+ }}, {{
+ {FIELD_LITERAL(0x003914f2f144b78b,0x007a95dd8bee6f68,0x00c7f4384d61c8e6,0x004e51eb60f1bdb2,0x00f64be7aa4621d8,0x006797bfec2f0ac0,0x007d17aab3c75900,0x001893e73cac8bc5)},
+ {FIELD_LITERAL(0x00140360b768665b,0x00b68aca4967f977,0x0001089b66195ae4,0x00fe71122185e725,0x000bca2618d49637,0x00a54f0557d7e98a,0x00cdcd2f91d6f417,0x00ab8c13741fd793)},
+ {FIELD_LITERAL(0x00725ee6b1e549e0,0x007124a0769777fa,0x000b68fdad07ae42,0x0085b909cd4952df,0x0092d2e3c81606f4,0x009f22f6cac099a0,0x00f59da57f2799a8,0x00f06c090122f777)},
+ }}, {{
+ {FIELD_LITERAL(0x00ce0bed0a3532bc,0x001a5048a22df16b,0x00e31db4cbad8bf1,0x00e89292120cf00e,0x007d1dd1a9b00034,0x00e2a9041ff8f680,0x006a4c837ae596e7,0x00713af1068070b3)},
+ {FIELD_LITERAL(0x00c4fe64ce66d04b,0x00b095d52e09b3d7,0x00758bbecb1a3a8e,0x00f35cce8d0650c0,0x002b878aa5984473,0x0062e0a3b7544ddc,0x00b25b290ed116fe,0x007b0f6abe0bebf2)},
+ {FIELD_LITERAL(0x0081d4e3addae0a8,0x003410c836c7ffcc,0x00c8129ad89e4314,0x000e3d5a23922dcd,0x00d91e46f29c31f3,0x006c728cde8c5947,0x002bc655ba2566c0,0x002ca94721533108)},
+ }}, {{
+ {FIELD_LITERAL(0x0051e4b3f764d8a9,0x0019792d46e904a0,0x00853bc13dbc8227,0x000840208179f12d,0x0068243474879235,0x0013856fbfe374d0,0x00bda12fe8676424,0x00bbb43635926eb2)},
+ {FIELD_LITERAL(0x0012cdc880a93982,0x003c495b21cd1b58,0x00b7e5c93f22a26e,0x0044aa82dfb99458,0x009ba092cdffe9c0,0x00a14b3ab2083b73,0x000271c2f70e1c4b,0x00eea9cac0f66eb8)},
+ {FIELD_LITERAL(0x001a1847c4ac5480,0x00b1b412935bb03a,0x00f74285983bf2b2,0x00624138b5b5d0f1,0x008820c0b03d38bf,0x00b94e50a18c1572,0x0060f6934841798f,0x00c52f5d66d6ebe2)},
+ }}, {{
+ {FIELD_LITERAL(0x00da23d59f9bcea6,0x00e0f27007a06a4b,0x00128b5b43a6758c,0x000cf50190fa8b56,0x00fc877aba2b2d72,0x00623bef52edf53f,0x00e6af6b819669e2,0x00e314dc34fcaa4f)},
+ {FIELD_LITERAL(0x0066e5eddd164d1e,0x00418a7c6fe28238,0x0002e2f37e962c25,0x00f01f56b5975306,0x0048842fa503875c,0x0057b0e968078143,0x00ff683024f3d134,0x0082ae28fcad12e4)},
+ {FIELD_LITERAL(0x0011ddfd21260e42,0x00d05b0319a76892,0x00183ea4368e9b8f,0x00b0815662affc96,0x00b466a5e7ce7c88,0x00db93b07506e6ee,0x0033885f82f62401,0x0086f9090ec9b419)},
+ }}, {{
+ {FIELD_LITERAL(0x00d95d1c5fcb435a,0x0016d1ed6b5086f9,0x00792aa0b7e54d71,0x0067b65715f1925d,0x00a219755ec6176b,0x00bc3f026b12c28f,0x00700c897ffeb93e,0x0089b83f6ec50b46)},
+ {FIELD_LITERAL(0x003c97e6384da36e,0x00423d53eac81a09,0x00b70d68f3cdce35,0x00ee7959b354b92c,0x00f4e9718819c8ca,0x009349f12acbffe9,0x005aee7b62cb7da6,0x00d97764154ffc86)},
+ {FIELD_LITERAL(0x00526324babb46dc,0x002ee99b38d7bf9e,0x007ea51794706ef4,0x00abeb04da6e3c39,0x006b457c1d281060,0x00fe243e9a66c793,0x00378de0fb6c6ee4,0x003e4194b9c3cb93)},
+ }}, {{
+ {FIELD_LITERAL(0x00fed3cd80ca2292,0x0015b043a73ca613,0x000a9fd7bf9be227,0x003b5e03de2db983,0x005af72d46904ef7,0x00c0f1b5c49faa99,0x00dc86fc3bd305e1,0x00c92f08c1cb1797)},
+ {FIELD_LITERAL(0x0079680ce111ed3b,0x001a1ed82806122c,0x000c2e7466d15df3,0x002c407f6f7150fd,0x00c5e7c96b1b0ce3,0x009aa44626863ff9,0x00887b8b5b80be42,0x00b6023cec964825)},
+ {FIELD_LITERAL(0x00e4a8e1048970c8,0x0062887b7830a302,0x00bcf1c8cd81402b,0x0056dbb81a68f5be,0x0014eced83f12452,0x00139e1a510150df,0x00bb81140a82d1a3,0x000febcc1aaf1aa7)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7527958238159,0x0013ec9537a84cd6,0x001d7fee7d562525,0x00b9eefa6191d5e5,0x00dbc97db70bcb8a,0x00481affc7a4d395,0x006f73d3e70c31bb,0x00183f324ed96a61)},
+ {FIELD_LITERAL(0x0039dd7ce7fc6860,0x00d64f6425653da1,0x003e037c7f57d0af,0x0063477a06e2bcf2,0x001727dbb7ac67e6,0x0049589f5efafe2e,0x00fc0fef2e813d54,0x008baa5d087fb50d)},
+ {FIELD_LITERAL(0x0024fb59d9b457c7,0x00a7d4e060223e4c,0x00c118d1b555fd80,0x0082e216c732f22a,0x00cd2a2993089504,0x003638e836a3e13d,0x000d855ee89b4729,0x008ec5b7d4810c91)},
+ }}, {{
+ {FIELD_LITERAL(0x001bf51f7d65cdfd,0x00d14cdafa16a97d,0x002c38e60fcd10e7,0x00a27446e393efbd,0x000b5d8946a71fdd,0x0063df2cde128f2f,0x006c8679569b1888,0x0059ffc4925d732d)},
+ {FIELD_LITERAL(0x00ece96f95f2b66f,0x00ece7952813a27b,0x0026fc36592e489e,0x007157d1a2de0f66,0x00759dc111d86ddf,0x0012881e5780bb0f,0x00c8ccc83ad29496,0x0012b9bd1929eb71)},
+ {FIELD_LITERAL(0x000fa15a20da5df0,0x00349ddb1a46cd31,0x002c512ad1d8e726,0x00047611f669318d,0x009e68fba591e17e,0x004320dffa803906,0x00a640874951a3d3,0x00b6353478baa24f)},
+ }}, {{
+ {FIELD_LITERAL(0x009696510000d333,0x00ec2f788bc04826,0x000e4d02b1f67ba5,0x00659aa8dace08b6,0x00d7a38a3a3ae533,0x008856defa8c746b,0x004d7a4402d3da1a,0x00ea82e06229260f)},
+ {FIELD_LITERAL(0x006a15bb20f75c0c,0x0079a144027a5d0c,0x00d19116ce0b4d70,0x0059b83bcb0b268e,0x005f58f63f16c127,0x0079958318ee2c37,0x00defbb063d07f82,0x00f1f0b931d2d446)},
+ {FIELD_LITERAL(0x00cb5e4c3c35d422,0x008df885ca43577f,0x00fa50b16ca3e471,0x005a0e58e17488c8,0x00b2ceccd6d34d19,0x00f01d5d235e36e9,0x00db2e7e4be6ca44,0x00260ab77f35fccd)},
+ }}, {{
+ {FIELD_LITERAL(0x006f6fd9baac61d5,0x002a7710a020a895,0x009de0db7fc03d4d,0x00cdedcb1875f40b,0x00050caf9b6b1e22,0x005e3a6654456ab0,0x00775fdf8c4423d4,0x0028701ea5738b5d)},
+ {FIELD_LITERAL(0x009ffd90abfeae96,0x00cba3c2b624a516,0x005ef08bcee46c91,0x00e6fde30afb6185,0x00f0b4db4f818ce4,0x006c54f45d2127f5,0x00040125035854c7,0x00372658a3287e13)},
+ {FIELD_LITERAL(0x00d7070fb1beb2ab,0x0078fc845a93896b,0x006894a4b2f224a6,0x005bdd8192b9dbde,0x00b38839874b3a9e,0x00f93618b04b7a57,0x003e3ec75fd2c67e,0x00bf5e6bfc29494a)},
+ }}, {{
+ {FIELD_LITERAL(0x00f19224ebba2aa5,0x0074f89d358e694d,0x00eea486597135ad,0x0081579a4555c7e1,0x0010b9b872930a9d,0x00f002e87a30ecc0,0x009b9d66b6de56e2,0x00a3c4f45e8004eb)},
+ {FIELD_LITERAL(0x0045e8dda9400888,0x002ff12e5fc05db7,0x00a7098d54afe69c,0x00cdbe846a500585,0x00879c1593ca1882,0x003f7a7fea76c8b0,0x002cd73dd0c8e0a1,0x00645d6ce96f51fe)},
+ {FIELD_LITERAL(0x002b7e83e123d6d6,0x00398346f7419c80,0x0042922e55940163,0x005e7fc5601886a3,0x00e88f2cee1d3103,0x00e7fab135f2e377,0x00b059984dbf0ded,0x0009ce080faa5bb8)},
+ }}, {{
+ {FIELD_LITERAL(0x0085e78af7758979,0x00275a4ee1631a3a,0x00d26bc0ed78b683,0x004f8355ea21064f,0x00d618e1a32696e5,0x008d8d7b150e5680,0x00a74cd854b278d2,0x001dd62702203ea0)},
+ {FIELD_LITERAL(0x00f89335c2a59286,0x00a0f5c905d55141,0x00b41fb836ee9382,0x00e235d51730ca43,0x00a5cb37b5c0a69a,0x009b966ffe136c45,0x00cb2ea10bf80ed1,0x00fb2b370b40dc35)},
+ {FIELD_LITERAL(0x00d687d16d4ee8ba,0x0071520bdd069dff,0x00de85c60d32355d,0x0087d2e3565102f4,0x00cde391b8dfc9aa,0x00e18d69efdfefe5,0x004a9d0591954e91,0x00fa36dd8b50eee5)},
+ }}, {{
+ {FIELD_LITERAL(0x002e788749a865f7,0x006e4dc3116861ea,0x009f1428c37276e6,0x00e7d2e0fc1e1226,0x003aeebc6b6c45f6,0x0071a8073bf500c9,0x004b22ad986b530c,0x00f439e63c0d79d4)},
+ {FIELD_LITERAL(0x006bc3d53011f470,0x00032d6e692b83e8,0x00059722f497cd0b,0x0009b4e6f0c497cc,0x0058a804b7cce6c0,0x002b71d3302bbd5d,0x00e2f82a36765fce,0x008dded99524c703)},
+ {FIELD_LITERAL(0x004d058953747d64,0x00701940fe79aa6f,0x00a620ac71c760bf,0x009532b611158b75,0x00547ed7f466f300,0x003cb5ab53a8401a,0x00c7763168ce3120,0x007e48e33e4b9ab2)},
+ }}, {{
+ {FIELD_LITERAL(0x001b2fc57bf3c738,0x006a3f918993fb80,0x0026f7a14fdec288,0x0075a2cdccef08db,0x00d3ecbc9eecdbf1,0x0048c40f06e5bf7f,0x00d63e423009896b,0x000598bc99c056a8)},
+ {FIELD_LITERAL(0x002f194eaafa46dc,0x008e38f57fe87613,0x00dc8e5ae25f4ab2,0x000a17809575e6bd,0x00d3ec7923ba366a,0x003a7e72e0ad75e3,0x0010024b88436e0a,0x00ed3c5444b64051)},
+ {FIELD_LITERAL(0x00831fc1340af342,0x00c9645669466d35,0x007692b4cc5a080f,0x009fd4a47ac9259f,0x001eeddf7d45928b,0x003c0446fc45f28b,0x002c0713aa3e2507,0x0095706935f0f41e)},
+ }}, {{
+ {FIELD_LITERAL(0x00766ae4190ec6d8,0x0065768cabc71380,0x00b902598416cdc2,0x00380021ad38df52,0x008f0b89d6551134,0x004254d4cc62c5a5,0x000d79f4484b9b94,0x00b516732ae3c50e)},
+ {FIELD_LITERAL(0x001fb73475c45509,0x00d2b2e5ea43345a,0x00cb3c3842077bd1,0x0029f90ad820946e,0x007c11b2380778aa,0x009e54ece62c1704,0x004bc60c41ca01c3,0x004525679a5a0b03)},
+ {FIELD_LITERAL(0x00c64fbddbed87b3,0x0040601d11731faa,0x009c22475b6f9d67,0x0024b79dae875f15,0x00616fed3f02c3b0,0x0000cf39f6af2d3b,0x00c46bac0aa9a688,0x00ab23e2800da204)},
+ }}, {{
+ {FIELD_LITERAL(0x000b3a37617632b0,0x00597199fe1cfb6c,0x0042a7ccdfeafdd6,0x004cc9f15ebcea17,0x00f436e596a6b4a4,0x00168861142df0d8,0x000753edfec26af5,0x000c495d7e388116)},
+ {FIELD_LITERAL(0x0017085f4a346148,0x00c7cf7a37f62272,0x001776e129bc5c30,0x009955134c9eef2a,0x001ba5bdf1df07be,0x00ec39497103a55c,0x006578354fda6cfb,0x005f02719d4f15ee)},
+ {FIELD_LITERAL(0x0052b9d9b5d9655d,0x00d4ec7ba1b461c3,0x00f95df4974f280b,0x003d8e5ca11aeb51,0x00d4981eb5a70b26,0x000af9a4f6659f29,0x004598c846faeb43,0x0049d9a183a47670)},
+ }}, {{
+ {FIELD_LITERAL(0x000a72d23dcb3f1f,0x00a3737f84011727,0x00f870c0fbbf4a47,0x00a7aadd04b5c9ca,0x000c7715c67bd072,0x00015a136afcd74e,0x0080d5caea499634,0x0026b448ec7514b7)},
+ {FIELD_LITERAL(0x00b60167d9e7d065,0x00e60ba0d07381e8,0x003a4f17b725c2d4,0x006c19fe176b64fa,0x003b57b31af86ccb,0x0021047c286180fd,0x00bdc8fb00c6dbb6,0x00fe4a9f4bab4f3f)},
+ {FIELD_LITERAL(0x0088ffc3a16111f7,0x009155e4245d0bc8,0x00851d68220572d5,0x00557ace1e514d29,0x0031d7c339d91022,0x00101d0ae2eaceea,0x00246ab3f837b66a,0x00d5216d381ff530)},
+ }}, {{
+ {FIELD_LITERAL(0x0057e7ea35f36dae,0x00f47d7ad15de22e,0x00d757ea4b105115,0x008311457d579d7e,0x00b49b75b1edd4eb,0x0081c7ff742fd63a,0x00ddda3187433df6,0x00475727d55f9c66)},
+ {FIELD_LITERAL(0x00a6295218dc136a,0x00563b3af0e9c012,0x00d3753b0145db1b,0x004550389c043dc1,0x00ea94ae27401bdf,0x002b0b949f2b7956,0x00c63f780ad8e23c,0x00e591c47d6bab15)},
+ {FIELD_LITERAL(0x00416c582b058eb6,0x004107da5b2cc695,0x00b3cd2556aeec64,0x00c0b418267e57a1,0x001799293579bd2e,0x0046ed44590e4d07,0x001d7459b3630a1e,0x00c6afba8b6696aa)},
+ }}, {{
+ {FIELD_LITERAL(0x008d6009b26da3f8,0x00898e88ca06b1ca,0x00edb22b2ed7fe62,0x00fbc93516aabe80,0x008b4b470c42ce0d,0x00e0032ba7d0dcbb,0x00d76da3a956ecc8,0x007f20fe74e3852a)},
+ {FIELD_LITERAL(0x002419222c607674,0x00a7f23af89188b3,0x00ad127284e73d1c,0x008bba582fae1c51,0x00fc6aa7ca9ecab1,0x003df5319eb6c2ba,0x002a05af8a8b199a,0x004bf8354558407c)},
+ {FIELD_LITERAL(0x00ce7d4a30f0fcbf,0x00d02c272629f03d,0x0048c001f7400bc2,0x002c21368011958d,0x0098a550391e96b5,0x002d80b66390f379,0x001fa878760cc785,0x001adfce54b613d5)},
+ }}, {{
+ {FIELD_LITERAL(0x001ed4dc71fa2523,0x005d0bff19bf9b5c,0x00c3801cee065a64,0x001ed0b504323fbf,0x0003ab9fdcbbc593,0x00df82070178b8d2,0x00a2bcaa9c251f85,0x00c628a3674bd02e)},
+ {FIELD_LITERAL(0x006b7a0674f9f8de,0x00a742414e5c7cff,0x0041cbf3c6e13221,0x00e3a64fd207af24,0x0087c05f15fbe8d1,0x004c50936d9e8a33,0x001306ec21042b6d,0x00a4f4137d1141c2)},
+ {FIELD_LITERAL(0x0009e6fb921568b0,0x00b3c60120219118,0x002a6c3460dd503a,0x009db1ef11654b54,0x0063e4bf0be79601,0x00670d34bb2592b9,0x00dcee2f6c4130ce,0x00b2682e88e77f54)},
+ }}, {{
+ {FIELD_LITERAL(0x000d5b4b3da135ab,0x00838f3e5064d81d,0x00d44eb50f6d94ed,0x0008931ab502ac6d,0x00debe01ca3d3586,0x0025c206775f0641,0x005ad4b6ae912763,0x007e2c318ad8f247)},
+ {FIELD_LITERAL(0x00ddbe0750dd1add,0x004b3c7b885844b8,0x00363e7ecf12f1ae,0x0062e953e6438f9d,0x0023cc73b076afe9,0x00b09fa083b4da32,0x00c7c3d2456c541d,0x005b591ec6b694d4)},
+ {FIELD_LITERAL(0x0028656e19d62fcf,0x0052a4af03df148d,0x00122765ddd14e42,0x00f2252904f67157,0x004741965b636f3a,0x006441d296132cb9,0x005e2106f956a5b7,0x00247029592d335c)},
+ }}, {{
+ {FIELD_LITERAL(0x003fe038eb92f894,0x000e6da1b72e8e32,0x003a1411bfcbe0fa,0x00b55d473164a9e4,0x00b9a775ac2df48d,0x0002ddf350659e21,0x00a279a69eb19cb3,0x00f844eab25cba44)},
+ {FIELD_LITERAL(0x00c41d1f9c1f1ac1,0x007b2df4e9f19146,0x00b469355fd5ba7a,0x00b5e1965afc852a,0x00388d5f1e2d8217,0x0022079e4c09ae93,0x0014268acd4ef518,0x00c1dd8d9640464c)},
+ {FIELD_LITERAL(0x0038526adeed0c55,0x00dd68c607e3fe85,0x00f746ddd48a5d57,0x0042f2952b963b7c,0x001cbbd6876d5ec2,0x005e341470bca5c2,0x00871d41e085f413,0x00e53ab098f45732)},
+ }}, {{
+ {FIELD_LITERAL(0x004d51124797c831,0x008f5ae3750347ad,0x0070ced94c1a0c8e,0x00f6db2043898e64,0x000d00c9a5750cd0,0x000741ec59bad712,0x003c9d11aab37b7f,0x00a67ba169807714)},
+ {FIELD_LITERAL(0x00adb2c1566e8b8f,0x0096c68a35771a9a,0x00869933356f334a,0x00ba9c93459f5962,0x009ec73fb6e8ca4b,0x003c3802c27202e1,0x0031f5b733e0c008,0x00f9058c19611fa9)},
+ {FIELD_LITERAL(0x00238f01814a3421,0x00c325a44b6cce28,0x002136f97aeb0e73,0x000cac8268a4afe2,0x0022fd218da471b3,0x009dcd8dfff8def9,0x00cb9f8181d999bb,0x00143ae56edea349)},
+ }}, {{
+ {FIELD_LITERAL(0x0000623bf87622c5,0x00a1966fdd069496,0x00c315b7b812f9fc,0x00bdf5efcd128b97,0x001d464f532e3e16,0x003cd94f081bfd7e,0x00ed9dae12ce4009,0x002756f5736eee70)},
+ {FIELD_LITERAL(0x00a5187e6ee7341b,0x00e6d52e82d83b6e,0x00df3c41323094a7,0x00b3324f444e9de9,0x00689eb21a35bfe5,0x00f16363becd548d,0x00e187cc98e7f60f,0x00127d9062f0ccab)},
+ {FIELD_LITERAL(0x004ad71b31c29e40,0x00a5fcace12fae29,0x004425b5597280ed,0x00e7ef5d716c3346,0x0010b53ada410ac8,0x0092310226060c9b,0x0091c26128729c7e,0x0088b42900f8ec3b)},
+ }}, {{
+ {FIELD_LITERAL(0x00f1e26e9762d4a8,0x00d9d74082183414,0x00ffec9bd57a0282,0x000919e128fd497a,0x00ab7ae7d00fe5f8,0x0054dc442851ff68,0x00c9ebeb3b861687,0x00507f7cab8b698f)},
+ {FIELD_LITERAL(0x00c13c5aae3ae341,0x009c6c9ed98373e7,0x00098f26864577a8,0x0015b886e9488b45,0x0037692c42aadba5,0x00b83170b8e7791c,0x001670952ece1b44,0x00fd932a39276da2)},
+ {FIELD_LITERAL(0x0081a3259bef3398,0x005480fff416107b,0x00ce4f607d21be98,0x003ffc084b41df9b,0x0043d0bb100502d1,0x00ec35f575ba3261,0x00ca18f677300ef3,0x00e8bb0a827d8548)},
+ }}, {{
+ {FIELD_LITERAL(0x00df76b3328ada72,0x002e20621604a7c2,0x00f910638a105b09,0x00ef4724d96ef2cd,0x00377d83d6b8a2f7,0x00b4f48805ade324,0x001cd5da8b152018,0x0045af671a20ca7f)},
+ {FIELD_LITERAL(0x009ae3b93a56c404,0x004a410b7a456699,0x00023a619355e6b2,0x009cdc7297387257,0x0055b94d4ae70d04,0x002cbd607f65b005,0x003208b489697166,0x00ea2aa058867370)},
+ {FIELD_LITERAL(0x00f29d2598ee3f32,0x00b4ac5385d82adc,0x007633eaf04df19b,0x00aa2d3d77ceab01,0x004a2302fcbb778a,0x00927f225d5afa34,0x004a8e9d5047f237,0x008224ae9dbce530)},
+ }}, {{
+ {FIELD_LITERAL(0x001cf640859b02f8,0x00758d1d5d5ce427,0x00763c784ef4604c,0x005fa81aee205270,0x00ac537bfdfc44cb,0x004b919bd342d670,0x00238508d9bf4b7a,0x00154888795644f3)},
+ {FIELD_LITERAL(0x00c845923c084294,0x00072419a201bc25,0x0045f408b5f8e669,0x00e9d6a186b74dfe,0x00e19108c68fa075,0x0017b91d874177b7,0x002f0ca2c7912c5a,0x009400aa385a90a2)},
+ {FIELD_LITERAL(0x0071110b01482184,0x00cfed0044f2bef8,0x0034f2901cf4662e,0x003b4ae2a67f9834,0x00cca9b96fe94810,0x00522507ae77abd0,0x00bac7422721e73e,0x0066622b0f3a62b0)},
+ }}, {{
+ {FIELD_LITERAL(0x00f8ac5cf4705b6a,0x00867d82dcb457e3,0x007e13ab2ccc2ce9,0x009ee9a018d3930e,0x008370f8ecb42df8,0x002d9f019add263e,0x003302385b92d196,0x00a15654536e2c0c)},
+ {FIELD_LITERAL(0x0026ef1614e160af,0x00c023f9edfc9c76,0x00cff090da5f57ba,0x0076db7a66643ae9,0x0019462f8c646999,0x008fec00b3854b22,0x00d55041692a0a1c,0x0065db894215ca00)},
+ {FIELD_LITERAL(0x00a925036e0a451c,0x002a0390c36b6cc1,0x00f27020d90894f4,0x008d90d52cbd3d7f,0x00e1d0137392f3b8,0x00f017c158b51a8f,0x00cac313d3ed7dbc,0x00b99a81e3eb42d3)},
+ }}, {{
+ {FIELD_LITERAL(0x00b54850275fe626,0x0053a3fd1ec71140,0x00e3d2d7dbe096fa,0x00e4ac7b595cce4c,0x0077bad449c0a494,0x00b7c98814afd5b3,0x0057226f58486cf9,0x00b1557154f0cc57)},
+ {FIELD_LITERAL(0x008cc9cd236315c0,0x0031d9c5b39fda54,0x00a5713ef37e1171,0x00293d5ae2886325,0x00c4aba3e05015e1,0x0003f35ef78e4fc6,0x0039d6bd3ac1527b,0x0019d7c3afb77106)},
+ {FIELD_LITERAL(0x007b162931a985af,0x00ad40a2e0daa713,0x006df27c4009f118,0x00503e9f4e2e8bec,0x00751a77c82c182d,0x000298937769245b,0x00ffb1e8fabf9ee5,0x0008334706e09abe)},
+ }}, {{
+ {FIELD_LITERAL(0x00dbca4e98a7dcd9,0x00ee29cfc78bde99,0x00e4a3b6995f52e9,0x0045d70189ae8096,0x00fd2a8a3b9b0d1b,0x00af1793b107d8e1,0x00dbf92cbe4afa20,0x00da60f798e3681d)},
+ {FIELD_LITERAL(0x004246bfcecc627a,0x004ba431246c03a4,0x00bd1d101872d497,0x003b73d3f185ee16,0x001feb2e2678c0e3,0x00ff13c5a89dec76,0x00ed06042e771d8f,0x00a4fd2a897a83dd)},
+ {FIELD_LITERAL(0x009a4a3be50d6597,0x00de3165fc5a1096,0x004f3f56e345b0c7,0x00f7bf721d5ab8bc,0x004313e47b098c50,0x00e4c7d5c0e1adbb,0x002e3e3db365051e,0x00a480c2cd6a96fb)},
+ }}, {{
+ {FIELD_LITERAL(0x00417fa30a7119ed,0x00af257758419751,0x00d358a487b463d4,0x0089703cc720b00d,0x00ce56314ff7f271,0x0064db171ade62c1,0x00640b36d4a22fed,0x00424eb88696d23f)},
+ {FIELD_LITERAL(0x004ede34af2813f3,0x00d4a8e11c9e8216,0x004796d5041de8a5,0x00c4c6b4d21cc987,0x00e8a433ee07fa1e,0x0055720b5abcc5a1,0x008873ea9c74b080,0x005b3fec1ab65d48)},
+ {FIELD_LITERAL(0x0047e5277db70ec5,0x000a096c66db7d6b,0x00b4164cc1730159,0x004a9f783fe720fe,0x00a8177b94449dbc,0x0095a24ff49a599f,0x0069c1c578250cbc,0x00452019213debf4)},
+ }}, {{
+ {FIELD_LITERAL(0x0021ce99e09ebda3,0x00fcbd9f91875ad0,0x009bbf6b7b7a0b5f,0x00388886a69b1940,0x00926a56d0f81f12,0x00e12903c3358d46,0x005dfce4e8e1ce9d,0x0044cfa94e2f7e23)},
+ {FIELD_LITERAL(0x001bd59c09e982ea,0x00f72daeb937b289,0x0018b76dca908e0e,0x00edb498512384ad,0x00ce0243b6cc9538,0x00f96ff690cb4e70,0x007c77bf9f673c8d,0x005bf704c088a528)},
+ {FIELD_LITERAL(0x0093d4628dcb33be,0x0095263d51d42582,0x0049b3222458fe06,0x00e7fce73b653a7f,0x003ca2ebce60b369,0x00c5de239a32bea4,0x0063b8b3d71fb6bf,0x0039aeeb78a1a839)},
+ }}, {{
+ {FIELD_LITERAL(0x007dc52da400336c,0x001fded1e15b9457,0x00902e00f5568e3a,0x00219bef40456d2d,0x005684161fb3dbc9,0x004a4e9be49a76ea,0x006e685ae88b78ff,0x0021c42f13042d3c)},
+ {FIELD_LITERAL(0x00fb22bb5fd3ce50,0x0017b48aada7ae54,0x00fd5c44ad19a536,0x000ccc4e4e55e45c,0x00fd637d45b4c3f5,0x0038914e023c37cf,0x00ac1881d6a8d898,0x00611ed8d3d943a8)},
+ {FIELD_LITERAL(0x0056e2259d113d2b,0x00594819b284ec16,0x00c7bf794bb36696,0x00721ee75097cdc6,0x00f71be9047a2892,0x00df6ba142564edf,0x0069580b7a184e8d,0x00f056e38fca0fee)},
+ }}, {{
+ {FIELD_LITERAL(0x009df98566a18c6d,0x00cf3a200968f219,0x0044ba60da6d9086,0x00dbc9c0e344da03,0x000f9401c4466855,0x00d46a57c5b0a8d1,0x00875a635d7ac7c6,0x00ef4a933b7e0ae6)},
+ {FIELD_LITERAL(0x005e8694077a1535,0x008bef75f71c8f1d,0x000a7c1316423511,0x00906e1d70604320,0x003fc46c1a2ffbd6,0x00d1d5022e68f360,0x002515fba37bbf46,0x00ca16234e023b44)},
+ {FIELD_LITERAL(0x00787c99561f4690,0x00a857a8c1561f27,0x00a10df9223c09fe,0x00b98a9562e3b154,0x004330b8744c3ed2,0x00e06812807ec5c4,0x00e4cf6a7db9f1e3,0x00d95b089f132a34)},
+ }}, {{
+ {FIELD_LITERAL(0x002922b39ca33eec,0x0090d12a5f3ab194,0x00ab60c02fb5f8ed,0x00188d292abba1cf,0x00e10edec9698f6e,0x0069a4d9934133c8,0x0024aac40e6d3d06,0x001702c2177661b0)},
+ {FIELD_LITERAL(0x00139078397030bd,0x000e3c447e859a00,0x0064a5b334c82393,0x00b8aabeb7358093,0x00020778bb9ae73b,0x0032ee94c7892a18,0x008215253cb41bda,0x005e2797593517ae)},
+ {FIELD_LITERAL(0x0083765a5f855d4a,0x0051b6d1351b8ee2,0x00116de548b0f7bb,0x0087bd88703affa0,0x0095b2cc34d7fdd2,0x0084cd81b53f0bc8,0x008562fc995350ed,0x00a39abb193651e3)},
+ }}, {{
+ {FIELD_LITERAL(0x0019e23f0474b114,0x00eb94c2ad3b437e,0x006ddb34683b75ac,0x00391f9209b564c6,0x00083b3bb3bff7aa,0x00eedcd0f6dceefc,0x00b50817f794fe01,0x0036474deaaa75c9)},
+ {FIELD_LITERAL(0x0091868594265aa2,0x00797accae98ca6d,0x0008d8c5f0f8a184,0x00d1f4f1c2b2fe6e,0x0036783dfb48a006,0x008c165120503527,0x0025fd780058ce9b,0x0068beb007be7d27)},
+ {FIELD_LITERAL(0x00d0ff88aa7c90c2,0x00b2c60dacf53394,0x0094a7284d9666d6,0x00bed9022ce7a19d,0x00c51553f0cd7682,0x00c3fb870b124992,0x008d0bc539956c9b,0x00fc8cf258bb8885)},
+ }}, {{
+ {FIELD_LITERAL(0x003667bf998406f8,0x0000115c43a12975,0x001e662f3b20e8fd,0x0019ffa534cb24eb,0x00016be0dc8efb45,0x00ff76a8b26243f5,0x00ae20d241a541e3,0x0069bd6af13cd430)},
+ {FIELD_LITERAL(0x0045fdc16487cda3,0x00b2d8e844cf2ed7,0x00612c50e88c1607,0x00a08aabc66c1672,0x006031fdcbb24d97,0x001b639525744b93,0x004409d62639ab17,0x00a1853d0347ab1d)},
+ {FIELD_LITERAL(0x0075a1a56ebf5c21,0x00a3e72be9ac53ed,0x00efcde1629170c2,0x0004225fe91ef535,0x0088049fc73dfda7,0x004abc74857e1288,0x0024e2434657317c,0x00d98cb3d3e5543c)},
+ }}, {{
+ {FIELD_LITERAL(0x00b4b53eab6bdb19,0x009b22d8b43711d0,0x00d948b9d961785d,0x00cb167b6f279ead,0x00191de3a678e1c9,0x00d9dd9511095c2e,0x00f284324cd43067,0x00ed74fa535151dd)},
+ {FIELD_LITERAL(0x007e32c049b5c477,0x009d2bfdbd9bcfd8,0x00636e93045938c6,0x007fde4af7687298,0x0046a5184fafa5d3,0x0079b1e7f13a359b,0x00875adf1fb927d6,0x00333e21c61bcad2)},
+ {FIELD_LITERAL(0x00048014f73d8b8d,0x0075684aa0966388,0x0092be7df06dc47c,0x0097cebcd0f5568a,0x005a7004d9c4c6a9,0x00b0ecbb659924c7,0x00d90332dd492a7c,0x0057fc14df11493d)},
+ }}, {{
+ {FIELD_LITERAL(0x0008ed8ea0ad95be,0x0041d324b9709645,0x00e25412257a19b4,0x0058df9f3423d8d2,0x00a9ab20def71304,0x009ae0dbf8ac4a81,0x00c9565977e4392a,0x003c9269444baf55)},
+ {FIELD_LITERAL(0x007df6cbb926830b,0x00d336058ae37865,0x007af47dac696423,0x0048d3011ec64ac8,0x006b87666e40049f,0x0036a2e0e51303d7,0x00ba319bd79dbc55,0x003e2737ecc94f53)},
+ {FIELD_LITERAL(0x00d296ff726272d9,0x00f6d097928fcf57,0x00e0e616a55d7013,0x00deaf454ed9eac7,0x0073a56bedef4d92,0x006ccfdf6fc92e19,0x009d1ee1371a7218,0x00ee3c2ee4462d80)},
+ }}, {{
+ {FIELD_LITERAL(0x00437bce9bccdf9d,0x00e0c8e2f85dc0a3,0x00c91a7073995a19,0x00856ec9fe294559,0x009e4b33394b156e,0x00e245b0dc497e5c,0x006a54e687eeaeff,0x00f1cd1cd00fdb7c)},
+ {FIELD_LITERAL(0x008132ae5c5d8cd1,0x00121d68324a1d9f,0x00d6be9dafcb8c76,0x00684d9070edf745,0x00519fbc96d7448e,0x00388182fdc1f27e,0x000235baed41f158,0x00bf6cf6f1a1796a)},
+ {FIELD_LITERAL(0x002adc4b4d148219,0x003084ada0d3a90a,0x0046de8aab0f2e4e,0x00452d342a67b5fd,0x00d4b50f01d4de21,0x00db6d9fc0cefb79,0x008c184c86a462cd,0x00e17c83764d42da)},
+ }}, {{
+ {FIELD_LITERAL(0x007b2743b9a1e01a,0x007847ffd42688c4,0x006c7844d610a316,0x00f0cb8b250aa4b0,0x00a19060143b3ae6,0x0014eb10b77cfd80,0x000170905729dd06,0x00063b5b9cd72477)},
+ {FIELD_LITERAL(0x00ce382dc7993d92,0x00021153e938b4c8,0x00096f7567f48f51,0x0058f81ddfe4b0d5,0x00cc379a56b355c7,0x002c760770d3e819,0x00ee22d1d26e5a40,0x00de6d93d5b082d7)},
+ {FIELD_LITERAL(0x000a91a42c52e056,0x00185f6b77fce7ea,0x000803c51962f6b5,0x0022528582ba563d,0x0043f8040e9856d6,0x0085a29ec81fb860,0x005f9a611549f5ff,0x00c1f974ecbd4b06)},
+ }}, {{
+ {FIELD_LITERAL(0x005b64c6fd65ec97,0x00c1fdd7f877bc7f,0x000d9cc6c89f841c,0x005c97b7f1aff9ad,0x0075e3c61475d47e,0x001ecb1ba8153011,0x00fe7f1c8d71d40d,0x003fa9757a229832)},
+ {FIELD_LITERAL(0x00ffc5c89d2b0cba,0x00d363d42e3e6fc3,0x0019a1a0118e2e8a,0x00f7baeff48882e1,0x001bd5af28c6b514,0x0055476ca2253cb2,0x00d8eb1977e2ddf3,0x00b173b1adb228a1)},
+ {FIELD_LITERAL(0x00f2cb99dd0ad707,0x00e1e08b6859ddd8,0x000008f2d0650bcc,0x00d7ed392f8615c3,0x00976750a94da27f,0x003e83bb0ecb69ba,0x00df8e8d15c14ac6,0x00f9f7174295d9c2)},
+ }}, {{
+ {FIELD_LITERAL(0x00f11cc8e0e70bcb,0x00e5dc689974e7dd,0x0014e409f9ee5870,0x00826e6689acbd63,0x008a6f4e3d895d88,0x00b26a8da41fd4ad,0x000fb7723f83efd7,0x009c749db0a5f6c3)},
+ {FIELD_LITERAL(0x002389319450f9ba,0x003677f31aa1250a,0x0092c3db642f38cb,0x00f8b64c0dfc9773,0x00cd49fe3505b795,0x0068105a4090a510,0x00df0ba2072a8bb6,0x00eb396143afd8be)},
+ {FIELD_LITERAL(0x00a0d4ecfb24cdff,0x00ddaf8008ba6479,0x00f0b3e36d4b0f44,0x003734bd3af1f146,0x00b87e2efc75527e,0x00d230df55ddab50,0x002613257ae56c1d,0x00bc0946d135934d)},
+ }}, {{
+ {FIELD_LITERAL(0x00468711bd994651,0x0033108fa67561bf,0x0089d760192a54b4,0x00adc433de9f1871,0x000467d05f36e050,0x007847e0f0579f7f,0x00a2314ad320052d,0x00b3a93649f0b243)},
+ {FIELD_LITERAL(0x0067f8f0c4fe26c9,0x0079c4a3cc8f67b9,0x0082b1e62f23550d,0x00f2d409caefd7f5,0x0080e67dcdb26e81,0x0087ae993ea1f98a,0x00aa108becf61d03,0x001acf11efb608a3)},
+ {FIELD_LITERAL(0x008225febbab50d9,0x00f3b605e4dd2083,0x00a32b28189e23d2,0x00d507e5e5eb4c97,0x005a1a84e302821f,0x0006f54c1c5f08c7,0x00a347c8cb2843f0,0x0009f73e9544bfa5)},
+ }}, {{
+ {FIELD_LITERAL(0x006c59c9ae744185,0x009fc32f1b4282cd,0x004d6348ca59b1ac,0x00105376881be067,0x00af4096013147dc,0x004abfb5a5cb3124,0x000d2a7f8626c354,0x009c6ed568e07431)},
+ {FIELD_LITERAL(0x00e828333c297f8b,0x009ef3cf8c3f7e1f,0x00ab45f8fff31cb9,0x00c8b4178cb0b013,0x00d0c50dd3260a3f,0x0097126ac257f5bc,0x0042376cc90c705a,0x001d96fdb4a1071e)},
+ {FIELD_LITERAL(0x00542d44d89ee1a8,0x00306642e0442d98,0x0090853872b87338,0x002362cbf22dc044,0x002c222adff663b8,0x0067c924495fcb79,0x000e621d983c977c,0x00df77a9eccb66fb)},
+ }}, {{
+ {FIELD_LITERAL(0x002809e4bbf1814a,0x00b9e854f9fafb32,0x00d35e67c10f7a67,0x008f1bcb76e748cf,0x004224d9515687d2,0x005ba0b774e620c4,0x00b5e57db5d54119,0x00e15babe5683282)},
+ {FIELD_LITERAL(0x00832d02369b482c,0x00cba52ff0d93450,0x003fa9c908d554db,0x008d1e357b54122f,0x00abd91c2dc950c6,0x007eff1df4c0ec69,0x003f6aeb13fb2d31,0x00002d6179fc5b2c)},
+ {FIELD_LITERAL(0x0046c9eda81c9c89,0x00b60cb71c8f62fc,0x0022f5a683baa558,0x00f87319fccdf997,0x009ca09b51ce6a22,0x005b12baf4af7d77,0x008a46524a1e33e2,0x00035a77e988be0d)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7efe46a7dbe2f,0x002f66fd55014fe7,0x006a428afa1ff026,0x0056caaa9604ab72,0x0033f3bcd7fac8ae,0x00ccb1aa01c86764,0x00158d1edf13bf40,0x009848ee76fcf3b4)},
+ {FIELD_LITERAL(0x00a9e7730a819691,0x00d9cc73c4992b70,0x00e299bde067de5a,0x008c314eb705192a,0x00e7226f17e8a3cc,0x0029dfd956e65a47,0x0053a8e839073b12,0x006f942b2ab1597e)},
+ {FIELD_LITERAL(0x001c3d780ecd5e39,0x0094f247fbdcc5fe,0x00d5c786fd527764,0x00b6f4da74f0db2a,0x0080f1f8badcd5fc,0x00f36a373ad2e23b,0x00f804f9f4343bf2,0x00d1af40ec623982)},
+ }}, {{
+ {FIELD_LITERAL(0x0082aeace5f1b144,0x00f68b3108cf4dd3,0x00634af01dde3020,0x000beab5df5c2355,0x00e8b790d1b49b0b,0x00e48d15854e36f4,0x0040ab2d95f3db9f,0x002711c4ed9e899a)},
+ {FIELD_LITERAL(0x0039343746531ebe,0x00c8509d835d429d,0x00e79eceff6b0018,0x004abfd31e8efce5,0x007bbfaaa1e20210,0x00e3be89c193e179,0x001c420f4c31d585,0x00f414a315bef5ae)},
+ {FIELD_LITERAL(0x007c296a24990df8,0x00d5d07525a75588,0x00dd8e113e94b7e7,0x007bbc58febe0cc8,0x0029f51af9bfcad3,0x007e9311ec7ab6f3,0x009a884de1676343,0x0050d5f2dce84be9)},
+ }}, {{
+ {FIELD_LITERAL(0x005fa020cca2450a,0x00491c29db6416d8,0x0037cefe3f9f9a85,0x003d405230647066,0x0049e835f0fdbe89,0x00feb78ac1a0815c,0x00828e4b32dc9724,0x00db84f2dc8d6fd4)},
+ {FIELD_LITERAL(0x0098cddc8b39549a,0x006da37e3b05d22c,0x00ce633cfd4eb3cb,0x00fda288ef526acd,0x0025338878c5d30a,0x00f34438c4e5a1b4,0x00584efea7c310f1,0x0041a551f1b660ad)},
+ {FIELD_LITERAL(0x00d7f7a8fbd6437a,0x0062872413bf3753,0x00ad4bbcb43c584b,0x007fe49be601d7e3,0x0077c659789babf4,0x00eb45fcb06a741b,0x005ce244913f9708,0x0088426401736326)},
+ }}, {{
+ {FIELD_LITERAL(0x007bf562ca768d7c,0x006c1f3a174e387c,0x00f024b447fee939,0x007e7af75f01143f,0x003adb70b4eed89d,0x00e43544021ad79a,0x0091f7f7042011f6,0x0093c1a1ee3a0ddc)},
+ {FIELD_LITERAL(0x00a0b68ec1eb72d2,0x002c03235c0d45a0,0x00553627323fe8c5,0x006186e94b17af94,0x00a9906196e29f14,0x0025b3aee6567733,0x007e0dd840080517,0x0018eb5801a4ba93)},
+ {FIELD_LITERAL(0x00d7fe7017bf6a40,0x006e3f0624be0c42,0x00ffbba205358245,0x00f9fc2cf8194239,0x008d93b37bf15b4e,0x006ddf2e38be8e95,0x002b6e79bf5fcff9,0x00ab355da425e2de)},
+ }}, {{
+ {FIELD_LITERAL(0x00938f97e20be973,0x0099141a36aaf306,0x0057b0ca29e545a1,0x0085db571f9fbc13,0x008b333c554b4693,0x0043ab6ef3e241cb,0x0054fb20aa1e5c70,0x00be0ff852760adf)},
+ {FIELD_LITERAL(0x003973d8938971d6,0x002aca26fa80c1f5,0x00108af1faa6b513,0x00daae275d7924e6,0x0053634ced721308,0x00d2355fe0bbd443,0x00357612b2d22095,0x00f9bb9dd4136cf3)},
+ {FIELD_LITERAL(0x002bff12cf5e03a5,0x001bdb1fa8a19cf8,0x00c91c6793f84d39,0x00f869f1b2eba9af,0x0059bc547dc3236b,0x00d91611d6d38689,0x00e062daaa2c0214,0x00ed3c047cc2bc82)},
+ }}, {{
+ {FIELD_LITERAL(0x000050d70c32b31a,0x001939d576d437b3,0x00d709e598bf9fe6,0x00a885b34bd2ee9e,0x00dd4b5c08ab1a50,0x0091bebd50b55639,0x00cf79ff64acdbc6,0x006067a39d826336)},
+ {FIELD_LITERAL(0x0062dd0fb31be374,0x00fcc96b84c8e727,0x003f64f1375e6ae3,0x0057d9b6dd1af004,0x00d6a167b1103c7b,0x00dd28f3180fb537,0x004ff27ad7167128,0x008934c33461f2ac)},
+ {FIELD_LITERAL(0x0065b472b7900043,0x00ba7efd2ff1064b,0x000b67d6c4c3020f,0x0012d28469f4e46d,0x0031c32939703ec7,0x00b49f0bce133066,0x00f7e10416181d47,0x005c90f51867eecc)},
+ }}, {{
+ {FIELD_LITERAL(0x0051207abd179101,0x00fc2a5c20d9c5da,0x00fb9d5f2701b6df,0x002dd040fdea82b8,0x00f163b0738442ff,0x00d9736bd68855b8,0x00e0d8e93005e61c,0x00df5a40b3988570)},
+ {FIELD_LITERAL(0x0006918f5dfce6dc,0x00d4bf1c793c57fb,0x0069a3f649435364,0x00e89a50e5b0cd6e,0x00b9f6a237e973af,0x006d4ed8b104e41d,0x00498946a3924cd2,0x00c136ec5ac9d4f7)},
+ {FIELD_LITERAL(0x0011a9c290ac5336,0x002b9a2d4a6a6533,0x009a8a68c445d937,0x00361b27b07e5e5c,0x003c043b1755b974,0x00b7eb66cf1155ee,0x0077af5909eefff2,0x0098f609877cc806)},
+ }}, {{
+ {FIELD_LITERAL(0x00ab13af436bf8f4,0x000bcf0a0dac8574,0x00d50c864f705045,0x00c40e611debc842,0x0085010489bd5caa,0x007c5050acec026f,0x00f67d943c8da6d1,0x00de1da0278074c6)},
+ {FIELD_LITERAL(0x00b373076597455f,0x00e83f1af53ac0f5,0x0041f63c01dc6840,0x0097dea19b0c6f4b,0x007f9d63b4c1572c,0x00e692d492d0f5f0,0x00cbcb392e83b4ad,0x0069c0f39ed9b1a8)},
+ {FIELD_LITERAL(0x00861030012707c9,0x009fbbdc7fd4aafb,0x008f591d6b554822,0x00df08a41ea18ade,0x009d7d83e642abea,0x0098c71bda3b78ff,0x0022c89e7021f005,0x0044d29a3fe1e3c4)},
+ }}, {{
+ {FIELD_LITERAL(0x00e748cd7b5c52f2,0x00ea9df883f89cc3,0x0018970df156b6c7,0x00c5a46c2a33a847,0x00cbde395e32aa09,0x0072474ebb423140,0x00fb00053086a23d,0x001dafcfe22d4e1f)},
+ {FIELD_LITERAL(0x00c903ee6d825540,0x00add6c4cf98473e,0x007636efed4227f1,0x00905124ae55e772,0x00e6b38fab12ed53,0x0045e132b863fe55,0x003974662edb366a,0x00b1787052be8208)},
+ {FIELD_LITERAL(0x00a614b00d775c7c,0x00d7c78941cc7754,0x00422dd68b5dabc4,0x00a6110f0167d28b,0x00685a309c252886,0x00b439ffd5143660,0x003656e29ee7396f,0x00c7c9b9ed5ad854)},
+ }}, {{
+ {FIELD_LITERAL(0x0040f7e7c5b37bf2,0x0064e4dc81181bba,0x00a8767ae2a366b6,0x001496b4f90546f2,0x002a28493f860441,0x0021f59513049a3a,0x00852d369a8b7ee3,0x00dd2e7d8b7d30a9)},
+ {FIELD_LITERAL(0x00006e34a35d9fbc,0x00eee4e48b2f019a,0x006b344743003a5f,0x00541d514f04a7e3,0x00e81f9ee7647455,0x005e2b916c438f81,0x00116f8137b7eff0,0x009bd3decc7039d1)},
+ {FIELD_LITERAL(0x0005d226f434110d,0x00af8288b8ef21d5,0x004a7a52ef181c8c,0x00be0b781b4b06de,0x00e6e3627ded07e1,0x00e43aa342272b8b,0x00e86ab424577d84,0x00fb292c566e35bb)},
+ }}, {{
+ {FIELD_LITERAL(0x00334f5303ea1222,0x00dfb3dbeb0a5d3e,0x002940d9592335c1,0x00706a7a63e8938a,0x005a533558bc4caf,0x00558e33192022a9,0x00970d9faf74c133,0x002979fcb63493ca)},
+ {FIELD_LITERAL(0x00e38abece3c82ab,0x005a51f18a2c7a86,0x009dafa2e86d592e,0x00495a62eb688678,0x00b79df74c0eb212,0x0023e8cc78b75982,0x005998cb91075e13,0x00735aa9ba61bc76)},
+ {FIELD_LITERAL(0x00d9f7a82ddbe628,0x00a1fc782889ae0f,0x0071ffda12d14b66,0x0037cf4eca7fb3d5,0x00c80bc242c58808,0x0075bf8c2d08c863,0x008d41f31afc52a7,0x00197962ecf38741)},
+ }}, {{
+ {FIELD_LITERAL(0x006e9f475cccf2ee,0x00454b9cd506430c,0x00224a4fb79ee479,0x0062e3347ef0b5e2,0x0034fd2a3512232a,0x00b8b3cb0f457046,0x00eb20165daa38ec,0x00128eebc2d9c0f7)},
+ {FIELD_LITERAL(0x00bfc5fa1e4ea21f,0x00c21d7b6bb892e6,0x00cf043f3acf0291,0x00c13f2f849b3c90,0x00d1a97ebef10891,0x0061e130a445e7fe,0x0019513fdedbf22b,0x001d60c813bff841)},
+ {FIELD_LITERAL(0x0019561c7fcf0213,0x00e3dca6843ebd77,0x0068ea95b9ca920e,0x009bdfb70f253595,0x00c68f59186aa02a,0x005aee1cca1c3039,0x00ab79a8a937a1ce,0x00b9a0e549959e6f)},
+ }}, {{
+ {FIELD_LITERAL(0x00c79e0b6d97dfbd,0x00917c71fd2bc6e8,0x00db7529ccfb63d8,0x00be5be957f17866,0x00a9e11fdc2cdac1,0x007b91a8e1f44443,0x00a3065e4057d80f,0x004825f5b8d5f6d4)},
+ {FIELD_LITERAL(0x003e4964fa8a8fc8,0x00f6a1cdbcf41689,0x00943cb18fe7fda7,0x00606dafbf34440a,0x005d37a86399c789,0x00e79a2a69417403,0x00fe34f7e68b8866,0x0011f448ed2df10e)},
+ {FIELD_LITERAL(0x00f1f57efcc1fcc4,0x00513679117de154,0x002e5b5b7c86d8c3,0x009f6486561f9cfb,0x00169e74b0170cf7,0x00900205af4af696,0x006acfddb77853f3,0x00df184c90f31068)},
+ }}, {{
+ {FIELD_LITERAL(0x00b37396c3320791,0x00fc7b67175c5783,0x00c36d2cd73ecc38,0x0080ebcc0b328fc5,0x0043a5b22b35d35d,0x00466c9f1713c9da,0x0026ad346dcaa8da,0x007c684e701183a6)},
+ {FIELD_LITERAL(0x00fd579ffb691713,0x00b76af4f81c412d,0x00f239de96110f82,0x00e965fb437f0306,0x00ca7e9436900921,0x00e487f1325fa24a,0x00633907de476380,0x00721c62ac5b8ea0)},
+ {FIELD_LITERAL(0x00c0d54e542eb4f9,0x004ed657171c8dcf,0x00b743a4f7c2a39b,0x00fd9f93ed6cc567,0x00307fae3113e58b,0x0058aa577c93c319,0x00d254556f35b346,0x00491aada2203f0d)},
+ }}, {{
+ {FIELD_LITERAL(0x00dff3103786ff34,0x000144553b1f20c3,0x0095613baeb930e4,0x00098058275ea5d4,0x007cd1402b046756,0x0074d74e4d58aee3,0x005f93fc343ff69b,0x00873df17296b3b0)},
+ {FIELD_LITERAL(0x00c4a1fb48635413,0x00b5dd54423ad59f,0x009ff5d53fd24a88,0x003c98d267fc06a7,0x002db7cb20013641,0x00bd1d6716e191f2,0x006dbc8b29094241,0x0044bbf233dafa2c)},
+ {FIELD_LITERAL(0x0055838d41f531e6,0x00bf6a2dd03c81b2,0x005827a061c4839e,0x0000de2cbb36aac3,0x002efa29d9717478,0x00f9e928cc8a77ba,0x00c134b458def9ef,0x00958a182223fc48)},
+ }}, {{
+ {FIELD_LITERAL(0x000a9ee23c06881f,0x002c727d3d871945,0x00f47d971512d24a,0x00671e816f9ef31a,0x00883af2cfaad673,0x00601f98583d6c9a,0x00b435f5adc79655,0x00ad87b71c04bff2)},
+ {FIELD_LITERAL(0x007860d99db787cf,0x00fda8983018f4a8,0x008c8866bac4743c,0x00ef471f84c82a3f,0x00abea5976d3b8e7,0x00714882896cd015,0x00b49fae584ddac5,0x008e33a1a0b69c81)},
+ {FIELD_LITERAL(0x007b6ee2c9e8a9ec,0x002455dbbd89d622,0x006490cf4eaab038,0x00d925f6c3081561,0x00153b3047de7382,0x003b421f8bdceb6f,0x00761a4a5049da78,0x00980348c5202433)},
+ }}, {{
+ {FIELD_LITERAL(0x007f8a43da97dd5c,0x00058539c800fc7b,0x0040f3cf5a28414a,0x00d68dd0d95283d6,0x004adce9da90146e,0x00befa41c7d4f908,0x007603bc2e3c3060,0x00bdf360ab3545db)},
+ {FIELD_LITERAL(0x00eebfd4e2312cc3,0x00474b2564e4fc8c,0x003303ef14b1da9b,0x003c93e0e66beb1d,0x0013619b0566925a,0x008817c24d901bf3,0x00b62bd8898d218b,0x0075a7716f1e88a2)},
+ {FIELD_LITERAL(0x0009218da1e6890f,0x0026907f5fd02575,0x004dabed5f19d605,0x003abf181870249d,0x00b52fd048cc92c4,0x00b6dd51e415a5c5,0x00d9eb82bd2b4014,0x002c865a43b46b43)},
+ }}, {{
+ {FIELD_LITERAL(0x0070047189452f4c,0x00f7ad12e1ce78d5,0x00af1ba51ec44a8b,0x005f39f63e667cd6,0x00058eac4648425e,0x00d7fdab42bea03b,0x0028576a5688de15,0x00af973209e77c10)},
+ {FIELD_LITERAL(0x00c338b915d8fef0,0x00a893292045c39a,0x0028ab4f2eba6887,0x0060743cb519fd61,0x0006213964093ac0,0x007c0b7a43f6266d,0x008e3557c4fa5bda,0x002da976de7b8d9d)},
+ {FIELD_LITERAL(0x0048729f8a8b6dcd,0x00fe23b85cc4d323,0x00e7384d16e4db0e,0x004a423970678942,0x00ec0b763345d4ba,0x00c477b9f99ed721,0x00c29dad3777b230,0x001c517b466f7df6)},
+ }}, {{
+ {FIELD_LITERAL(0x006366c380f7b574,0x001c7d1f09ff0438,0x003e20a7301f5b22,0x00d3efb1916d28f6,0x0049f4f81060ce83,0x00c69d91ea43ced1,0x002b6f3e5cd269ed,0x005b0fb22ce9ec65)},
+ {FIELD_LITERAL(0x00aa2261022d883f,0x00ebcca4548010ac,0x002528512e28a437,0x0070ca7676b66082,0x0084bda170f7c6d3,0x00581b4747c9b8bb,0x005c96a01061c7e2,0x00fb7c4a362b5273)},
+ {FIELD_LITERAL(0x00c30020eb512d02,0x0060f288283a4d26,0x00b7ed13becde260,0x0075ebb74220f6e9,0x00701079fcfe8a1f,0x001c28fcdff58938,0x002e4544b8f4df6b,0x0060c5bc4f1a7d73)},
+ }}, {{
+ {FIELD_LITERAL(0x00ae307cf069f701,0x005859f222dd618b,0x00212d6c46ec0b0d,0x00a0fe4642afb62d,0x00420d8e4a0a8903,0x00a80ff639bdf7b0,0x0019bee1490b5d8e,0x007439e4b9c27a86)},
+ {FIELD_LITERAL(0x00a94700032a093f,0x0076e96c225216e7,0x00a63a4316e45f91,0x007d8bbb4645d3b2,0x00340a6ff22793eb,0x006f935d4572aeb7,0x00b1fb69f00afa28,0x009e8f3423161ed3)},
+ {FIELD_LITERAL(0x009ef49c6b5ced17,0x00a555e6269e9f0a,0x007e6f1d79ec73b5,0x009ac78695a32ac4,0x0001d77fbbcd5682,0x008cea1fee0aaeed,0x00f42bea82a53462,0x002e46ab96cafcc9)},
+ }}, {{
+ {FIELD_LITERAL(0x0051cfcc5885377a,0x00dce566cb1803ca,0x00430c7643f2c7d4,0x00dce1a1337bdcc0,0x0010d5bd7283c128,0x003b1b547f9b46fe,0x000f245e37e770ab,0x007b72511f022b37)},
+ {FIELD_LITERAL(0x0060db815bc4786c,0x006fab25beedc434,0x00c610d06084797c,0x000c48f08537bec0,0x0031aba51c5b93da,0x007968fa6e01f347,0x0030070da52840c6,0x00c043c225a4837f)},
+ {FIELD_LITERAL(0x001bcfd00649ee93,0x006dceb47e2a0fd5,0x00f2cebda0cf8fd0,0x00b6b9d9d1fbdec3,0x00815262e6490611,0x00ef7f5ce3176760,0x00e49cd0c998d58b,0x005fc6cc269ba57c)},
+ }}, {{
+ {FIELD_LITERAL(0x008940211aa0d633,0x00addae28136571d,0x00d68fdbba20d673,0x003bc6129bc9e21a,0x000346cf184ebe9a,0x0068774d741ebc7f,0x0019d5e9e6966557,0x0003cbd7f981b651)},
+ {FIELD_LITERAL(0x004a2902926f8d3f,0x00ad79b42637ab75,0x0088f60b90f2d4e8,0x0030f54ef0e398c4,0x00021dc9bf99681e,0x007ebf66fde74ee3,0x004ade654386e9a4,0x00e7485066be4c27)},
+ {FIELD_LITERAL(0x00445f1263983be0,0x004cf371dda45e6a,0x00744a89d5a310e7,0x001f20ce4f904833,0x00e746edebe66e29,0x000912ab1f6c153d,0x00f61d77d9b2444c,0x0001499cd6647610)},
+ }}
+ }
+};
+const struct curve448_precomputed_s *curve448_precomputed_base
+ = &curve448_precomputed_base_table;
+
+static const niels_t curve448_wnaf_base_table[32] = {
+ {{
+ {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x00e822938a0a0c0c,0x00263a61c9ea9216,0x001204029321b828,0x006a468360983c65,0x0002846f0a782143)},
+ {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x006822938a0a0c0c,0x00263a61c9ea9215,0x001204029321b828,0x006a468360983c65,0x0082846f0a782143)},
+ {FIELD_LITERAL(0x00ef8e22b275198d,0x00b0eb141a0b0e8b,0x001f6789da3cb38c,0x006d2ff8ed39073e,0x00610bdb69a167f3,0x00571f306c9689b4,0x00f557e6f84b2df8,0x002affd38b2c86db)},
+ }}, {{
+ {FIELD_LITERAL(0x00cea0fc8d2e88b5,0x00821612d69f1862,0x0074c283b3e67522,0x005a195ba05a876d,0x000cddfe557feea4,0x008046c795bcc5e5,0x00540969f4d6e119,0x00d27f96d6b143d5)},
+ {FIELD_LITERAL(0x000c3b1019d474e8,0x00e19533e4952284,0x00cc9810ba7c920a,0x00f103d2785945ac,0x00bfa5696cc69b34,0x00a8d3d51e9ca839,0x005623cb459586b9,0x00eae7ce1cd52e9e)},
+ {FIELD_LITERAL(0x0005a178751dd7d8,0x002cc3844c69c42f,0x00acbfe5efe10539,0x009c20f43431a65a,0x008435d96374a7b3,0x009ee57566877bd3,0x0044691725ed4757,0x001e87bb2fe2c6b2)},
+ }}, {{
+ {FIELD_LITERAL(0x000cedc4debf7a04,0x002ffa45000470ac,0x002e9f9678201915,0x0017da1208c4fe72,0x007d558cc7d656cb,0x0037a827287cf289,0x00142472d3441819,0x009c21f166cf8dd1)},
+ {FIELD_LITERAL(0x003ef83af164b2f2,0x000949a5a0525d0d,0x00f4498186cac051,0x00e77ac09ef126d2,0x0073ae0b2c9296e9,0x001c163f6922e3ed,0x0062946159321bea,0x00cfb79b22990b39)},
+ {FIELD_LITERAL(0x00b001431ca9e654,0x002d7e5eabcc9a3a,0x0052e8114c2f6747,0x0079ac4f94487f92,0x00bffd919b5d749c,0x00261f92ad15e620,0x00718397b7a97895,0x00c1443e6ebbc0c4)},
+ }}, {{
+ {FIELD_LITERAL(0x00eacd90c1e0a049,0x008977935b149fbe,0x0004cb9ba11c93dc,0x009fbd5b3470844d,0x004bc18c9bfc22cf,0x0057679a991839f3,0x00ef15b76fb4092e,0x0074a5173a225041)},
+ {FIELD_LITERAL(0x003f5f9d7ec4777b,0x00ab2e733c919c94,0x001bb6c035245ae5,0x00a325a49a883630,0x0033e9a9ea3cea2f,0x00e442a1eaa0e844,0x00b2116d5b0e71b8,0x00c16abed6d64047)},
+ {FIELD_LITERAL(0x00c560b5ed051165,0x001945adc5d65094,0x00e221865710f910,0x00cc12bc9e9b8ceb,0x004faa9518914e35,0x0017476d89d42f6d,0x00b8f637c8fa1c8b,0x0088c7d2790864b8)},
+ }}, {{
+ {FIELD_LITERAL(0x00ef7eafc1c69be6,0x0085d3855778fbea,0x002c8d5b450cb6f5,0x004e77de5e1e7fec,0x0047c057893abded,0x001b430b85d51e16,0x00965c7b45640c3c,0x00487b2bb1162b97)},
+ {FIELD_LITERAL(0x0099c73a311beec2,0x00a3eff38d8912ad,0x002efa9d1d7e8972,0x00f717ae1e14d126,0x002833f795850c8b,0x0066c12ad71486bd,0x00ae9889da4820eb,0x00d6044309555c08)},
+ {FIELD_LITERAL(0x004b1c5283d15e41,0x00669d8ea308ff75,0x0004390233f762a1,0x00e1d67b83cb6cec,0x003eebaa964c78b1,0x006b0aff965eb664,0x00b313d4470bdc37,0x008814ffcb3cb9d8)},
+ }}, {{
+ {FIELD_LITERAL(0x009724b8ce68db70,0x007678b5ed006f3d,0x00bdf4b89c0abd73,0x00299748e04c7c6d,0x00ddd86492c3c977,0x00c5a7febfa30a99,0x00ed84715b4b02bb,0x00319568adf70486)},
+ {FIELD_LITERAL(0x0070ff2d864de5bb,0x005a37eeb637ee95,0x0033741c258de160,0x00e6ca5cb1988f46,0x001ceabd92a24661,0x0030957bd500fe40,0x001c3362afe912c5,0x005187889f678bd2)},
+ {FIELD_LITERAL(0x0086835fc62bbdc7,0x009c3516ca4910a1,0x00956c71f8d00783,0x0095c78fcf63235f,0x00fc7ff6ba05c222,0x00cdd8b3f8d74a52,0x00ac5ae16de8256e,0x00e9d4be8ed48624)},
+ }}, {{
+ {FIELD_LITERAL(0x00c0ce11405df2d8,0x004e3f37b293d7b6,0x002410172e1ac6db,0x00b8dbff4bf8143d,0x003a7b409d56eb66,0x003e0f6a0dfef9af,0x0081c4e4d3645be1,0x00ce76076b127623)},
+ {FIELD_LITERAL(0x00f6ee0f98974239,0x0042d89af07d3a4f,0x00846b7fe84346b5,0x006a21fc6a8d39a1,0x00ac8bc2541ff2d9,0x006d4e2a77732732,0x009a39b694cc3f2f,0x0085c0aa2a404c8f)},
+ {FIELD_LITERAL(0x00b261101a218548,0x00c1cae96424277b,0x00869da0a77dd268,0x00bc0b09f8ec83ea,0x00d61027f8e82ba9,0x00aa4c85999dce67,0x00eac3132b9f3fe1,0x00fb9b0cf1c695d2)},
+ }}, {{
+ {FIELD_LITERAL(0x0043079295512f0d,0x0046a009861758e0,0x003ee2842a807378,0x0034cc9d1298e4fa,0x009744eb4d31b3ee,0x00afacec96650cd0,0x00ac891b313761ae,0x00e864d6d26e708a)},
+ {FIELD_LITERAL(0x00a84d7c8a23b491,0x0088e19aa868b27f,0x0005986d43e78ce9,0x00f28012f0606d28,0x0017ded7e10249b3,0x005ed4084b23af9b,0x00b9b0a940564472,0x00ad9056cceeb1f4)},
+ {FIELD_LITERAL(0x00db91b357fe755e,0x00a1aa544b15359c,0x00af4931a0195574,0x007686124fe11aef,0x00d1ead3c7b9ef7e,0x00aaf5fc580f8c15,0x00e727be147ee1ec,0x003c61c1e1577b86)},
+ }}, {{
+ {FIELD_LITERAL(0x009d3fca983220cf,0x00cd11acbc853dc4,0x0017590409d27f1d,0x00d2176698082802,0x00fa01251b2838c8,0x00dd297a0d9b51c6,0x00d76c92c045820a,0x00534bc7c46c9033)},
+ {FIELD_LITERAL(0x0080ed9bc9b07338,0x00fceac7745d2652,0x008a9d55f5f2cc69,0x0096ce72df301ac5,0x00f53232e7974d87,0x0071728c7ae73947,0x0090507602570778,0x00cb81cfd883b1b2)},
+ {FIELD_LITERAL(0x005011aadea373da,0x003a8578ec896034,0x00f20a6535fa6d71,0x005152d31e5a87cf,0x002bac1c8e68ca31,0x00b0e323db4c1381,0x00f1d596b7d5ae25,0x00eae458097cb4e0)},
+ }}, {{
+ {FIELD_LITERAL(0x00920ac80f9b0d21,0x00f80f7f73401246,0x0086d37849b557d6,0x0002bd4b317b752e,0x00b26463993a42bb,0x002070422a73b129,0x00341acaa0380cb3,0x00541914dd66a1b2)},
+ {FIELD_LITERAL(0x00c1513cd66abe8c,0x000139e01118944d,0x0064abbcb8080bbb,0x00b3b08202473142,0x00c629ef25da2403,0x00f0aec3310d9b7f,0x0050b2227472d8cd,0x00f6c8a922d41fb4)},
+ {FIELD_LITERAL(0x001075ccf26b7b1f,0x00bb6bb213170433,0x00e9491ad262da79,0x009ef4f48d2d384c,0x008992770766f09d,0x001584396b6b1101,0x00af3f8676c9feef,0x0024603c40269118)},
+ }}, {{
+ {FIELD_LITERAL(0x009dd7b31319527c,0x001e7ac948d873a9,0x00fa54b46ef9673a,0x0066efb8d5b02fe6,0x00754b1d3928aeae,0x0004262ac72a6f6b,0x0079b7d49a6eb026,0x003126a753540102)},
+ {FIELD_LITERAL(0x009666e24f693947,0x00f714311269d45f,0x0010ffac1d0c851c,0x0066e80c37363497,0x00f1f4ad010c60b0,0x0015c87408470ff7,0x00651d5e9c7766a4,0x008138819d7116de)},
+ {FIELD_LITERAL(0x003934b11c57253b,0x00ef308edf21f46e,0x00e54e99c7a16198,0x0080d57135764e63,0x00751c27b946bc24,0x00dd389ce4e9e129,0x00a1a2bfd1cd84dc,0x002fae73e5149b32)},
+ }}, {{
+ {FIELD_LITERAL(0x00911657dffb4cdd,0x00c100b7cc553d06,0x00449d075ec467cc,0x007062100bc64e70,0x0043cf86f7bd21e7,0x00f401dc4b797dea,0x005224afb2f62e65,0x00d1ede3fb5a42be)},
+ {FIELD_LITERAL(0x00f2ba36a41aa144,0x00a0c22d946ee18f,0x008aae8ef9a14f99,0x00eef4d79b19bb36,0x008e75ce3d27b1fc,0x00a65daa03b29a27,0x00d9cc83684eb145,0x009e1ed80cc2ed74)},
+ {FIELD_LITERAL(0x00bed953d1997988,0x00b93ed175a24128,0x00871c5963fb6365,0x00ca2df20014a787,0x00f5d9c1d0b34322,0x00f6f5942818db0a,0x004cc091f49c9906,0x00e8a188a60bff9f)},
+ }}, {{
+ {FIELD_LITERAL(0x0032c7762032fae8,0x00e4087232e0bc21,0x00f767344b6e8d85,0x00bbf369b76c2aa2,0x008a1f46c6e1570c,0x001368cd9780369f,0x007359a39d079430,0x0003646512921434)},
+ {FIELD_LITERAL(0x007c4b47ca7c73e7,0x005396221039734b,0x008b64ddf0e45d7e,0x00bfad5af285e6c2,0x008ec711c5b1a1a8,0x00cf663301237f98,0x00917ee3f1655126,0x004152f337efedd8)},
+ {FIELD_LITERAL(0x0007c7edc9305daa,0x000a6664f273701c,0x00f6e78795e200b1,0x005d05b9ecd2473e,0x0014f5f17c865786,0x00c7fd2d166fa995,0x004939a2d8eb80e0,0x002244ba0942c199)},
+ }}, {{
+ {FIELD_LITERAL(0x00321e767f0262cf,0x002e57d776caf68e,0x00bf2c94814f0437,0x00c339196acd622f,0x001db4cce71e2770,0x001ded5ddba6eee2,0x0078608ab1554c8d,0x00067fe0ab76365b)},
+ {FIELD_LITERAL(0x00f09758e11e3985,0x00169efdbd64fad3,0x00e8889b7d6dacd6,0x0035cdd58ea88209,0x00bcda47586d7f49,0x003cdddcb2879088,0x0016da70187e954b,0x009556ea2e92aacd)},
+ {FIELD_LITERAL(0x008cab16bd1ff897,0x00b389972cdf753f,0x00ea8ed1e46dfdc0,0x004fe7ef94c589f4,0x002b8ae9b805ecf3,0x0025c08d892874a5,0x0023938e98d44c4c,0x00f759134cabf69c)},
+ }}, {{
+ {FIELD_LITERAL(0x006c2a84678e4b3b,0x007a194aacd1868f,0x00ed0225af424761,0x00da0a6f293c64b8,0x001062ac5c6a7a18,0x0030f5775a8aeef4,0x0002acaad76b7af0,0x00410b8fd63a579f)},
+ {FIELD_LITERAL(0x001ec59db3d9590e,0x001e9e3f1c3f182d,0x0045a9c3ec2cab14,0x0008198572aeb673,0x00773b74068bd167,0x0012535eaa395434,0x0044dba9e3bbb74a,0x002fba4d3c74bd0e)},
+ {FIELD_LITERAL(0x0042bf08fe66922c,0x003318b8fbb49e8c,0x00d75946004aa14c,0x00f601586b42bf1c,0x00c74cf1d912fe66,0x00abcb36974b30ad,0x007eb78720c9d2b8,0x009f54ab7bd4df85)},
+ }}, {{
+ {FIELD_LITERAL(0x00db9fc948f73826,0x00fa8b3746ed8ee9,0x00132cb65aafbeb2,0x00c36ff3fe7925b8,0x00837daed353d2fe,0x00ec661be0667cf4,0x005beb8ed2e90204,0x00d77dd69e564967)},
+ {FIELD_LITERAL(0x0042e6268b861751,0x0008dd0469500c16,0x00b51b57c338a3fd,0x00cc4497d85cff6b,0x002f13d6b57c34a4,0x0083652eaf301105,0x00cc344294cc93a8,0x0060f4d02810e270)},
+ {FIELD_LITERAL(0x00a8954363cd518b,0x00ad171124bccb7b,0x0065f46a4adaae00,0x001b1a5b2a96e500,0x0043fe24f8233285,0x0066996d8ae1f2c3,0x00c530f3264169f9,0x00c0f92d07cf6a57)},
+ }}, {{
+ {FIELD_LITERAL(0x0036a55c6815d943,0x008c8d1def993db3,0x002e0e1e8ff7318f,0x00d883a4b92db00a,0x002f5e781ae33906,0x001a72adb235c06d,0x00f2e59e736e9caa,0x001a4b58e3031914)},
+ {FIELD_LITERAL(0x00d73bfae5e00844,0x00bf459766fb5f52,0x0061b4f5a5313cde,0x004392d4c3b95514,0x000d3551b1077523,0x0000998840ee5d71,0x006de6e340448b7b,0x00251aa504875d6e)},
+ {FIELD_LITERAL(0x003bf343427ac342,0x00adc0a78642b8c5,0x0003b893175a8314,0x0061a34ade5703bc,0x00ea3ea8bb71d632,0x00be0df9a1f198c2,0x0046dd8e7c1635fb,0x00f1523fdd25d5e5)},
+ }}, {{
+ {FIELD_LITERAL(0x00633f63fc9dd406,0x00e713ff80e04a43,0x0060c6e970f2d621,0x00a57cd7f0df1891,0x00f2406a550650bb,0x00b064290efdc684,0x001eab0144d17916,0x00cd15f863c293ab)},
+ {FIELD_LITERAL(0x0029cec55273f70d,0x007044ee275c6340,0x0040f637a93015e2,0x00338bb78db5aae9,0x001491b2a6132147,0x00a125d6cfe6bde3,0x005f7ac561ba8669,0x001d5eaea3fbaacf)},
+ {FIELD_LITERAL(0x00054e9635e3be31,0x000e43f31e2872be,0x00d05b1c9e339841,0x006fac50bd81fd98,0x00cdc7852eaebb09,0x004ff519b061991b,0x009099e8107d4c85,0x00273e24c36a4a61)},
+ }}, {{
+ {FIELD_LITERAL(0x00070b4441ef2c46,0x00efa5b02801a109,0x00bf0b8c3ee64adf,0x008a67e0b3452e98,0x001916b1f2fa7a74,0x00d781a78ff6cdc3,0x008682ce57e5c919,0x00cc1109dd210da3)},
+ {FIELD_LITERAL(0x00cae8aaff388663,0x005e983a35dda1c7,0x007ab1030d8e37f4,0x00e48940f5d032fe,0x006a36f9ef30b331,0x009be6f03958c757,0x0086231ceba91400,0x008bd0f7b823e7aa)},
+ {FIELD_LITERAL(0x00cf881ebef5a45a,0x004ebea78e7c6f2c,0x0090da9209cf26a0,0x00de2b2e4c775b84,0x0071d6031c3c15ae,0x00d9e927ef177d70,0x00894ee8c23896fd,0x00e3b3b401e41aad)},
+ }}, {{
+ {FIELD_LITERAL(0x00204fef26864170,0x00819269c5dee0f8,0x00bfb4713ec97966,0x0026339a6f34df78,0x001f26e64c761dc2,0x00effe3af313cb60,0x00e17b70138f601b,0x00f16e1ccd9ede5e)},
+ {FIELD_LITERAL(0x005d9a8353fdb2db,0x0055cc2048c698f0,0x00f6c4ac89657218,0x00525034d73faeb2,0x00435776fbda3c7d,0x0070ea5312323cbc,0x007a105d44d069fb,0x006dbc8d6dc786aa)},
+ {FIELD_LITERAL(0x0017cff19cd394ec,0x00fef7b810922587,0x00e6483970dff548,0x00ddf36ad6874264,0x00e61778523fcce2,0x0093a66c0c93b24a,0x00fd367114db7f86,0x007652d7ddce26dd)},
+ }}, {{
+ {FIELD_LITERAL(0x00d92ced7ba12843,0x00aea9c7771e86e7,0x0046639693354f7b,0x00a628dbb6a80c47,0x003a0b0507372953,0x00421113ab45c0d9,0x00e545f08362ab7a,0x0028ce087b4d6d96)},
+ {FIELD_LITERAL(0x00a67ee7cf9f99eb,0x005713b275f2ff68,0x00f1d536a841513d,0x00823b59b024712e,0x009c46b9d0d38cec,0x00cdb1595aa2d7d4,0x008375b3423d9af8,0x000ab0b516d978f7)},
+ {FIELD_LITERAL(0x00428dcb3c510b0f,0x00585607ea24bb4e,0x003736bf1603687a,0x00c47e568c4fe3c7,0x003cd00282848605,0x0043a487c3b91939,0x004ffc04e1095a06,0x00a4c989a3d4b918)},
+ }}, {{
+ {FIELD_LITERAL(0x00a8778d0e429f7a,0x004c02b059105a68,0x0016653b609da3ff,0x00d5107bd1a12d27,0x00b4708f9a771cab,0x00bb63b662033f69,0x0072f322240e7215,0x0019445b59c69222)},
+ {FIELD_LITERAL(0x00cf4f6069a658e6,0x0053ca52859436a6,0x0064b994d7e3e117,0x00cb469b9a07f534,0x00cfb68f399e9d47,0x00f0dcb8dac1c6e7,0x00f2ab67f538b3a5,0x0055544f178ab975)},
+ {FIELD_LITERAL(0x0099b7a2685d538c,0x00e2f1897b7c0018,0x003adac8ce48dae3,0x00089276d5c50c0c,0x00172fca07ad6717,0x00cb1a72f54069e5,0x004ee42f133545b3,0x00785f8651362f16)},
+ }}, {{
+ {FIELD_LITERAL(0x0049cbac38509e11,0x0015234505d42cdf,0x00794fb0b5840f1c,0x00496437344045a5,0x0031b6d944e4f9b0,0x00b207318ac1f5d8,0x0000c840da7f5c5d,0x00526f373a5c8814)},
+ {FIELD_LITERAL(0x002c7b7742d1dfd9,0x002cabeb18623c01,0x00055f5e3e044446,0x006c20f3b4ef54ba,0x00c600141ec6b35f,0x00354f437f1a32a3,0x00bac4624a3520f9,0x00c483f734a90691)},
+ {FIELD_LITERAL(0x0053a737d422918d,0x00f7fca1d8758625,0x00c360336dadb04c,0x00f38e3d9158a1b8,0x0069ce3b418e84c6,0x005d1697eca16ead,0x00f8bd6a35ece13d,0x007885dfc2b5afea)},
+ }}, {{
+ {FIELD_LITERAL(0x00c3617ae260776c,0x00b20dc3e96922d7,0x00a1a7802246706a,0x00ca6505a5240244,0x002246b62d919782,0x001439102d7aa9b3,0x00e8af1139e6422c,0x00c888d1b52f2b05)},
+ {FIELD_LITERAL(0x005b67690ffd41d9,0x005294f28df516f9,0x00a879272412fcb9,0x00098b629a6d1c8d,0x00fabd3c8050865a,0x00cd7e5b0a3879c5,0x00153238210f3423,0x00357cac101e9f42)},
+ {FIELD_LITERAL(0x008917b454444fb7,0x00f59247c97e441b,0x00a6200a6815152d,0x0009a4228601d254,0x001c0360559bd374,0x007563362039cb36,0x00bd75b48d74e32b,0x0017f515ac3499e8)},
+ }}, {{
+ {FIELD_LITERAL(0x001532a7ffe41c5a,0x00eb1edce358d6bf,0x00ddbacc7b678a7b,0x008a7b70f3c841a3,0x00f1923bf27d3f4c,0x000b2713ed8f7873,0x00aaf67e29047902,0x0044994a70b3976d)},
+ {FIELD_LITERAL(0x00d54e802082d42c,0x00a55aa0dce7cc6c,0x006477b96073f146,0x0082efe4ceb43594,0x00a922bcba026845,0x0077f19d1ab75182,0x00c2bb2737846e59,0x0004d7eec791dd33)},
+ {FIELD_LITERAL(0x0044588d1a81d680,0x00b0a9097208e4f8,0x00212605350dc57e,0x0028717cd2871123,0x00fb083c100fd979,0x0045a056ce063fdf,0x00a5d604b4dd6a41,0x001dabc08ba4e236)},
+ }}, {{
+ {FIELD_LITERAL(0x00c4887198d7a7fa,0x00244f98fb45784a,0x0045911e15a15d01,0x001d323d374c0966,0x00967c3915196562,0x0039373abd2f3c67,0x000d2c5614312423,0x0041cf2215442ce3)},
+ {FIELD_LITERAL(0x008ede889ada7f06,0x001611e91de2e135,0x00fdb9a458a471b9,0x00563484e03710d1,0x0031cc81925e3070,0x0062c97b3af80005,0x00fa733eea28edeb,0x00e82457e1ebbc88)},
+ {FIELD_LITERAL(0x006a0df5fe9b6f59,0x00a0d4ff46040d92,0x004a7cedb6f93250,0x00d1df8855b8c357,0x00e73a46086fd058,0x0048fb0add6dfe59,0x001e03a28f1b4e3d,0x00a871c993308d76)},
+ }}, {{
+ {FIELD_LITERAL(0x0030dbb2d1766ec8,0x00586c0ad138555e,0x00d1a34f9e91c77c,0x0063408ad0e89014,0x00d61231b05f6f5b,0x0009abf569f5fd8a,0x00aec67a110f1c43,0x0031d1a790938dd7)},
+ {FIELD_LITERAL(0x006cded841e2a862,0x00198d60af0ab6fb,0x0018f09db809e750,0x004e6ac676016263,0x00eafcd1620969cb,0x002c9784ca34917d,0x0054f00079796de7,0x00d9fab5c5972204)},
+ {FIELD_LITERAL(0x004bd0fee2438a83,0x00b571e62b0f83bd,0x0059287d7ce74800,0x00fb3631b645c3f0,0x00a018e977f78494,0x0091e27065c27b12,0x007696c1817165e0,0x008c40be7c45ba3a)},
+ }}, {{
+ {FIELD_LITERAL(0x00a0f326327cb684,0x001c7d0f672680ff,0x008c1c81ffb112d1,0x00f8f801674eddc8,0x00e926d5d48c2a9d,0x005bd6d954c6fe9a,0x004c6b24b4e33703,0x00d05eb5c09105cc)},
+ {FIELD_LITERAL(0x00d61731caacf2cf,0x002df0c7609e01c5,0x00306172208b1e2b,0x00b413fe4fb2b686,0x00826d360902a221,0x003f8d056e67e7f7,0x0065025b0175e989,0x00369add117865eb)},
+ {FIELD_LITERAL(0x00aaf895aec2fa11,0x000f892bc313eb52,0x005b1c794dad050b,0x003f8ec4864cec14,0x00af81058d0b90e5,0x00ebe43e183997bb,0x00a9d610f9f3e615,0x007acd8eec2e88d3)},
+ }}, {{
+ {FIELD_LITERAL(0x0049b2fab13812a3,0x00846db32cd60431,0x000177fa578c8d6c,0x00047d0e2ad4bc51,0x00b158ba38d1e588,0x006a45daad79e3f3,0x000997b93cab887b,0x00c47ea42fa23dc3)},
+ {FIELD_LITERAL(0x0012b6fef7aeb1ca,0x009412768194b6a7,0x00ff0d351f23ab93,0x007e8a14c1aff71b,0x006c1c0170c512bc,0x0016243ea02ab2e5,0x007bb6865b303f3e,0x0015ce6b29b159f4)},
+ {FIELD_LITERAL(0x009961cd02e68108,0x00e2035d3a1d0836,0x005d51f69b5e1a1d,0x004bccb4ea36edcd,0x0069be6a7aeef268,0x0063f4dd9de8d5a7,0x006283783092ca35,0x0075a31af2c35409)},
+ }}, {{
+ {FIELD_LITERAL(0x00c412365162e8cf,0x00012283fb34388a,0x003e6543babf39e2,0x00eead6b3a804978,0x0099c0314e8b326f,0x00e98e0a8d477a4f,0x00d2eb96b127a687,0x00ed8d7df87571bb)},
+ {FIELD_LITERAL(0x00777463e308cacf,0x00c8acb93950132d,0x00ebddbf4ca48b2c,0x0026ad7ca0795a0a,0x00f99a3d9a715064,0x000d60bcf9d4dfcc,0x005e65a73a437a06,0x0019d536a8db56c8)},
+ {FIELD_LITERAL(0x00192d7dd558d135,0x0027cd6a8323ffa7,0x00239f1a412dc1e7,0x0046b4b3be74fc5c,0x0020c47a2bef5bce,0x00aa17e48f43862b,0x00f7e26c96342e5f,0x0008011c530f39a9)},
+ }}, {{
+ {FIELD_LITERAL(0x00aad4ac569bf0f1,0x00a67adc90b27740,0x0048551369a5751a,0x0031252584a3306a,0x0084e15df770e6fc,0x00d7bba1c74b5805,0x00a80ef223af1012,0x0089c85ceb843a34)},
+ {FIELD_LITERAL(0x00c4545be4a54004,0x0099e11f60357e6c,0x001f3936d19515a6,0x007793df84341a6e,0x0051061886717ffa,0x00e9b0a660b28f85,0x0044ea685892de0d,0x000257d2a1fda9d9)},
+ {FIELD_LITERAL(0x007e8b01b24ac8a8,0x006cf3b0b5ca1337,0x00f1607d3e36a570,0x0039b7fab82991a1,0x00231777065840c5,0x00998e5afdd346f9,0x00b7dc3e64acc85f,0x00baacc748013ad6)},
+ }}, {{
+ {FIELD_LITERAL(0x008ea6a4177580bf,0x005fa1953e3f0378,0x005fe409ac74d614,0x00452327f477e047,0x00a4018507fb6073,0x007b6e71951caac8,0x0012b42ab8a6ce91,0x0080eca677294ab7)},
+ {FIELD_LITERAL(0x00a53edc023ba69b,0x00c6afa83ddde2e8,0x00c3f638b307b14e,0x004a357a64414062,0x00e4d94d8b582dc9,0x001739caf71695b7,0x0012431b2ae28de1,0x003b6bc98682907c)},
+ {FIELD_LITERAL(0x008a9a93be1f99d6,0x0079fa627cc699c8,0x00b0cfb134ba84c8,0x001c4b778249419a,0x00df4ab3d9c44f40,0x009f596e6c1a9e3c,0x001979c0df237316,0x00501e953a919b87)},
+ }}
+};
+const niels_t *curve448_wnaf_base = curve448_wnaf_base_table;
diff --git a/deps/openssl/openssl/crypto/ec/curve448/curve448utils.h b/deps/openssl/openssl/crypto/ec/curve448/curve448utils.h
new file mode 100644
index 0000000000..9bf837993c
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/curve448utils.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_CURVE448UTILS_H
+# define HEADER_CURVE448UTILS_H
+
+# include <openssl/e_os2.h>
+
+/*
+ * Internal word types. Somewhat tricky. This could be decided separately per
+ * platform. However, the structs do need to be all the same size and
+ * alignment on a given platform to support dynamic linking, since even if you
+ * header was built with eg arch_neon, you might end up linking a library built
+ * with arch_arm32.
+ */
+# ifndef C448_WORD_BITS
+# if (defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) \
+ && !defined(__sparc__)
+# define C448_WORD_BITS 64 /* The number of bits in a word */
+# else
+# define C448_WORD_BITS 32 /* The number of bits in a word */
+# endif
+# endif
+
+# if C448_WORD_BITS == 64
+/* Word size for internal computations */
+typedef uint64_t c448_word_t;
+/* Signed word size for internal computations */
+typedef int64_t c448_sword_t;
+/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
+typedef uint64_t c448_bool_t;
+/* Double-word size for internal computations */
+typedef __uint128_t c448_dword_t;
+/* Signed double-word size for internal computations */
+typedef __int128_t c448_dsword_t;
+# elif C448_WORD_BITS == 32
+/* Word size for internal computations */
+typedef uint32_t c448_word_t;
+/* Signed word size for internal computations */
+typedef int32_t c448_sword_t;
+/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
+typedef uint32_t c448_bool_t;
+/* Double-word size for internal computations */
+typedef uint64_t c448_dword_t;
+/* Signed double-word size for internal computations */
+typedef int64_t c448_dsword_t;
+# else
+# error "Only supporting C448_WORD_BITS = 32 or 64 for now"
+# endif
+
+/* C448_TRUE = -1 so that C448_TRUE & x = x */
+# define C448_TRUE (0 - (c448_bool_t)1)
+
+/* C448_FALSE = 0 so that C448_FALSE & x = 0 */
+# define C448_FALSE 0
+
+/* Another boolean type used to indicate success or failure. */
+typedef enum {
+ C448_SUCCESS = -1, /**< The operation succeeded. */
+ C448_FAILURE = 0 /**< The operation failed. */
+} c448_error_t;
+
+/* Return success if x is true */
+static ossl_inline c448_error_t c448_succeed_if(c448_bool_t x)
+{
+ return (c448_error_t) x;
+}
+
+#endif /* __C448_COMMON_H__ */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/ed448.h b/deps/openssl/openssl/crypto/ec/curve448/ed448.h
new file mode 100644
index 0000000000..5fe939e8e1
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/ed448.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_ED448_H
+# define HEADER_ED448_H
+
+# include "point_448.h"
+
+/* Number of bytes in an EdDSA public key. */
+# define EDDSA_448_PUBLIC_BYTES 57
+
+/* Number of bytes in an EdDSA private key. */
+# define EDDSA_448_PRIVATE_BYTES EDDSA_448_PUBLIC_BYTES
+
+/* Number of bytes in an EdDSA private key. */
+# define EDDSA_448_SIGNATURE_BYTES (EDDSA_448_PUBLIC_BYTES + \
+ EDDSA_448_PRIVATE_BYTES)
+
+/* EdDSA encoding ratio. */
+# define C448_EDDSA_ENCODE_RATIO 4
+
+/* EdDSA decoding ratio. */
+# define C448_EDDSA_DECODE_RATIO (4 / 4)
+
+/*
+ * EdDSA key generation. This function uses a different (non-Decaf) encoding.
+ *
+ * pubkey (out): The public key.
+ * privkey (in): The private key.
+ */
+c448_error_t c448_ed448_derive_public_key(
+ uint8_t pubkey [EDDSA_448_PUBLIC_BYTES],
+ const uint8_t privkey [EDDSA_448_PRIVATE_BYTES]);
+
+/*
+ * EdDSA signing.
+ *
+ * signature (out): The signature.
+ * privkey (in): The private key.
+ * pubkey (in): The public key.
+ * message (in): The message to sign.
+ * message_len (in): The length of the message.
+ * prehashed (in): Nonzero if the message is actually the hash of something
+ * you want to sign.
+ * context (in): A "context" for this signature of up to 255 bytes.
+ * context_len (in): Length of the context.
+ *
+ * For Ed25519, it is unsafe to use the same key for both prehashed and
+ * non-prehashed messages, at least without some very careful protocol-level
+ * disambiguation. For Ed448 it is safe.
+ */
+c448_error_t c448_ed448_sign(
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ size_t context_len);
+
+/*
+ * EdDSA signing with prehash.
+ *
+ * signature (out): The signature.
+ * privkey (in): The private key.
+ * pubkey (in): The public key.
+ * hash (in): The hash of the message. This object will not be modified by the
+ * call.
+ * context (in): A "context" for this signature of up to 255 bytes. Must be the
+ * same as what was used for the prehash.
+ * context_len (in): Length of the context.
+ *
+ * For Ed25519, it is unsafe to use the same key for both prehashed and
+ * non-prehashed messages, at least without some very careful protocol-level
+ * disambiguation. For Ed448 it is safe.
+ */
+c448_error_t c448_ed448_sign_prehash(
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64],
+ const uint8_t *context,
+ size_t context_len);
+
+/*
+ * EdDSA signature verification.
+ *
+ * Uses the standard (i.e. less-strict) verification formula.
+ *
+ * signature (in): The signature.
+ * pubkey (in): The public key.
+ * message (in): The message to verify.
+ * message_len (in): The length of the message.
+ * prehashed (in): Nonzero if the message is actually the hash of something you
+ * want to verify.
+ * context (in): A "context" for this signature of up to 255 bytes.
+ * context_len (in): Length of the context.
+ *
+ * For Ed25519, it is unsafe to use the same key for both prehashed and
+ * non-prehashed messages, at least without some very careful protocol-level
+ * disambiguation. For Ed448 it is safe.
+ */
+c448_error_t c448_ed448_verify(const uint8_t
+ signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t
+ pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ uint8_t context_len);
+
+/*
+ * EdDSA signature verification.
+ *
+ * Uses the standard (i.e. less-strict) verification formula.
+ *
+ * signature (in): The signature.
+ * pubkey (in): The public key.
+ * hash (in): The hash of the message. This object will not be modified by the
+ * call.
+ * context (in): A "context" for this signature of up to 255 bytes. Must be the
+ * same as what was used for the prehash.
+ * context_len (in): Length of the context.
+ *
+ * For Ed25519, it is unsafe to use the same key for both prehashed and
+ * non-prehashed messages, at least without some very careful protocol-level
+ * disambiguation. For Ed448 it is safe.
+ */
+c448_error_t c448_ed448_verify_prehash(
+ const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64],
+ const uint8_t *context,
+ uint8_t context_len);
+
+/*
+ * EdDSA point encoding. Used internally, exposed externally.
+ * Multiplies by C448_EDDSA_ENCODE_RATIO first.
+ *
+ * The multiplication is required because the EdDSA encoding represents
+ * the cofactor information, but the Decaf encoding ignores it (which
+ * is the whole point). So if you decode from EdDSA and re-encode to
+ * EdDSA, the cofactor info must get cleared, because the intermediate
+ * representation doesn't track it.
+ *
+ * The way we handle this is to multiply by C448_EDDSA_DECODE_RATIO when
+ * decoding, and by C448_EDDSA_ENCODE_RATIO when encoding. The product of
+ * these ratios is always exactly the cofactor 4, so the cofactor ends up
+ * cleared one way or another. But exactly how that shakes out depends on the
+ * base points specified in RFC 8032.
+ *
+ * The upshot is that if you pass the Decaf/Ristretto base point to
+ * this function, you will get C448_EDDSA_ENCODE_RATIO times the
+ * EdDSA base point.
+ *
+ * enc (out): The encoded point.
+ * p (in): The point.
+ */
+void curve448_point_mul_by_ratio_and_encode_like_eddsa(
+ uint8_t enc [EDDSA_448_PUBLIC_BYTES],
+ const curve448_point_t p);
+
+/*
+ * EdDSA point decoding. Multiplies by C448_EDDSA_DECODE_RATIO, and
+ * ignores cofactor information.
+ *
+ * See notes on curve448_point_mul_by_ratio_and_encode_like_eddsa
+ *
+ * enc (out): The encoded point.
+ * p (in): The point.
+ */
+c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
+ curve448_point_t p,
+ const uint8_t enc[EDDSA_448_PUBLIC_BYTES]);
+
+/*
+ * EdDSA to ECDH private key conversion
+ * Using the appropriate hash function, hash the EdDSA private key
+ * and keep only the lower bytes to get the ECDH private key
+ *
+ * x (out): The ECDH private key as in RFC7748
+ * ed (in): The EdDSA private key
+ */
+c448_error_t c448_ed448_convert_private_key_to_x448(
+ uint8_t x[X448_PRIVATE_BYTES],
+ const uint8_t ed[EDDSA_448_PRIVATE_BYTES]);
+
+#endif /* HEADER_ED448_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/eddsa.c b/deps/openssl/openssl/crypto/ec/curve448/eddsa.c
new file mode 100644
index 0000000000..909413a535
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/eddsa.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include "curve448_lcl.h"
+#include "word.h"
+#include "ed448.h"
+#include "internal/numbers.h"
+
+#define COFACTOR 4
+
+static c448_error_t oneshot_hash(uint8_t *out, size_t outlen,
+ const uint8_t *in, size_t inlen)
+{
+ EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
+
+ if (hashctx == NULL)
+ return C448_FAILURE;
+
+ if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+ || !EVP_DigestUpdate(hashctx, in, inlen)
+ || !EVP_DigestFinalXOF(hashctx, out, outlen)) {
+ EVP_MD_CTX_free(hashctx);
+ return C448_FAILURE;
+ }
+
+ EVP_MD_CTX_free(hashctx);
+ return C448_SUCCESS;
+}
+
+static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
+{
+ secret_scalar_ser[0] &= -COFACTOR;
+ secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0;
+ secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
+}
+
+static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed,
+ uint8_t for_prehash,
+ const uint8_t *context,
+ size_t context_len)
+{
+ const char *dom_s = "SigEd448";
+ uint8_t dom[2];
+
+ if (context_len > UINT8_MAX)
+ return C448_FAILURE;
+
+ dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0)
+ - (for_prehash == 0 ? 1 : 0));
+ dom[1] = (uint8_t)context_len;
+
+ if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL)
+ || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s))
+ || !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
+ || !EVP_DigestUpdate(hashctx, context, context_len))
+ return C448_FAILURE;
+
+ return C448_SUCCESS;
+}
+
+/* In this file because it uses the hash */
+c448_error_t c448_ed448_convert_private_key_to_x448(
+ uint8_t x[X448_PRIVATE_BYTES],
+ const uint8_t ed [EDDSA_448_PRIVATE_BYTES])
+{
+ /* pass the private key through oneshot_hash function */
+ /* and keep the first X448_PRIVATE_BYTES bytes */
+ return oneshot_hash(x, X448_PRIVATE_BYTES, ed,
+ EDDSA_448_PRIVATE_BYTES);
+}
+
+c448_error_t c448_ed448_derive_public_key(
+ uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES])
+{
+ /* only this much used for keygen */
+ uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
+ curve448_scalar_t secret_scalar;
+ unsigned int c;
+ curve448_point_t p;
+
+ if (!oneshot_hash(secret_scalar_ser, sizeof(secret_scalar_ser), privkey,
+ EDDSA_448_PRIVATE_BYTES))
+ return C448_FAILURE;
+
+ clamp(secret_scalar_ser);
+
+ curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
+ sizeof(secret_scalar_ser));
+
+ /*
+ * Since we are going to mul_by_cofactor during encoding, divide by it
+ * here. However, the EdDSA base point is not the same as the decaf base
+ * point if the sigma isogeny is in use: the EdDSA base point is on
+ * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when
+ * converted it effectively picks up a factor of 2 from the isogenies. So
+ * we might start at 2 instead of 1.
+ */
+ for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
+ curve448_scalar_halve(secret_scalar, secret_scalar);
+
+ curve448_precomputed_scalarmul(p, curve448_precomputed_base, secret_scalar);
+
+ curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
+
+ /* Cleanup */
+ curve448_scalar_destroy(secret_scalar);
+ curve448_point_destroy(p);
+ OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
+
+ return C448_SUCCESS;
+}
+
+c448_error_t c448_ed448_sign(
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ size_t context_len)
+{
+ curve448_scalar_t secret_scalar;
+ EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
+ c448_error_t ret = C448_FAILURE;
+ curve448_scalar_t nonce_scalar;
+ uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 };
+ unsigned int c;
+ curve448_scalar_t challenge_scalar;
+
+ if (hashctx == NULL)
+ return C448_FAILURE;
+
+ {
+ /*
+ * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialised
+ * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
+ */
+ uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
+
+ if (!oneshot_hash(expanded, sizeof(expanded), privkey,
+ EDDSA_448_PRIVATE_BYTES))
+ goto err;
+ clamp(expanded);
+ curve448_scalar_decode_long(secret_scalar, expanded,
+ EDDSA_448_PRIVATE_BYTES);
+
+ /* Hash to create the nonce */
+ if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+ || !EVP_DigestUpdate(hashctx,
+ expanded + EDDSA_448_PRIVATE_BYTES,
+ EDDSA_448_PRIVATE_BYTES)
+ || !EVP_DigestUpdate(hashctx, message, message_len)) {
+ OPENSSL_cleanse(expanded, sizeof(expanded));
+ goto err;
+ }
+ OPENSSL_cleanse(expanded, sizeof(expanded));
+ }
+
+ /* Decode the nonce */
+ {
+ uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES];
+
+ if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
+ goto err;
+ curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
+ OPENSSL_cleanse(nonce, sizeof(nonce));
+ }
+
+ {
+ /* Scalarmul to create the nonce-point */
+ curve448_scalar_t nonce_scalar_2;
+ curve448_point_t p;
+
+ curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
+ for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
+ curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
+
+ curve448_precomputed_scalarmul(p, curve448_precomputed_base,
+ nonce_scalar_2);
+ curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p);
+ curve448_point_destroy(p);
+ curve448_scalar_destroy(nonce_scalar_2);
+ }
+
+ {
+ uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
+
+ /* Compute the challenge */
+ if (!hash_init_with_dom(hashctx, prehashed, 0, context, context_len)
+ || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
+ || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
+ || !EVP_DigestUpdate(hashctx, message, message_len)
+ || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
+ goto err;
+
+ curve448_scalar_decode_long(challenge_scalar, challenge,
+ sizeof(challenge));
+ OPENSSL_cleanse(challenge, sizeof(challenge));
+ }
+
+ curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
+ curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
+
+ OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES);
+ memcpy(signature, nonce_point, sizeof(nonce_point));
+ curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
+ challenge_scalar);
+
+ curve448_scalar_destroy(secret_scalar);
+ curve448_scalar_destroy(nonce_scalar);
+ curve448_scalar_destroy(challenge_scalar);
+
+ ret = C448_SUCCESS;
+ err:
+ EVP_MD_CTX_free(hashctx);
+ return ret;
+}
+
+c448_error_t c448_ed448_sign_prehash(
+ uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64], const uint8_t *context,
+ size_t context_len)
+{
+ return c448_ed448_sign(signature, privkey, pubkey, hash, 64, 1, context,
+ context_len);
+}
+
+c448_error_t c448_ed448_verify(
+ const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t *message, size_t message_len,
+ uint8_t prehashed, const uint8_t *context,
+ uint8_t context_len)
+{
+ curve448_point_t pk_point, r_point;
+ c448_error_t error =
+ curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
+ curve448_scalar_t challenge_scalar;
+ curve448_scalar_t response_scalar;
+
+ if (C448_SUCCESS != error)
+ return error;
+
+ error =
+ curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
+ if (C448_SUCCESS != error)
+ return error;
+
+ {
+ /* Compute the challenge */
+ EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
+ uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
+
+ if (hashctx == NULL
+ || !hash_init_with_dom(hashctx, prehashed, 0, context,
+ context_len)
+ || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
+ || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
+ || !EVP_DigestUpdate(hashctx, message, message_len)
+ || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) {
+ EVP_MD_CTX_free(hashctx);
+ return C448_FAILURE;
+ }
+
+ EVP_MD_CTX_free(hashctx);
+ curve448_scalar_decode_long(challenge_scalar, challenge,
+ sizeof(challenge));
+ OPENSSL_cleanse(challenge, sizeof(challenge));
+ }
+ curve448_scalar_sub(challenge_scalar, curve448_scalar_zero,
+ challenge_scalar);
+
+ curve448_scalar_decode_long(response_scalar,
+ &signature[EDDSA_448_PUBLIC_BYTES],
+ EDDSA_448_PRIVATE_BYTES);
+
+ /* pk_point = -c(x(P)) + (cx + k)G = kG */
+ curve448_base_double_scalarmul_non_secret(pk_point,
+ response_scalar,
+ pk_point, challenge_scalar);
+ return c448_succeed_if(curve448_point_eq(pk_point, r_point));
+}
+
+c448_error_t c448_ed448_verify_prehash(
+ const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
+ const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
+ const uint8_t hash[64], const uint8_t *context,
+ uint8_t context_len)
+{
+ return c448_ed448_verify(signature, pubkey, hash, 64, 1, context,
+ context_len);
+}
+
+int ED448_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len)
+{
+ return c448_ed448_sign(out_sig, private_key, public_key, message,
+ message_len, 0, context, context_len)
+ == C448_SUCCESS;
+}
+
+int ED448_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[114], const uint8_t public_key[57],
+ const uint8_t *context, size_t context_len)
+{
+ return c448_ed448_verify(signature, public_key, message, message_len, 0,
+ context, (uint8_t)context_len) == C448_SUCCESS;
+}
+
+int ED448ph_sign(uint8_t *out_sig, const uint8_t hash[64],
+ const uint8_t public_key[57], const uint8_t private_key[57],
+ const uint8_t *context, size_t context_len)
+{
+ return c448_ed448_sign_prehash(out_sig, private_key, public_key, hash,
+ context, context_len) == C448_SUCCESS;
+
+}
+
+int ED448ph_verify(const uint8_t hash[64], const uint8_t signature[114],
+ const uint8_t public_key[57], const uint8_t *context,
+ size_t context_len)
+{
+ return c448_ed448_verify_prehash(signature, public_key, hash, context,
+ (uint8_t)context_len) == C448_SUCCESS;
+}
+
+int ED448_public_from_private(uint8_t out_public_key[57],
+ const uint8_t private_key[57])
+{
+ return c448_ed448_derive_public_key(out_public_key, private_key)
+ == C448_SUCCESS;
+}
diff --git a/deps/openssl/openssl/crypto/ec/curve448/f_generic.c b/deps/openssl/openssl/crypto/ec/curve448/f_generic.c
new file mode 100644
index 0000000000..ed8f36d868
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/f_generic.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+#include "field.h"
+
+static const gf MODULUS = {
+ FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff,
+ 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff,
+ 0xffffffffffffff, 0xffffffffffffff)
+};
+
+/* Serialize to wire format. */
+void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit)
+{
+ unsigned int j = 0, fill = 0;
+ dword_t buffer = 0;
+ int i;
+ gf red;
+
+ gf_copy(red, x);
+ gf_strong_reduce(red);
+ if (!with_hibit)
+ assert(gf_hibit(red) == 0);
+
+ for (i = 0; i < (with_hibit ? X_SER_BYTES : SER_BYTES); i++) {
+ if (fill < 8 && j < NLIMBS) {
+ buffer |= ((dword_t) red->limb[LIMBPERM(j)]) << fill;
+ fill += LIMB_PLACE_VALUE(LIMBPERM(j));
+ j++;
+ }
+ serial[i] = (uint8_t)buffer;
+ fill -= 8;
+ buffer >>= 8;
+ }
+}
+
+/* Return high bit of x = low bit of 2x mod p */
+mask_t gf_hibit(const gf x)
+{
+ gf y;
+
+ gf_add(y, x, x);
+ gf_strong_reduce(y);
+ return 0 - (y->limb[0] & 1);
+}
+
+/* Return high bit of x = low bit of 2x mod p */
+mask_t gf_lobit(const gf x)
+{
+ gf y;
+
+ gf_copy(y, x);
+ gf_strong_reduce(y);
+ return 0 - (y->limb[0] & 1);
+}
+
+/* Deserialize from wire format; return -1 on success and 0 on failure. */
+mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit,
+ uint8_t hi_nmask)
+{
+ unsigned int j = 0, fill = 0;
+ dword_t buffer = 0;
+ dsword_t scarry = 0;
+ const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES;
+ unsigned int i;
+ mask_t succ;
+
+ for (i = 0; i < NLIMBS; i++) {
+ while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) {
+ uint8_t sj;
+
+ sj = serial[j];
+ if (j == nbytes - 1)
+ sj &= ~hi_nmask;
+ buffer |= ((dword_t) sj) << fill;
+ fill += 8;
+ j++;
+ }
+ x->limb[LIMBPERM(i)] = (word_t)
+ ((i < NLIMBS - 1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer);
+ fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
+ buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
+ scarry =
+ (scarry + x->limb[LIMBPERM(i)] -
+ MODULUS->limb[LIMBPERM(i)]) >> (8 * sizeof(word_t));
+ }
+ succ = with_hibit ? 0 - (mask_t) 1 : ~gf_hibit(x);
+ return succ & word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry);
+}
+
+/* Reduce to canonical form. */
+void gf_strong_reduce(gf a)
+{
+ dsword_t scarry;
+ word_t scarry_0;
+ dword_t carry = 0;
+ unsigned int i;
+
+ /* first, clear high */
+ gf_weak_reduce(a); /* Determined to have negligible perf impact. */
+
+ /* now the total is less than 2p */
+
+ /* compute total_value - p. No need to reduce mod p. */
+ scarry = 0;
+ for (i = 0; i < NLIMBS; i++) {
+ scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
+ a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i));
+ scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
+ }
+
+ /*
+ * uncommon case: it was >= p, so now scarry = 0 and this = x common case:
+ * it was < p, so now scarry = -1 and this = x - p + 2^255 so let's add
+ * back in p. will carry back off the top for 2^255.
+ */
+ assert(scarry == 0 || scarry == -1);
+
+ scarry_0 = (word_t)scarry;
+
+ /* add it back */
+ for (i = 0; i < NLIMBS; i++) {
+ carry =
+ carry + a->limb[LIMBPERM(i)] +
+ (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
+ a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i));
+ carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
+ }
+
+ assert(carry < 2 && ((word_t)carry + scarry_0) == 0);
+}
+
+/* Subtract two gf elements d=a-b */
+void gf_sub(gf d, const gf a, const gf b)
+{
+ gf_sub_RAW(d, a, b);
+ gf_bias(d, 2);
+ gf_weak_reduce(d);
+}
+
+/* Add two field elements d = a+b */
+void gf_add(gf d, const gf a, const gf b)
+{
+ gf_add_RAW(d, a, b);
+ gf_weak_reduce(d);
+}
+
+/* Compare a==b */
+mask_t gf_eq(const gf a, const gf b)
+{
+ gf c;
+ mask_t ret = 0;
+ unsigned int i;
+
+ gf_sub(c, a, b);
+ gf_strong_reduce(c);
+
+ for (i = 0; i < NLIMBS; i++)
+ ret |= c->limb[LIMBPERM(i)];
+
+ return word_is_zero(ret);
+}
+
+mask_t gf_isr(gf a, const gf x)
+{
+ gf L0, L1, L2;
+
+ gf_sqr(L1, x);
+ gf_mul(L2, x, L1);
+ gf_sqr(L1, L2);
+ gf_mul(L2, x, L1);
+ gf_sqrn(L1, L2, 3);
+ gf_mul(L0, L2, L1);
+ gf_sqrn(L1, L0, 3);
+ gf_mul(L0, L2, L1);
+ gf_sqrn(L2, L0, 9);
+ gf_mul(L1, L0, L2);
+ gf_sqr(L0, L1);
+ gf_mul(L2, x, L0);
+ gf_sqrn(L0, L2, 18);
+ gf_mul(L2, L1, L0);
+ gf_sqrn(L0, L2, 37);
+ gf_mul(L1, L2, L0);
+ gf_sqrn(L0, L1, 37);
+ gf_mul(L1, L2, L0);
+ gf_sqrn(L0, L1, 111);
+ gf_mul(L2, L1, L0);
+ gf_sqr(L0, L2);
+ gf_mul(L1, x, L0);
+ gf_sqrn(L0, L1, 223);
+ gf_mul(L1, L2, L0);
+ gf_sqr(L2, L1);
+ gf_mul(L0, L2, x);
+ gf_copy(a, L1);
+ return gf_eq(L0, ONE);
+}
diff --git a/deps/openssl/openssl/crypto/ec/curve448/field.h b/deps/openssl/openssl/crypto/ec/curve448/field.h
new file mode 100644
index 0000000000..d96d4c023d
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/field.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_FIELD_H
+# define HEADER_FIELD_H
+
+# include "internal/constant_time_locl.h"
+# include <string.h>
+# include <assert.h>
+# include "word.h"
+
+# define NLIMBS (64/sizeof(word_t))
+# define X_SER_BYTES 56
+# define SER_BYTES 56
+
+# if defined(__GNUC__) || defined(__clang__)
+# define INLINE_UNUSED __inline__ __attribute__((__unused__,__always_inline__))
+# define RESTRICT __restrict__
+# define ALIGNED __attribute__((__aligned__(16)))
+# else
+# define INLINE_UNUSED ossl_inline
+# define RESTRICT
+# define ALIGNED
+# endif
+
+typedef struct gf_s {
+ word_t limb[NLIMBS];
+} ALIGNED gf_s, gf[1];
+
+/* RFC 7748 support */
+# define X_PUBLIC_BYTES X_SER_BYTES
+# define X_PRIVATE_BYTES X_PUBLIC_BYTES
+# define X_PRIVATE_BITS 448
+
+static INLINE_UNUSED void gf_copy(gf out, const gf a)
+{
+ *out = *a;
+}
+
+static INLINE_UNUSED void gf_add_RAW(gf out, const gf a, const gf b);
+static INLINE_UNUSED void gf_sub_RAW(gf out, const gf a, const gf b);
+static INLINE_UNUSED void gf_bias(gf inout, int amount);
+static INLINE_UNUSED void gf_weak_reduce(gf inout);
+
+void gf_strong_reduce(gf inout);
+void gf_add(gf out, const gf a, const gf b);
+void gf_sub(gf out, const gf a, const gf b);
+void gf_mul(gf_s * RESTRICT out, const gf a, const gf b);
+void gf_mulw_unsigned(gf_s * RESTRICT out, const gf a, uint32_t b);
+void gf_sqr(gf_s * RESTRICT out, const gf a);
+mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */
+mask_t gf_eq(const gf x, const gf y);
+mask_t gf_lobit(const gf x);
+mask_t gf_hibit(const gf x);
+
+void gf_serialize(uint8_t *serial, const gf x, int with_highbit);
+mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit,
+ uint8_t hi_nmask);
+
+# include "f_impl.h" /* Bring in the inline implementations */
+
+# define LIMBPERM(i) (i)
+# define LIMB_MASK(i) (((1)<<LIMB_PLACE_VALUE(i))-1)
+
+static const gf ZERO = {{{0}}}, ONE = {{{1}}};
+
+/* Square x, n times. */
+static ossl_inline void gf_sqrn(gf_s * RESTRICT y, const gf x, int n)
+{
+ gf tmp;
+
+ assert(n > 0);
+ if (n & 1) {
+ gf_sqr(y, x);
+ n--;
+ } else {
+ gf_sqr(tmp, x);
+ gf_sqr(y, tmp);
+ n -= 2;
+ }
+ for (; n; n -= 2) {
+ gf_sqr(tmp, y);
+ gf_sqr(y, tmp);
+ }
+}
+
+# define gf_add_nr gf_add_RAW
+
+/* Subtract mod p. Bias by 2 and don't reduce */
+static ossl_inline void gf_sub_nr(gf c, const gf a, const gf b)
+{
+ gf_sub_RAW(c, a, b);
+ gf_bias(c, 2);
+ if (GF_HEADROOM < 3)
+ gf_weak_reduce(c);
+}
+
+/* Subtract mod p. Bias by amt but don't reduce. */
+static ossl_inline void gf_subx_nr(gf c, const gf a, const gf b, int amt)
+{
+ gf_sub_RAW(c, a, b);
+ gf_bias(c, amt);
+ if (GF_HEADROOM < amt + 1)
+ gf_weak_reduce(c);
+}
+
+/* Mul by signed int. Not constant-time WRT the sign of that int. */
+static ossl_inline void gf_mulw(gf c, const gf a, int32_t w)
+{
+ if (w > 0) {
+ gf_mulw_unsigned(c, a, w);
+ } else {
+ gf_mulw_unsigned(c, a, -w);
+ gf_sub(c, ZERO, c);
+ }
+}
+
+/* Constant time, x = is_z ? z : y */
+static ossl_inline void gf_cond_sel(gf x, const gf y, const gf z, mask_t is_z)
+{
+ size_t i;
+
+ for (i = 0; i < NLIMBS; i++) {
+#if ARCH_WORD_BITS == 32
+ x[0].limb[i] = constant_time_select_32(is_z, z[0].limb[i],
+ y[0].limb[i]);
+#else
+ /* Must be 64 bit */
+ x[0].limb[i] = constant_time_select_64(is_z, z[0].limb[i],
+ y[0].limb[i]);
+#endif
+ }
+}
+
+/* Constant time, if (neg) x=-x; */
+static ossl_inline void gf_cond_neg(gf x, mask_t neg)
+{
+ gf y;
+
+ gf_sub(y, ZERO, x);
+ gf_cond_sel(x, x, y, neg);
+}
+
+/* Constant time, if (swap) (x,y) = (y,x); */
+static ossl_inline void gf_cond_swap(gf x, gf_s * RESTRICT y, mask_t swap)
+{
+ size_t i;
+
+ for (i = 0; i < NLIMBS; i++) {
+#if ARCH_WORD_BITS == 32
+ constant_time_cond_swap_32(swap, &(x[0].limb[i]), &(y->limb[i]));
+#else
+ /* Must be 64 bit */
+ constant_time_cond_swap_64(swap, &(x[0].limb[i]), &(y->limb[i]));
+#endif
+ }
+}
+
+#endif /* HEADER_FIELD_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/point_448.h b/deps/openssl/openssl/crypto/ec/curve448/point_448.h
new file mode 100644
index 0000000000..0ef3b8714e
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/point_448.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_POINT_448_H
+# define HEADER_POINT_448_H
+
+# include "curve448utils.h"
+# include "field.h"
+
+/* Comb config: number of combs, n, t, s. */
+#define COMBS_N 5
+#define COMBS_T 5
+#define COMBS_S 18
+
+/* Projective Niels coordinates */
+typedef struct {
+ gf a, b, c;
+} niels_s, niels_t[1];
+typedef struct {
+ niels_t n;
+ gf z;
+} pniels_t[1];
+
+/* Precomputed base */
+struct curve448_precomputed_s {
+ niels_t table[COMBS_N << (COMBS_T - 1)];
+};
+
+# define C448_SCALAR_LIMBS ((446-1)/C448_WORD_BITS+1)
+
+/* The number of bits in a scalar */
+# define C448_SCALAR_BITS 446
+
+/* Number of bytes in a serialized scalar. */
+# define C448_SCALAR_BYTES 56
+
+/* X448 encoding ratio. */
+# define X448_ENCODE_RATIO 2
+
+/* Number of bytes in an x448 public key */
+# define X448_PUBLIC_BYTES 56
+
+/* Number of bytes in an x448 private key */
+# define X448_PRIVATE_BYTES 56
+
+/* Twisted Edwards extended homogeneous coordinates */
+typedef struct curve448_point_s {
+ gf x, y, z, t;
+} curve448_point_t[1];
+
+/* Precomputed table based on a point. Can be trivial implementation. */
+struct curve448_precomputed_s;
+
+/* Precomputed table based on a point. Can be trivial implementation. */
+typedef struct curve448_precomputed_s curve448_precomputed_s;
+
+/* Scalar is stored packed, because we don't need the speed. */
+typedef struct curve448_scalar_s {
+ c448_word_t limb[C448_SCALAR_LIMBS];
+} curve448_scalar_t[1];
+
+/* A scalar equal to 1. */
+extern const curve448_scalar_t curve448_scalar_one;
+
+/* A scalar equal to 0. */
+extern const curve448_scalar_t curve448_scalar_zero;
+
+/* The identity point on the curve. */
+extern const curve448_point_t curve448_point_identity;
+
+/* Precomputed table for the base point on the curve. */
+extern const struct curve448_precomputed_s *curve448_precomputed_base;
+extern const niels_t *curve448_wnaf_base;
+
+/*
+ * Read a scalar from wire format or from bytes.
+ *
+ * ser (in): Serialized form of a scalar.
+ * out (out): Deserialized form.
+ *
+ * Returns:
+ * C448_SUCCESS: The scalar was correctly encoded.
+ * C448_FAILURE: The scalar was greater than the modulus, and has been reduced
+ * modulo that modulus.
+ */
+c448_error_t curve448_scalar_decode(curve448_scalar_t out,
+ const unsigned char ser[C448_SCALAR_BYTES]);
+
+/*
+ * Read a scalar from wire format or from bytes. Reduces mod scalar prime.
+ *
+ * ser (in): Serialized form of a scalar.
+ * ser_len (in): Length of serialized form.
+ * out (out): Deserialized form.
+ */
+void curve448_scalar_decode_long(curve448_scalar_t out,
+ const unsigned char *ser, size_t ser_len);
+
+/*
+ * Serialize a scalar to wire format.
+ *
+ * ser (out): Serialized form of a scalar.
+ * s (in): Deserialized scalar.
+ */
+void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
+ const curve448_scalar_t s);
+
+/*
+ * Add two scalars. |a|, |b| and |out| may alias each other.
+ *
+ * a (in): One scalar.
+ * b (in): Another scalar.
+ * out (out): a+b.
+ */
+void curve448_scalar_add(curve448_scalar_t out,
+ const curve448_scalar_t a, const curve448_scalar_t b);
+
+/*
+ * Subtract two scalars. |a|, |b| and |out| may alias each other.
+ * a (in): One scalar.
+ * b (in): Another scalar.
+ * out (out): a-b.
+ */
+void curve448_scalar_sub(curve448_scalar_t out,
+ const curve448_scalar_t a, const curve448_scalar_t b);
+
+/*
+ * Multiply two scalars. |a|, |b| and |out| may alias each other.
+ *
+ * a (in): One scalar.
+ * b (in): Another scalar.
+ * out (out): a*b.
+ */
+void curve448_scalar_mul(curve448_scalar_t out,
+ const curve448_scalar_t a, const curve448_scalar_t b);
+
+/*
+* Halve a scalar. |a| and |out| may alias each other.
+*
+* a (in): A scalar.
+* out (out): a/2.
+*/
+void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a);
+
+/*
+ * Copy a scalar. The scalars may alias each other, in which case this
+ * function does nothing.
+ *
+ * a (in): A scalar.
+ * out (out): Will become a copy of a.
+ */
+static ossl_inline void curve448_scalar_copy(curve448_scalar_t out,
+ const curve448_scalar_t a)
+{
+ *out = *a;
+}
+
+/*
+ * Copy a point. The input and output may alias, in which case this function
+ * does nothing.
+ *
+ * a (out): A copy of the point.
+ * b (in): Any point.
+ */
+static ossl_inline void curve448_point_copy(curve448_point_t a,
+ const curve448_point_t b)
+{
+ *a = *b;
+}
+
+/*
+ * Test whether two points are equal. If yes, return C448_TRUE, else return
+ * C448_FALSE.
+ *
+ * a (in): A point.
+ * b (in): Another point.
+ *
+ * Returns:
+ * C448_TRUE: The points are equal.
+ * C448_FALSE: The points are not equal.
+ */
+__owur c448_bool_t curve448_point_eq(const curve448_point_t a,
+ const curve448_point_t b);
+
+/*
+ * Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially
+ * faster.
+ *
+ * two_a (out): The sum a+a.
+ * a (in): A point.
+ */
+void curve448_point_double(curve448_point_t two_a, const curve448_point_t a);
+
+/*
+ * RFC 7748 Diffie-Hellman scalarmul. This function uses a different
+ * (non-Decaf) encoding.
+ *
+ * out (out): The scaled point base*scalar
+ * base (in): The point to be scaled.
+ * scalar (in): The scalar to multiply by.
+ *
+ * Returns:
+ * C448_SUCCESS: The scalarmul succeeded.
+ * C448_FAILURE: The scalarmul didn't succeed, because the base point is in a
+ * small subgroup.
+ */
+__owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES],
+ const uint8_t base[X448_PUBLIC_BYTES],
+ const uint8_t scalar[X448_PRIVATE_BYTES]);
+
+/*
+ * Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748.
+ *
+ * This function is mainly used internally, but is exported in case
+ * it will be useful.
+ *
+ * The ratio is necessary because the internal representation doesn't
+ * track the cofactor information, so on output we must clear the cofactor.
+ * This would multiply by the cofactor, but in fact internally points are always
+ * even, so it multiplies by half the cofactor instead.
+ *
+ * As it happens, this aligns with the base point definitions; that is,
+ * if you pass the Decaf/Ristretto base point to this function, the result
+ * will be X448_ENCODE_RATIO times the X448
+ * base point.
+ *
+ * out (out): The scaled and encoded point.
+ * p (in): The point to be scaled and encoded.
+ */
+void curve448_point_mul_by_ratio_and_encode_like_x448(
+ uint8_t out[X448_PUBLIC_BYTES],
+ const curve448_point_t p);
+
+/*
+ * RFC 7748 Diffie-Hellman base point scalarmul. This function uses a different
+ * (non-Decaf) encoding.
+ *
+ * out (out): The scaled point base*scalar
+ * scalar (in): The scalar to multiply by.
+ */
+void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES],
+ const uint8_t scalar[X448_PRIVATE_BYTES]);
+
+/*
+ * Multiply a precomputed base point by a scalar: out = scalar*base.
+ *
+ * scaled (out): The scaled point base*scalar
+ * base (in): The point to be scaled.
+ * scalar (in): The scalar to multiply by.
+ */
+void curve448_precomputed_scalarmul(curve448_point_t scaled,
+ const curve448_precomputed_s * base,
+ const curve448_scalar_t scalar);
+
+/*
+ * Multiply two base points by two scalars:
+ * combo = scalar1*curve448_point_base + scalar2*base2.
+ *
+ * Otherwise equivalent to curve448_point_double_scalarmul, but may be
+ * faster at the expense of being variable time.
+ *
+ * combo (out): The linear combination scalar1*base + scalar2*base2.
+ * scalar1 (in): A first scalar to multiply by.
+ * base2 (in): A second point to be scaled.
+ * scalar2 (in) A second scalar to multiply by.
+ *
+ * Warning: This function takes variable time, and may leak the scalars used.
+ * It is designed for signature verification.
+ */
+void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
+ const curve448_scalar_t scalar1,
+ const curve448_point_t base2,
+ const curve448_scalar_t scalar2);
+
+/*
+ * Test that a point is valid, for debugging purposes.
+ *
+ * to_test (in): The point to test.
+ *
+ * Returns:
+ * C448_TRUE The point is valid.
+ * C448_FALSE The point is invalid.
+ */
+__owur c448_bool_t curve448_point_valid(const curve448_point_t to_test);
+
+/* Overwrite scalar with zeros. */
+void curve448_scalar_destroy(curve448_scalar_t scalar);
+
+/* Overwrite point with zeros. */
+void curve448_point_destroy(curve448_point_t point);
+
+#endif /* HEADER_POINT_448_H */
diff --git a/deps/openssl/openssl/crypto/ec/curve448/scalar.c b/deps/openssl/openssl/crypto/ec/curve448/scalar.c
new file mode 100644
index 0000000000..b5702c0255
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/scalar.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2016 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+#include <openssl/crypto.h>
+
+#include "word.h"
+#include "point_448.h"
+
+static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5;
+static const curve448_scalar_t sc_p = {
+ {
+ {
+ SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55),
+ SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9),
+ SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff),
+ SC_LIMB(0x3fffffffffffffff)
+ }
+ }
+}, sc_r2 = {
+ {
+ {
+
+ SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9),
+ SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838),
+ SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af),
+ SC_LIMB(0x3402a939f823b729)
+ }
+ }
+};
+
+#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
+
+const curve448_scalar_t curve448_scalar_one = {{{1}}};
+const curve448_scalar_t curve448_scalar_zero = {{{0}}};
+
+/*
+ * {extra,accum} - sub +? p
+ * Must have extra <= 1
+ */
+static void sc_subx(curve448_scalar_t out,
+ const c448_word_t accum[C448_SCALAR_LIMBS],
+ const curve448_scalar_t sub,
+ const curve448_scalar_t p, c448_word_t extra)
+{
+ c448_dsword_t chain = 0;
+ unsigned int i;
+ c448_word_t borrow;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ chain = (chain + accum[i]) - sub->limb[i];
+ out->limb[i] = (c448_word_t)chain;
+ chain >>= WBITS;
+ }
+ borrow = (c448_word_t)chain + extra; /* = 0 or -1 */
+
+ chain = 0;
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
+ out->limb[i] = (c448_word_t)chain;
+ chain >>= WBITS;
+ }
+}
+
+static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
+ const curve448_scalar_t b)
+{
+ unsigned int i, j;
+ c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 };
+ c448_word_t hi_carry = 0;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ c448_word_t mand = a->limb[i];
+ const c448_word_t *mier = b->limb;
+
+ c448_dword_t chain = 0;
+ for (j = 0; j < C448_SCALAR_LIMBS; j++) {
+ chain += ((c448_dword_t) mand) * mier[j] + accum[j];
+ accum[j] = (c448_word_t)chain;
+ chain >>= WBITS;
+ }
+ accum[j] = (c448_word_t)chain;
+
+ mand = accum[0] * MONTGOMERY_FACTOR;
+ chain = 0;
+ mier = sc_p->limb;
+ for (j = 0; j < C448_SCALAR_LIMBS; j++) {
+ chain += (c448_dword_t) mand *mier[j] + accum[j];
+ if (j)
+ accum[j - 1] = (c448_word_t)chain;
+ chain >>= WBITS;
+ }
+ chain += accum[j];
+ chain += hi_carry;
+ accum[j - 1] = (c448_word_t)chain;
+ hi_carry = chain >> WBITS;
+ }
+
+ sc_subx(out, accum, sc_p, sc_p, hi_carry);
+}
+
+void curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
+ const curve448_scalar_t b)
+{
+ sc_montmul(out, a, b);
+ sc_montmul(out, out, sc_r2);
+}
+
+void curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
+ const curve448_scalar_t b)
+{
+ sc_subx(out, a->limb, b, sc_p, 0);
+}
+
+void curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
+ const curve448_scalar_t b)
+{
+ c448_dword_t chain = 0;
+ unsigned int i;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ chain = (chain + a->limb[i]) + b->limb[i];
+ out->limb[i] = (c448_word_t)chain;
+ chain >>= WBITS;
+ }
+ sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain);
+}
+
+static ossl_inline void scalar_decode_short(curve448_scalar_t s,
+ const unsigned char *ser,
+ size_t nbytes)
+{
+ size_t i, j, k = 0;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ c448_word_t out = 0;
+
+ for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++)
+ out |= ((c448_word_t) ser[k]) << (8 * j);
+ s->limb[i] = out;
+ }
+}
+
+c448_error_t curve448_scalar_decode(
+ curve448_scalar_t s,
+ const unsigned char ser[C448_SCALAR_BYTES])
+{
+ unsigned int i;
+ c448_dsword_t accum = 0;
+
+ scalar_decode_short(s, ser, C448_SCALAR_BYTES);
+ for (i = 0; i < C448_SCALAR_LIMBS; i++)
+ accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
+ /* Here accum == 0 or -1 */
+
+ curve448_scalar_mul(s, s, curve448_scalar_one); /* ham-handed reduce */
+
+ return c448_succeed_if(~word_is_zero((uint32_t)accum));
+}
+
+void curve448_scalar_destroy(curve448_scalar_t scalar)
+{
+ OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
+}
+
+void curve448_scalar_decode_long(curve448_scalar_t s,
+ const unsigned char *ser, size_t ser_len)
+{
+ size_t i;
+ curve448_scalar_t t1, t2;
+
+ if (ser_len == 0) {
+ curve448_scalar_copy(s, curve448_scalar_zero);
+ return;
+ }
+
+ i = ser_len - (ser_len % C448_SCALAR_BYTES);
+ if (i == ser_len)
+ i -= C448_SCALAR_BYTES;
+
+ scalar_decode_short(t1, &ser[i], ser_len - i);
+
+ if (ser_len == sizeof(curve448_scalar_t)) {
+ assert(i == 0);
+ /* ham-handed reduce */
+ curve448_scalar_mul(s, t1, curve448_scalar_one);
+ curve448_scalar_destroy(t1);
+ return;
+ }
+
+ while (i) {
+ i -= C448_SCALAR_BYTES;
+ sc_montmul(t1, t1, sc_r2);
+ (void)curve448_scalar_decode(t2, ser + i);
+ curve448_scalar_add(t1, t1, t2);
+ }
+
+ curve448_scalar_copy(s, t1);
+ curve448_scalar_destroy(t1);
+ curve448_scalar_destroy(t2);
+}
+
+void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
+ const curve448_scalar_t s)
+{
+ unsigned int i, j, k = 0;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ for (j = 0; j < sizeof(c448_word_t); j++, k++)
+ ser[k] = s->limb[i] >> (8 * j);
+ }
+}
+
+void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a)
+{
+ c448_word_t mask = 0 - (a->limb[0] & 1);
+ c448_dword_t chain = 0;
+ unsigned int i;
+
+ for (i = 0; i < C448_SCALAR_LIMBS; i++) {
+ chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
+ out->limb[i] = (c448_word_t)chain;
+ chain >>= C448_WORD_BITS;
+ }
+ for (i = 0; i < C448_SCALAR_LIMBS - 1; i++)
+ out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1);
+ out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1));
+}
diff --git a/deps/openssl/openssl/crypto/ec/curve448/word.h b/deps/openssl/openssl/crypto/ec/curve448/word.h
new file mode 100644
index 0000000000..a48b9e053a
--- /dev/null
+++ b/deps/openssl/openssl/crypto/ec/curve448/word.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014 Cryptography Research, Inc.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ *
+ * Originally written by Mike Hamburg
+ */
+
+#ifndef HEADER_WORD_H
+# define HEADER_WORD_H
+
+# include <string.h>
+# include <assert.h>
+# include <stdlib.h>
+# include <openssl/e_os2.h>
+# include "arch_intrinsics.h"
+# include "curve448utils.h"
+
+# if (ARCH_WORD_BITS == 64)
+typedef uint64_t word_t, mask_t;
+typedef __uint128_t dword_t;
+typedef int32_t hsword_t;
+typedef int64_t sword_t;
+typedef __int128_t dsword_t;
+# elif (ARCH_WORD_BITS == 32)
+typedef uint32_t word_t, mask_t;
+typedef uint64_t dword_t;
+typedef int16_t hsword_t;
+typedef int32_t sword_t;
+typedef int64_t dsword_t;
+# else
+# error "For now, we only support 32- and 64-bit architectures."
+# endif
+
+/*
+ * Scalar limbs are keyed off of the API word size instead of the arch word
+ * size.
+ */
+# if C448_WORD_BITS == 64
+# define SC_LIMB(x) (x)
+# elif C448_WORD_BITS == 32
+# define SC_LIMB(x) ((uint32_t)(x)),((x) >> 32)
+# else
+# error "For now we only support 32- and 64-bit architectures."
+# endif
+
+/*
+ * The plan on booleans: The external interface uses c448_bool_t, but this
+ * might be a different size than our particular arch's word_t (and thus
+ * mask_t). Also, the caller isn't guaranteed to pass it as nonzero. So
+ * bool_to_mask converts word sizes and checks nonzero. On the flip side,
+ * mask_t is always -1 or 0, but it might be a different size than
+ * c448_bool_t. On the third hand, we have success vs boolean types, but
+ * that's handled in common.h: it converts between c448_bool_t and
+ * c448_error_t.
+ */
+static ossl_inline c448_bool_t mask_to_bool(mask_t m)
+{
+ return (c448_sword_t)(sword_t)m;
+}
+
+static ossl_inline mask_t bool_to_mask(c448_bool_t m)
+{
+ /* On most arches this will be optimized to a simple cast. */
+ mask_t ret = 0;
+ unsigned int i;
+ unsigned int limit = sizeof(c448_bool_t) / sizeof(mask_t);
+
+ if (limit < 1)
+ limit = 1;
+ for (i = 0; i < limit; i++)
+ ret |= ~word_is_zero(m >> (i * 8 * sizeof(word_t)));
+
+ return ret;
+}
+
+#endif /* HEADER_WORD_H */
diff --git a/deps/openssl/openssl/crypto/ec/ec2_mult.c b/deps/openssl/openssl/crypto/ec/ec2_mult.c
deleted file mode 100644
index e4a1ec5737..0000000000
--- a/deps/openssl/openssl/crypto/ec/ec2_mult.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
- * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
- * to the OpenSSL project.
- *
- * The ECC Code is licensed pursuant to the OpenSSL open source
- * license provided below.
- *
- * The software is originally written by Sheueling Chang Shantz and
- * Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
-#include <openssl/err.h>
-
-#include "internal/bn_int.h"
-#include "ec_lcl.h"
-
-#ifndef OPENSSL_NO_EC2M
-
-/*-
- * Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
- * coordinates.
- * Uses algorithm Mdouble in appendix of
- * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
- * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- * modified to not require precomputation of c=b^{2^{m-1}}.
- */
-static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z,
- BN_CTX *ctx)
-{
- BIGNUM *t1;
- int ret = 0;
-
- /* Since Mdouble is static we can guarantee that ctx != NULL. */
- BN_CTX_start(ctx);
- t1 = BN_CTX_get(ctx);
- if (t1 == NULL)
- goto err;
-
- if (!group->meth->field_sqr(group, x, x, ctx))
- goto err;
- if (!group->meth->field_sqr(group, t1, z, ctx))
- goto err;
- if (!group->meth->field_mul(group, z, x, t1, ctx))
- goto err;
- if (!group->meth->field_sqr(group, x, x, ctx))
- goto err;
- if (!group->meth->field_sqr(group, t1, t1, ctx))
- goto err;
- if (!group->meth->field_mul(group, t1, group->b, t1, ctx))
- goto err;
- if (!BN_GF2m_add(x, x, t1))
- goto err;
-
- ret = 1;
-
- err:
- BN_CTX_end(ctx);
- return ret;
-}
-
-/*-
- * Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
- * projective coordinates.
- * Uses algorithm Madd in appendix of
- * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
- * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- */
-static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,
- BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,
- BN_CTX *ctx)
-{
- BIGNUM *t1, *t2;
- int ret = 0;
-
- /* Since Madd is static we can guarantee that ctx != NULL. */
- BN_CTX_start(ctx);
- t1 = BN_CTX_get(ctx);
- t2 = BN_CTX_get(ctx);
- if (t2 == NULL)
- goto err;
-
- if (!BN_copy(t1, x))
- goto err;
- if (!group->meth->field_mul(group, x1, x1, z2, ctx))
- goto err;
- if (!group->meth->field_mul(group, z1, z1, x2, ctx))
- goto err;
- if (!group->meth->field_mul(group, t2, x1, z1, ctx))
- goto err;
- if (!BN_GF2m_add(z1, z1, x1))
- goto err;
- if (!group->meth->field_sqr(group, z1, z1, ctx))
- goto err;
- if (!group->meth->field_mul(group, x1, z1, t1, ctx))
- goto err;
- if (!BN_GF2m_add(x1, x1, t2))
- goto err;
-
- ret = 1;
-
- err:
- BN_CTX_end(ctx);
- return ret;
-}
-
-/*-
- * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
- * using Montgomery point multiplication algorithm Mxy() in appendix of
- * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
- * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- * Returns:
- * 0 on error
- * 1 if return value should be the point at infinity
- * 2 otherwise
- */
-static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
- BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
- BN_CTX *ctx)
-{
- BIGNUM *t3, *t4, *t5;
- int ret = 0;
-
- if (BN_is_zero(z1)) {
- BN_zero(x2);
- BN_zero(z2);
- return 1;
- }
-
- if (BN_is_zero(z2)) {
- if (!BN_copy(x2, x))
- return 0;
- if (!BN_GF2m_add(z2, x, y))
- return 0;
- return 2;
- }
-
- /* Since Mxy is static we can guarantee that ctx != NULL. */
- BN_CTX_start(ctx);
- t3 = BN_CTX_get(ctx);
- t4 = BN_CTX_get(ctx);
- t5 = BN_CTX_get(ctx);
- if (t5 == NULL)
- goto err;
-
- if (!BN_one(t5))
- goto err;
-
- if (!group->meth->field_mul(group, t3, z1, z2, ctx))
- goto err;
-
- if (!group->meth->field_mul(group, z1, z1, x, ctx))
- goto err;
- if (!BN_GF2m_add(z1, z1, x1))
- goto err;
- if (!group->meth->field_mul(group, z2, z2, x, ctx))
- goto err;
- if (!group->meth->field_mul(group, x1, z2, x1, ctx))
- goto err;
- if (!BN_GF2m_add(z2, z2, x2))
- goto err;
-
- if (!group->meth->field_mul(group, z2, z2, z1, ctx))
- goto err;
- if (!group->meth->field_sqr(group, t4, x, ctx))
- goto err;
- if (!BN_GF2m_add(t4, t4, y))
- goto err;
- if (!group->meth->field_mul(group, t4, t4, t3, ctx))
- goto err;
- if (!BN_GF2m_add(t4, t4, z2))
- goto err;
-
- if (!group->meth->field_mul(group, t3, t3, x, ctx))
- goto err;
- if (!group->meth->field_div(group, t3, t5, t3, ctx))
- goto err;
- if (!group->meth->field_mul(group, t4, t3, t4, ctx))
- goto err;
- if (!group->meth->field_mul(group, x2, x1, t3, ctx))
- goto err;
- if (!BN_GF2m_add(z2, x2, x))
- goto err;
-
- if (!group->meth->field_mul(group, z2, z2, t4, ctx))
- goto err;
- if (!BN_GF2m_add(z2, z2, y))
- goto err;
-
- ret = 2;
-
- err:
- BN_CTX_end(ctx);
- return ret;
-}
-
-/*-
- * Computes scalar*point and stores the result in r.
- * point can not equal r.
- * Uses a modified algorithm 2P of
- * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
- * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- *
- * To protect against side-channel attack the function uses constant time swap,
- * avoiding conditional branches.
- */
-static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,
- EC_POINT *r,
- const BIGNUM *scalar,
- const EC_POINT *point,
- BN_CTX *ctx)
-{
- BIGNUM *x1, *x2, *z1, *z2;
- int ret = 0, i, group_top;
- BN_ULONG mask, word;
-
- if (r == point) {
- ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
- return 0;
- }
-
- /* if result should be point at infinity */
- if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
- EC_POINT_is_at_infinity(group, point)) {
- return EC_POINT_set_to_infinity(group, r);
- }
-
- /* only support affine coordinates */
- if (!point->Z_is_one)
- return 0;
-
- /*
- * Since point_multiply is static we can guarantee that ctx != NULL.
- */
- BN_CTX_start(ctx);
- x1 = BN_CTX_get(ctx);
- z1 = BN_CTX_get(ctx);
- if (z1 == NULL)
- goto err;
-
- x2 = r->X;
- z2 = r->Y;
-
- group_top = bn_get_top(group->field);
- if (bn_wexpand(x1, group_top) == NULL
- || bn_wexpand(z1, group_top) == NULL
- || bn_wexpand(x2, group_top) == NULL
- || bn_wexpand(z2, group_top) == NULL)
- goto err;
-
- if (!BN_GF2m_mod_arr(x1, point->X, group->poly))
- goto err; /* x1 = x */
- if (!BN_one(z1))
- goto err; /* z1 = 1 */
- if (!group->meth->field_sqr(group, z2, x1, ctx))
- goto err; /* z2 = x1^2 = x^2 */
- if (!group->meth->field_sqr(group, x2, z2, ctx))
- goto err;
- if (!BN_GF2m_add(x2, x2, group->b))
- goto err; /* x2 = x^4 + b */
-
- /* find top most bit and go one past it */
- i = bn_get_top(scalar) - 1;
- mask = BN_TBIT;
- word = bn_get_words(scalar)[i];
- while (!(word & mask))
- mask >>= 1;
- mask >>= 1;
- /* if top most bit was at word break, go to next word */
- if (!mask) {
- i--;
- mask = BN_TBIT;
- }
-
- for (; i >= 0; i--) {
- word = bn_get_words(scalar)[i];
- while (mask) {
- BN_consttime_swap(word & mask, x1, x2, group_top);
- BN_consttime_swap(word & mask, z1, z2, group_top);
- if (!gf2m_Madd(group, point->X, x2, z2, x1, z1, ctx))
- goto err;
- if (!gf2m_Mdouble(group, x1, z1, ctx))
- goto err;
- BN_consttime_swap(word & mask, x1, x2, group_top);
- BN_consttime_swap(word & mask, z1, z2, group_top);
- mask >>= 1;
- }
- mask = BN_TBIT;
- }
-
- /* convert out of "projective" coordinates */
- i = gf2m_Mxy(group, point->X, point->Y, x1, z1, x2, z2, ctx);
- if (i == 0)
- goto err;
- else if (i == 1) {
- if (!EC_POINT_set_to_infinity(group, r))
- goto err;
- } else {
- if (!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;
-}
-
-/*-
- * Computes the sum
- * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
- * gracefully ignoring NULL scalar values.
- */
-int ec_GF2m_simple_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;
- int ret = 0;
- size_t i;
- EC_POINT *p = NULL;
- EC_POINT *acc = NULL;
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL)
- return 0;
- }
-
- /*
- * This implementation is more efficient than the wNAF implementation for
- * 2 or fewer points. Use the ec_wNAF_mul implementation for 3 or more
- * points, or if we can perform a fast multiplication based on
- * precomputation.
- */
- if ((scalar && (num > 1)) || (num > 2)
- || (num == 0 && EC_GROUP_have_precompute_mult(group))) {
- ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
- goto err;
- }
-
- if ((p = EC_POINT_new(group)) == NULL)
- goto err;
- if ((acc = EC_POINT_new(group)) == NULL)
- goto err;
-
- if (!EC_POINT_set_to_infinity(group, acc))
- goto err;
-
- if (scalar) {
- if (!ec_GF2m_montgomery_point_multiply
- (group, p, scalar, group->generator, ctx))
- goto err;
- if (BN_is_negative(scalar))
- if (!group->meth->invert(group, p, ctx))
- goto err;
- if (!group->meth->add(group, acc, acc, p, ctx))
- goto err;
- }
-
- for (i = 0; i < num; i++) {
- if (!ec_GF2m_montgomery_point_multiply
- (group, p, scalars[i], points[i], ctx))
- goto err;
- if (BN_is_negative(scalars[i]))
- if (!group->meth->invert(group, p, ctx))
- goto err;
- if (!group->meth->add(group, acc, acc, p, ctx))
- goto err;
- }
-
- if (!EC_POINT_copy(r, acc))
- goto err;
-
- ret = 1;
-
- err:
- EC_POINT_free(p);
- EC_POINT_free(acc);
- BN_CTX_free(new_ctx);
- return ret;
-}
-
-/*
- * Precomputation for point multiplication: fall back to wNAF methods because
- * ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate
- */
-
-int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
-{
- return ec_wNAF_precompute_mult(group, ctx);
-}
-
-int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
-{
- return ec_wNAF_have_precompute_mult(group);
-}
-
-#endif
diff --git a/deps/openssl/openssl/crypto/ec/ec2_oct.c b/deps/openssl/openssl/crypto/ec/ec2_oct.c
index ea88ce860a..0867f994ea 100644
--- a/deps/openssl/openssl/crypto/ec/ec2_oct.c
+++ b/deps/openssl/openssl/crypto/ec/ec2_oct.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,21 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
- * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
- * to the OpenSSL project.
- *
- * The ECC Code is licensed pursuant to the OpenSSL open source
- * license provided below.
- *
- * The software is originally written by Sheueling Chang Shantz and
- * Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
#include <openssl/err.h>
#include "ec_lcl.h"
@@ -108,7 +94,7 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
}
}
- if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
ret = 1;
@@ -180,7 +166,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
if (yxi == NULL)
goto err;
- if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
buf[0] = form;
@@ -315,8 +301,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
}
if (form == POINT_CONVERSION_COMPRESSED) {
- if (!EC_POINT_set_compressed_coordinates_GF2m
- (group, point, x, y_bit, ctx))
+ if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx))
goto err;
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
@@ -335,10 +320,10 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
}
/*
- * EC_POINT_set_affine_coordinates_GF2m is responsible for checking that
+ * EC_POINT_set_affine_coordinates is responsible for checking that
* the point is on the curve.
*/
- if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
}
diff --git a/deps/openssl/openssl/crypto/ec/ec2_smpl.c b/deps/openssl/openssl/crypto/ec/ec2_smpl.c
index cdacce61ac..87f7ce5691 100644
--- a/deps/openssl/openssl/crypto/ec/ec2_smpl.c
+++ b/deps/openssl/openssl/crypto/ec/ec2_smpl.c
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,21 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
- * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
- * to the OpenSSL project.
- *
- * The ECC Code is licensed pursuant to the OpenSSL open source
- * license provided below.
- *
- * The software is originally written by Sheueling Chang Shantz and
- * Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
#include <openssl/err.h>
#include "internal/bn_int.h"
@@ -29,67 +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,
-
- /*
- * the following three method functions are defined in ec2_mult.c
- */
- ec_GF2m_simple_mul,
- ec_GF2m_precompute_mult,
- ec_GF2m_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 /* blind_coordinates */
- };
-
- return &ret;
-}
-
/*
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
* are handled by EC_GROUP_new.
@@ -465,7 +390,7 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (!BN_copy(y0, a->Y))
goto err;
} else {
- if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx))
goto err;
}
if (b->Z_is_one) {
@@ -474,7 +399,7 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (!BN_copy(y1, b->Y))
goto err;
} else {
- if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx))
goto err;
}
@@ -522,7 +447,7 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
if (!BN_GF2m_add(y2, y2, y1))
goto err;
- if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx))
goto err;
ret = 1;
@@ -619,9 +544,9 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
if (!BN_GF2m_add(lh, lh, y2))
goto err;
ret = BN_is_zero(lh);
+
err:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -665,15 +590,14 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
if (bY == NULL)
goto err;
- if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx))
goto err;
- if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx))
goto err;
ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
err:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -701,7 +625,7 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
if (y == NULL)
goto err;
- if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!BN_copy(point->X, x))
goto err;
@@ -714,8 +638,7 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
ret = 1;
err:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -757,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
diff --git a/deps/openssl/openssl/crypto/ec/ec_ameth.c b/deps/openssl/openssl/crypto/ec/ec_ameth.c
index f8f1e2c842..a3164b5b2e 100644
--- a/deps/openssl/openssl/crypto/ec/ec_ameth.c
+++ b/deps/openssl/openssl/crypto/ec/ec_ameth.c
@@ -521,6 +521,48 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
}
+static int ec_pkey_check(const EVP_PKEY *pkey)
+{
+ EC_KEY *eckey = pkey->pkey.ec;
+
+ /* stay consistent to what EVP_PKEY_check demands */
+ if (eckey->priv_key == NULL) {
+ ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY);
+ return 0;
+ }
+
+ return EC_KEY_check_key(eckey);
+}
+
+static int ec_pkey_public_check(const EVP_PKEY *pkey)
+{
+ EC_KEY *eckey = pkey->pkey.ec;
+
+ /*
+ * Note: it unnecessary to check eckey->pub_key here since
+ * it will be checked in EC_KEY_check_key(). In fact, the
+ * EC_KEY_check_key() mainly checks the public key, and checks
+ * the private key optionally (only if there is one). So if
+ * someone passes a whole EC key (public + private), this
+ * will also work...
+ */
+
+ return EC_KEY_check_key(eckey);
+}
+
+static int ec_pkey_param_check(const EVP_PKEY *pkey)
+{
+ EC_KEY *eckey = pkey->pkey.ec;
+
+ /* stay consistent to what EVP_PKEY_check demands */
+ if (eckey->group == NULL) {
+ ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS);
+ return 0;
+ }
+
+ return EC_GROUP_check(eckey->group, NULL);
+}
+
const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
EVP_PKEY_EC,
EVP_PKEY_EC,
@@ -552,9 +594,23 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
int_ec_free,
ec_pkey_ctrl,
old_ec_priv_decode,
- old_ec_priv_encode
+ old_ec_priv_encode,
+
+ 0, 0, 0,
+
+ ec_pkey_check,
+ ec_pkey_public_check,
+ ec_pkey_param_check
};
+#if !defined(OPENSSL_NO_SM2)
+const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = {
+ EVP_PKEY_SM2,
+ EVP_PKEY_EC,
+ ASN1_PKEY_ALIAS
+};
+#endif
+
int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
{
int private = EC_KEY_get0_private_key(x) != NULL;
@@ -643,7 +699,7 @@ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
return 0;
- if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0)
+ if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
return 0;
kdf_md = EVP_get_digestbynid(kdfmd_nid);
@@ -808,7 +864,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
ecdh_nid = NID_dh_cofactor_kdf;
if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
- kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
+ kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
goto err;
} else
diff --git a/deps/openssl/openssl/crypto/ec/ec_asn1.c b/deps/openssl/openssl/crypto/ec/ec_asn1.c
index 271178f82e..13c56a621d 100644
--- a/deps/openssl/openssl/crypto/ec/ec_asn1.c
+++ b/deps/openssl/openssl/crypto/ec/ec_asn1.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -12,6 +12,7 @@
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
+#include "internal/nelem.h"
int EC_GROUP_get_basis_type(const EC_GROUP *group)
{
@@ -87,13 +88,13 @@ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
/* some structures needed for the asn1 encoding */
typedef struct x9_62_pentanomial_st {
- long k1;
- long k2;
- long k3;
+ int32_t k1;
+ int32_t k2;
+ int32_t k3;
} X9_62_PENTANOMIAL;
typedef struct x9_62_characteristic_two_st {
- long m;
+ int32_t m;
ASN1_OBJECT *type;
union {
char *ptr;
@@ -128,7 +129,7 @@ typedef struct x9_62_curve_st {
} X9_62_CURVE;
struct ec_parameters_st {
- long version;
+ int32_t version;
X9_62_FIELDID *fieldID;
X9_62_CURVE *curve;
ASN1_OCTET_STRING *base;
@@ -147,7 +148,7 @@ struct ecpk_parameters_st {
/* SEC1 ECPrivateKey */
typedef struct ec_privatekey_st {
- long version;
+ int32_t version;
ASN1_OCTET_STRING *privateKey;
ECPKPARAMETERS *parameters;
ASN1_BIT_STRING *publicKey;
@@ -155,9 +156,9 @@ typedef struct ec_privatekey_st {
/* the OpenSSL ASN.1 definitions */
ASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
+ ASN1_EMBED(X9_62_PENTANOMIAL, k1, INT32),
+ ASN1_EMBED(X9_62_PENTANOMIAL, k2, INT32),
+ ASN1_EMBED(X9_62_PENTANOMIAL, k3, INT32)
} static_ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
@@ -172,7 +173,7 @@ ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
- ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
+ ASN1_EMBED(X9_62_CHARACTERISTIC_TWO, m, INT32),
ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
} static_ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
@@ -199,7 +200,7 @@ ASN1_SEQUENCE(X9_62_CURVE) = {
} static_ASN1_SEQUENCE_END(X9_62_CURVE)
ASN1_SEQUENCE(ECPARAMETERS) = {
- ASN1_SIMPLE(ECPARAMETERS, version, LONG),
+ ASN1_EMBED(ECPARAMETERS, version, INT32),
ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
@@ -221,7 +222,7 @@ DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
ASN1_SEQUENCE(EC_PRIVATEKEY) = {
- ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
+ ASN1_EMBED(EC_PRIVATEKEY, version, INT32),
ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
@@ -265,7 +266,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
goto err;
}
/* the parameters are specified by the prime number p */
- if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) {
+ if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) {
ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
goto err;
}
@@ -359,17 +360,15 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
err:
BN_free(tmp);
- return (ok);
+ return ok;
}
static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
{
- int ok = 0, nid;
+ int ok = 0;
BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
- unsigned char *buffer_1 = NULL, *buffer_2 = NULL,
- *a_buf = NULL, *b_buf = NULL;
- size_t len_1, len_2;
- unsigned char char_zero = 0;
+ unsigned char *a_buf = NULL, *b_buf = NULL;
+ size_t len;
if (!group || !curve || !curve->a || !curve->b)
return 0;
@@ -379,62 +378,32 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
goto err;
}
- nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
-
/* get a and b */
- if (nid == NID_X9_62_prime_field) {
- if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
- goto err;
- }
- }
-#ifndef OPENSSL_NO_EC2M
- else { /* nid == NID_X9_62_characteristic_two_field */
-
- if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
- goto err;
- }
+ if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
+ goto err;
}
-#endif
- len_1 = (size_t)BN_num_bytes(tmp_1);
- len_2 = (size_t)BN_num_bytes(tmp_2);
- if (len_1 == 0) {
- /* len_1 == 0 => a == 0 */
- a_buf = &char_zero;
- len_1 = 1;
- } else {
- if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
- goto err;
- }
- a_buf = buffer_1;
+ /*
+ * Per SEC 1, the curve coefficients must be padded up to size. See C.2's
+ * definition of Curve, C.1's definition of FieldElement, and 2.3.5's
+ * definition of how to encode the field elements.
+ */
+ len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8;
+ if ((a_buf = OPENSSL_malloc(len)) == NULL
+ || (b_buf = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ goto err;
}
-
- if (len_2 == 0) {
- /* len_2 == 0 => b == 0 */
- b_buf = &char_zero;
- len_2 = 1;
- } else {
- if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
- goto err;
- }
- b_buf = buffer_2;
+ if (BN_bn2binpad(tmp_1, a_buf, len) < 0
+ || BN_bn2binpad(tmp_2, b_buf, len) < 0) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+ goto err;
}
/* set a and b */
- if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
- !ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
+ if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len)
+ || !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) {
ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
goto err;
}
@@ -461,11 +430,11 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
ok = 1;
err:
- OPENSSL_free(buffer_1);
- OPENSSL_free(buffer_2);
+ OPENSSL_free(a_buf);
+ OPENSSL_free(b_buf);
BN_free(tmp_1);
BN_free(tmp_2);
- return (ok);
+ return ok;
}
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
@@ -571,7 +540,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group,
if (EC_GROUP_get_asn1_flag(group)) {
/*
- * use the asn1 OID to describe the the elliptic curve parameters
+ * use the asn1 OID to describe the elliptic curve parameters
*/
tmp = EC_GROUP_get_curve_name(group);
if (tmp) {
@@ -610,7 +579,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
goto err;
}
- /* now extract the curve parameters a and b */
+ /*
+ * Now extract the curve parameters a and b. Note that, although SEC 1
+ * specifies the length of their encodings, historical versions of OpenSSL
+ * encoded them incorrectly, so we must accept any length for backwards
+ * compatibility.
+ */
if (!params->curve || !params->curve->a ||
!params->curve->a->data || !params->curve->b ||
!params->curve->b->data) {
@@ -827,7 +801,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params)
BN_free(a);
BN_free(b);
EC_POINT_free(point);
- return (ret);
+ return ret;
}
EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
@@ -855,7 +829,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB);
return NULL;
}
- EC_GROUP_set_asn1_flag(ret, 0x0);
+ EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE);
} else if (params->type == 2) { /* implicitlyCA */
return NULL;
} else {
@@ -893,7 +867,7 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
ECPKPARAMETERS_free(params);
*in = p;
- return (group);
+ return group;
}
int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
@@ -910,7 +884,7 @@ int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
return 0;
}
ECPKPARAMETERS_free(tmp);
- return (ret);
+ return ret;
}
/* some EC_KEY functions */
@@ -985,7 +959,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
*a = ret;
EC_PRIVATEKEY_free(priv_key);
*in = p;
- return (ret);
+ return ret;
err:
if (a == NULL || *a != ret)
@@ -1197,6 +1171,16 @@ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
*ps = sig->s;
}
+const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig)
+{
+ return sig->r;
+}
+
+const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig)
+{
+ return sig->s;
+}
+
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
@@ -1233,5 +1217,5 @@ int ECDSA_size(const EC_KEY *r)
i = i2d_ASN1_INTEGER(&bs, NULL);
i += i; /* r and s */
ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
- return (ret);
+ return ret;
}
diff --git a/deps/openssl/openssl/crypto/ec/ec_curve.c b/deps/openssl/openssl/crypto/ec/ec_curve.c
index b022528be2..bb1ce196d0 100644
--- a/deps/openssl/openssl/crypto/ec/ec_curve.c
+++ b/deps/openssl/openssl/crypto/ec/ec_curve.c
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,26 +8,12 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * The elliptic curve binary polynomial software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
#include <string.h>
#include "ec_lcl.h"
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#include <openssl/opensslconf.h>
-#include "e_os.h"
+#include "internal/nelem.h"
typedef struct {
int field_type, /* either NID_X9_62_prime_field or
@@ -2217,7 +2204,7 @@ static const struct {
#endif
/*
- * These curves were added by Annie Yousar <a.yousar@informatik.hu-berlin.de>
+ * These curves were added by Annie Yousar.
* For the definition of RFC 5639 curves see
* http://www.ietf.org/rfc/rfc5639.txt These curves are generated verifiable
* at random, nevertheless the seed is omitted as parameter because the
@@ -2764,6 +2751,45 @@ static const struct {
}
};
+#ifndef OPENSSL_NO_SM2
+static const struct {
+ EC_CURVE_DATA h;
+ unsigned char data[0 + 32 * 6];
+} _EC_sm2p256v1 = {
+ {
+ NID_X9_62_prime_field, 0, 32, 1
+ },
+ {
+ /* no seed */
+
+ /* p */
+ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* a */
+ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ /* b */
+ 0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b,
+ 0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92,
+ 0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93,
+ /* x */
+ 0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46,
+ 0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1,
+ 0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7,
+ /* y */
+ 0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3,
+ 0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40,
+ 0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0,
+ /* order */
+ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b,
+ 0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23,
+ }
+};
+#endif /* OPENSSL_NO_SM2 */
+
typedef struct _ec_list_element_st {
int nid;
const EC_CURVE_DATA *data;
@@ -2973,6 +2999,10 @@ static const ec_list_element curve_list[] = {
"RFC 5639 curve over a 512 bit prime field"},
{NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
"RFC 5639 curve over a 512 bit prime field"},
+#ifndef OPENSSL_NO_SM2
+ {NID_sm2, &_EC_sm2p256v1.h, 0,
+ "SM2 curve over a 256 bit prime field"},
+#endif
};
#define curve_list_length OSSL_NELEM(curve_list)
@@ -3048,7 +3078,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
goto err;
}
- if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
+ if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) {
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
goto err;
}
diff --git a/deps/openssl/openssl/crypto/ec/ec_cvt.c b/deps/openssl/openssl/crypto/ec/ec_cvt.c
index bfff6d65f7..0ec346c125 100644
--- a/deps/openssl/openssl/crypto/ec/ec_cvt.c
+++ b/deps/openssl/openssl/crypto/ec/ec_cvt.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,20 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * The elliptic curve binary polynomial software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
#include <openssl/err.h>
#include "ec_lcl.h"
@@ -64,7 +51,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
if (ret == NULL)
return NULL;
- if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) {
+ if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
EC_GROUP_clear_free(ret);
return NULL;
}
@@ -85,7 +72,7 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
if (ret == NULL)
return NULL;
- if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx)) {
+ if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
EC_GROUP_clear_free(ret);
return NULL;
}
diff --git a/deps/openssl/openssl/crypto/ec/ec_err.c b/deps/openssl/openssl/crypto/ec/ec_err.c
index 717c92e984..8f4911abec 100644
--- a/deps/openssl/openssl/crypto/ec/ec_err.c
+++ b/deps/openssl/openssl/crypto/ec/ec_err.c
@@ -8,272 +8,368 @@
* https://www.openssl.org/source/license.html
*/
-#include <stdio.h>
#include <openssl/err.h>
-#include <openssl/ec.h>
+#include <openssl/ecerr.h>
-/* BEGIN ERROR CODES */
#ifndef OPENSSL_NO_ERR
-# define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0)
-# define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason)
-
-static ERR_STRING_DATA EC_str_functs[] = {
- {ERR_FUNC(EC_F_BN_TO_FELEM), "BN_to_felem"},
- {ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"},
- {ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"},
- {ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"},
- {ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "do_EC_KEY_print"},
- {ERR_FUNC(EC_F_ECDH_CMS_DECRYPT), "ecdh_cms_decrypt"},
- {ERR_FUNC(EC_F_ECDH_CMS_SET_SHARED_INFO), "ecdh_cms_set_shared_info"},
- {ERR_FUNC(EC_F_ECDH_COMPUTE_KEY), "ECDH_compute_key"},
- {ERR_FUNC(EC_F_ECDH_SIMPLE_COMPUTE_KEY), "ecdh_simple_compute_key"},
- {ERR_FUNC(EC_F_ECDSA_DO_SIGN_EX), "ECDSA_do_sign_ex"},
- {ERR_FUNC(EC_F_ECDSA_DO_VERIFY), "ECDSA_do_verify"},
- {ERR_FUNC(EC_F_ECDSA_SIGN_EX), "ECDSA_sign_ex"},
- {ERR_FUNC(EC_F_ECDSA_SIGN_SETUP), "ECDSA_sign_setup"},
- {ERR_FUNC(EC_F_ECDSA_SIG_NEW), "ECDSA_SIG_new"},
- {ERR_FUNC(EC_F_ECDSA_VERIFY), "ECDSA_verify"},
- {ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "eckey_param2type"},
- {ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "eckey_param_decode"},
- {ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "eckey_priv_decode"},
- {ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "eckey_priv_encode"},
- {ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "eckey_pub_decode"},
- {ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "eckey_pub_encode"},
- {ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "eckey_type2param"},
- {ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"},
- {ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"},
- {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"},
- {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"},
- {ERR_FUNC(EC_F_ECP_NISTZ256_GET_AFFINE), "ecp_nistz256_get_affine"},
- {ERR_FUNC(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE),
+static const ERR_STRING_DATA EC_str_functs[] = {
+ {ERR_PACK(ERR_LIB_EC, EC_F_BN_TO_FELEM, 0), "BN_to_felem"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPARAMETERS, 0), "d2i_ECParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPKPARAMETERS, 0), "d2i_ECPKParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPRIVATEKEY, 0), "d2i_ECPrivateKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_DO_EC_KEY_PRINT, 0), "do_EC_KEY_print"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_DECRYPT, 0), "ecdh_cms_decrypt"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_SET_SHARED_INFO, 0),
+ "ecdh_cms_set_shared_info"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_COMPUTE_KEY, 0), "ECDH_compute_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_SIMPLE_COMPUTE_KEY, 0),
+ "ecdh_simple_compute_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_SIGN_EX, 0), "ECDSA_do_sign_ex"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_VERIFY, 0), "ECDSA_do_verify"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_EX, 0), "ECDSA_sign_ex"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_SETUP, 0), "ECDSA_sign_setup"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIG_NEW, 0), "ECDSA_SIG_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_VERIFY, 0), "ECDSA_verify"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECD_ITEM_VERIFY, 0), "ecd_item_verify"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM2TYPE, 0), "eckey_param2type"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM_DECODE, 0), "eckey_param_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_DECODE, 0), "eckey_priv_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_ENCODE, 0), "eckey_priv_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_DECODE, 0), "eckey_pub_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_ENCODE, 0), "eckey_pub_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_TYPE2PARAM, 0), "eckey_type2param"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT, 0), "ECParameters_print"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT_FP, 0),
+ "ECParameters_print_fp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT, 0),
+ "ECPKParameters_print"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT_FP, 0),
+ "ECPKParameters_print_fp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_GET_AFFINE, 0),
+ "ecp_nistz256_get_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_INV_MOD_ORD, 0),
+ "ecp_nistz256_inv_mod_ord"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, 0),
"ecp_nistz256_mult_precompute"},
- {ERR_FUNC(EC_F_ECP_NISTZ256_POINTS_MUL), "ecp_nistz256_points_mul"},
- {ERR_FUNC(EC_F_ECP_NISTZ256_PRE_COMP_NEW), "ecp_nistz256_pre_comp_new"},
- {ERR_FUNC(EC_F_ECP_NISTZ256_WINDOWED_MUL), "ecp_nistz256_windowed_mul"},
- {ERR_FUNC(EC_F_ECX_KEY_OP), "ecx_key_op"},
- {ERR_FUNC(EC_F_ECX_PRIV_ENCODE), "ecx_priv_encode"},
- {ERR_FUNC(EC_F_ECX_PUB_ENCODE), "ecx_pub_encode"},
- {ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "ec_asn1_group2curve"},
- {ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "ec_asn1_group2fieldid"},
- {ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY),
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_POINTS_MUL, 0),
+ "ecp_nistz256_points_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_PRE_COMP_NEW, 0),
+ "ecp_nistz256_pre_comp_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_WINDOWED_MUL, 0),
+ "ecp_nistz256_windowed_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECX_KEY_OP, 0), "ecx_key_op"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PRIV_ENCODE, 0), "ecx_priv_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_ECX_PUB_ENCODE, 0), "ecx_pub_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2CURVE, 0), "ec_asn1_group2curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_ASN1_GROUP2FIELDID, 0),
+ "ec_asn1_group2fieldid"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, 0),
"ec_GF2m_montgomery_point_multiply"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
"ec_GF2m_simple_group_check_discriminant"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0),
"ec_GF2m_simple_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES),
+ {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_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
"ec_GF2m_simple_point_set_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, 0),
"ec_GF2m_simple_set_compressed_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_DECODE, 0),
+ "ec_GFp_mont_field_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_ENCODE, 0),
+ "ec_GFp_mont_field_encode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_MUL, 0),
+ "ec_GFp_mont_field_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, 0),
"ec_GFp_mont_field_set_to_one"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
- {ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SQR, 0),
+ "ec_GFp_mont_field_sqr"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_GROUP_SET_CURVE, 0),
"ec_GFp_mont_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, 0),
"ec_GFp_nistp224_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINTS_MUL, 0),
+ "ec_GFp_nistp224_points_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, 0),
"ec_GFp_nistp224_point_get_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, 0),
"ec_GFp_nistp256_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINTS_MUL, 0),
+ "ec_GFp_nistp256_points_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, 0),
"ec_GFp_nistp256_point_get_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, 0),
"ec_GFp_nistp521_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"},
- {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINTS_MUL, 0),
+ "ec_GFp_nistp521_points_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, 0),
"ec_GFp_nistp521_point_get_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
- {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
- {ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_MUL, 0),
+ "ec_GFp_nist_field_mul"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_FIELD_SQR, 0),
+ "ec_GFp_nist_field_sqr"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_GROUP_SET_CURVE, 0),
"ec_GFp_nist_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0),
"ec_GFp_simple_blind_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
"ec_GFp_simple_group_check_discriminant"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0),
"ec_GFp_simple_group_set_curve"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, 0),
+ "ec_GFp_simple_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_OCT2POINT, 0),
+ "ec_GFp_simple_oct2point"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT2OCT, 0),
+ "ec_GFp_simple_point2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, 0),
"ec_GFp_simple_points_make_affine"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0),
"ec_GFp_simple_point_get_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
"ec_GFp_simple_point_set_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, 0),
"ec_GFp_simple_set_compressed_coordinates"},
- {ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"},
- {ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK, 0), "EC_GROUP_check"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_CHECK_DISCRIMINANT, 0),
"EC_GROUP_check_discriminant"},
- {ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_ECPARAMETERS), "EC_GROUP_get_ecparameters"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_ECPKPARAMETERS),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_COPY, 0), "EC_GROUP_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE, 0), "EC_GROUP_get_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GF2M, 0),
+ "EC_GROUP_get_curve_GF2m"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GFP, 0),
+ "EC_GROUP_get_curve_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_DEGREE, 0), "EC_GROUP_get_degree"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPARAMETERS, 0),
+ "EC_GROUP_get_ecparameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPKPARAMETERS, 0),
"EC_GROUP_get_ecpkparameters"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, 0),
"EC_GROUP_get_pentanomial_basis"},
- {ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, 0),
"EC_GROUP_get_trinomial_basis"},
- {ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"},
- {ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"},
- {ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "ec_group_new_from_data"},
- {ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW, 0), "EC_GROUP_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_BY_CURVE_NAME, 0),
+ "EC_GROUP_new_by_curve_name"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_DATA, 0),
+ "ec_group_new_from_data"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, 0),
"EC_GROUP_new_from_ecparameters"},
- {ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, 0),
"EC_GROUP_new_from_ecpkparameters"},
- {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"},
- {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"},
- {ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"},
- {ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"},
- {ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"},
- {ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"},
- {ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
- {ERR_FUNC(EC_F_EC_KEY_NEW_METHOD), "EC_KEY_new_method"},
- {ERR_FUNC(EC_F_EC_KEY_OCT2PRIV), "EC_KEY_oct2priv"},
- {ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
- {ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
- {ERR_FUNC(EC_F_EC_KEY_PRIV2OCT), "EC_KEY_priv2oct"},
- {ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE, 0), "EC_GROUP_set_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GF2M, 0),
+ "EC_GROUP_set_curve_GF2m"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GFP, 0),
+ "EC_GROUP_set_curve_GFp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_GENERATOR, 0),
+ "EC_GROUP_set_generator"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_SEED, 0), "EC_GROUP_set_seed"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_CHECK_KEY, 0), "EC_KEY_check_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_COPY, 0), "EC_KEY_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_GENERATE_KEY, 0), "EC_KEY_generate_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW, 0), "EC_KEY_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW_METHOD, 0), "EC_KEY_new_method"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_OCT2PRIV, 0), "EC_KEY_oct2priv"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT, 0), "EC_KEY_print"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT_FP, 0), "EC_KEY_print_fp"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2BUF, 0), "EC_KEY_priv2buf"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2OCT, 0), "EC_KEY_priv2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 0),
"EC_KEY_set_public_key_affine_coordinates"},
- {ERR_FUNC(EC_F_EC_KEY_SIMPLE_CHECK_KEY), "ec_key_simple_check_key"},
- {ERR_FUNC(EC_F_EC_KEY_SIMPLE_OCT2PRIV), "ec_key_simple_oct2priv"},
- {ERR_FUNC(EC_F_EC_KEY_SIMPLE_PRIV2OCT), "ec_key_simple_priv2oct"},
- {ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
- {ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
- {ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
- {ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"},
- {ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"},
- {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_CHECK_KEY, 0),
+ "ec_key_simple_check_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_OCT2PRIV, 0),
+ "ec_key_simple_oct2priv"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_PRIV2OCT, 0),
+ "ec_key_simple_priv2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_CHECK, 0), "ec_pkey_check"},
+ {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"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_COPY, 0), "EC_POINT_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_DBL, 0), "EC_POINT_dbl"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES, 0),
+ "EC_POINT_get_affine_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 0),
"EC_POINT_get_affine_coordinates_GF2m"},
- {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 0),
"EC_POINT_get_affine_coordinates_GFp"},
- {ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 0),
"EC_POINT_get_Jprojective_coordinates_GFp"},
- {ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"},
- {ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"},
- {ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"},
- {ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"},
- {ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"},
- {ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"},
- {ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"},
- {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_INVERT, 0), "EC_POINT_invert"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_AT_INFINITY, 0),
+ "EC_POINT_is_at_infinity"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_ON_CURVE, 0),
+ "EC_POINT_is_on_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_MAKE_AFFINE, 0),
+ "EC_POINT_make_affine"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_NEW, 0), "EC_POINT_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_OCT2POINT, 0), "EC_POINT_oct2point"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2BUF, 0), "EC_POINT_point2buf"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2OCT, 0), "EC_POINT_point2oct"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES, 0),
+ "EC_POINT_set_affine_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 0),
"EC_POINT_set_affine_coordinates_GF2m"},
- {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 0),
"EC_POINT_set_affine_coordinates_GFp"},
- {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, 0),
+ "EC_POINT_set_compressed_coordinates"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 0),
"EC_POINT_set_compressed_coordinates_GF2m"},
- {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 0),
"EC_POINT_set_compressed_coordinates_GFp"},
- {ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP),
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 0),
"EC_POINT_set_Jprojective_coordinates_GFp"},
- {ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"},
- {ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "ec_pre_comp_new"},
- {ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"},
- {ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"},
- {ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"},
- {ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
- {ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
- {ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
- {ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "nistp224_pre_comp_new"},
- {ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "nistp256_pre_comp_new"},
- {ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "nistp521_pre_comp_new"},
- {ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
- {ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "old_ec_priv_decode"},
- {ERR_FUNC(EC_F_OSSL_ECDH_COMPUTE_KEY), "ossl_ecdh_compute_key"},
- {ERR_FUNC(EC_F_OSSL_ECDSA_SIGN_SIG), "ossl_ecdsa_sign_sig"},
- {ERR_FUNC(EC_F_OSSL_ECDSA_VERIFY_SIG), "ossl_ecdsa_verify_sig"},
- {ERR_FUNC(EC_F_PKEY_ECX_DERIVE), "pkey_ecx_derive"},
- {ERR_FUNC(EC_F_PKEY_EC_CTRL), "pkey_ec_ctrl"},
- {ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "pkey_ec_ctrl_str"},
- {ERR_FUNC(EC_F_PKEY_EC_DERIVE), "pkey_ec_derive"},
- {ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "pkey_ec_keygen"},
- {ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "pkey_ec_paramgen"},
- {ERR_FUNC(EC_F_PKEY_EC_SIGN), "pkey_ec_sign"},
+ {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"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPARAMETERS, 0), "i2d_ECParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPKPARAMETERS, 0), "i2d_ECPKParameters"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPRIVATEKEY, 0), "i2d_ECPrivateKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_I2O_ECPUBLICKEY, 0), "i2o_ECPublicKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_NISTP224_PRE_COMP_NEW, 0),
+ "nistp224_pre_comp_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_NISTP256_PRE_COMP_NEW, 0),
+ "nistp256_pre_comp_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_NISTP521_PRE_COMP_NEW, 0),
+ "nistp521_pre_comp_new"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_O2I_ECPUBLICKEY, 0), "o2i_ECPublicKey"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_OLD_EC_PRIV_DECODE, 0), "old_ec_priv_decode"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDH_COMPUTE_KEY, 0),
+ "ossl_ecdh_compute_key"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_SIGN_SIG, 0), "ossl_ecdsa_sign_sig"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_VERIFY_SIG, 0),
+ "ossl_ecdsa_verify_sig"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_CTRL, 0), "pkey_ecd_ctrl"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN, 0), "pkey_ecd_digestsign"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN25519, 0),
+ "pkey_ecd_digestsign25519"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN448, 0),
+ "pkey_ecd_digestsign448"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECX_DERIVE, 0), "pkey_ecx_derive"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, 0), "pkey_ec_ctrl"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL_STR, 0), "pkey_ec_ctrl_str"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_DERIVE, 0), "pkey_ec_derive"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_INIT, 0), "pkey_ec_init"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KDF_DERIVE, 0), "pkey_ec_kdf_derive"},
+ {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_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"},
{0, NULL}
};
-static ERR_STRING_DATA EC_str_reasons[] = {
- {ERR_REASON(EC_R_ASN1_ERROR), "asn1 error"},
- {ERR_REASON(EC_R_BAD_SIGNATURE), "bad signature"},
- {ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
- {ERR_REASON(EC_R_BUFFER_TOO_SMALL), "buffer too small"},
- {ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"},
- {ERR_REASON(EC_R_CURVE_DOES_NOT_SUPPORT_ECDH),
- "curve does not support ecdh"},
- {ERR_REASON(EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING),
- "curve does not support signing"},
- {ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),
- "d2i ecpkparameters failure"},
- {ERR_REASON(EC_R_DECODE_ERROR), "decode error"},
- {ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"},
- {ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
- "ec group new by name failure"},
- {ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"},
- {ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
- {ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),
- "group2pkparameters failure"},
- {ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),
- "i2d ecpkparameters failure"},
- {ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"},
- {ERR_REASON(EC_R_INVALID_ARGUMENT), "invalid argument"},
- {ERR_REASON(EC_R_INVALID_COMPRESSED_POINT), "invalid compressed point"},
- {ERR_REASON(EC_R_INVALID_COMPRESSION_BIT), "invalid compression bit"},
- {ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"},
- {ERR_REASON(EC_R_INVALID_DIGEST), "invalid digest"},
- {ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
- {ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"},
- {ERR_REASON(EC_R_INVALID_FIELD), "invalid field"},
- {ERR_REASON(EC_R_INVALID_FORM), "invalid form"},
- {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"},
- {ERR_REASON(EC_R_INVALID_KEY), "invalid key"},
- {ERR_REASON(EC_R_INVALID_OUTPUT_LENGTH), "invalid output length"},
- {ERR_REASON(EC_R_INVALID_PEER_KEY), "invalid peer key"},
- {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
- {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
- {ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"},
- {ERR_REASON(EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
- {ERR_REASON(EC_R_KEYS_NOT_SET), "keys not set"},
- {ERR_REASON(EC_R_MISSING_PARAMETERS), "missing parameters"},
- {ERR_REASON(EC_R_MISSING_PRIVATE_KEY), "missing private key"},
- {ERR_REASON(EC_R_NEED_NEW_SETUP_VALUES), "need new setup values"},
- {ERR_REASON(EC_R_NOT_A_NIST_PRIME), "not a NIST prime"},
- {ERR_REASON(EC_R_NOT_IMPLEMENTED), "not implemented"},
- {ERR_REASON(EC_R_NOT_INITIALIZED), "not initialized"},
- {ERR_REASON(EC_R_NO_PARAMETERS_SET), "no parameters set"},
- {ERR_REASON(EC_R_NO_PRIVATE_VALUE), "no private value"},
- {ERR_REASON(EC_R_OPERATION_NOT_SUPPORTED), "operation not supported"},
- {ERR_REASON(EC_R_PASSED_NULL_PARAMETER), "passed null parameter"},
- {ERR_REASON(EC_R_PEER_KEY_ERROR), "peer key error"},
- {ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),
- "pkparameters2group failure"},
- {ERR_REASON(EC_R_POINT_ARITHMETIC_FAILURE), "point arithmetic failure"},
- {ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"},
- {ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"},
- {ERR_REASON(EC_R_RANDOM_NUMBER_GENERATION_FAILED),
- "random number generation failed"},
- {ERR_REASON(EC_R_SHARED_INFO_ERROR), "shared info error"},
- {ERR_REASON(EC_R_SLOT_FULL), "slot full"},
- {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
- {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
- {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"},
- {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"},
- {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"},
- {ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"},
- {ERR_REASON(EC_R_WRONG_ORDER), "wrong order"},
+static const ERR_STRING_DATA EC_str_reasons[] = {
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_ASN1_ERROR), "asn1 error"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_BAD_SIGNATURE), "bad signature"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "buffer too small"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE),
+ "coordinates out of range"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH),
+ "curve does not support ecdh"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING),
+ "curve does not support signing"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_D2I_ECPKPARAMETERS_FAILURE),
+ "d2i ecpkparameters failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_DECODE_ERROR), "decode error"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_DISCRIMINANT_IS_ZERO),
+ "discriminant is zero"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
+ "ec group new by name failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_FIELD_TOO_LARGE), "field too large"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE),
+ "group2pkparameters failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_I2D_ECPKPARAMETERS_FAILURE),
+ "i2d ecpkparameters failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS),
+ "incompatible objects"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ARGUMENT), "invalid argument"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSED_POINT),
+ "invalid compressed point"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COMPRESSION_BIT),
+ "invalid compression bit"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_CURVE), "invalid curve"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST), "invalid digest"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ENCODING), "invalid encoding"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FIELD), "invalid field"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_FORM), "invalid form"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_GROUP_ORDER), "invalid group order"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_KEY), "invalid key"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_OUTPUT_LENGTH),
+ "invalid output length"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PEER_KEY), "invalid peer key"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PENTANOMIAL_BASIS),
+ "invalid pentanomial basis"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_TRINOMIAL_BASIS),
+ "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),
+ "need new setup values"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_A_NIST_PRIME), "not a NIST prime"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_IMPLEMENTED), "not implemented"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NOT_INITIALIZED), "not initialized"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PARAMETERS_SET), "no parameters set"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_NO_PRIVATE_VALUE), "no private value"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_OPERATION_NOT_SUPPORTED),
+ "operation not supported"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_PASSED_NULL_PARAMETER),
+ "passed null parameter"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_PEER_KEY_ERROR), "peer key error"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_PKPARAMETERS2GROUP_FAILURE),
+ "pkparameters2group failure"},
+ {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),
+ "random number generation failed"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_SHARED_INFO_ERROR), "shared info error"},
+ {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"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_CURVE_PARAMETERS),
+ "wrong curve parameters"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_WRONG_ORDER), "wrong order"},
{0, NULL}
};
@@ -282,10 +378,9 @@ static ERR_STRING_DATA EC_str_reasons[] = {
int ERR_load_EC_strings(void)
{
#ifndef OPENSSL_NO_ERR
-
if (ERR_func_error_string(EC_str_functs[0].error) == NULL) {
- ERR_load_strings(0, EC_str_functs);
- ERR_load_strings(0, EC_str_reasons);
+ ERR_load_strings_const(EC_str_functs);
+ ERR_load_strings_const(EC_str_reasons);
}
#endif
return 1;
diff --git a/deps/openssl/openssl/crypto/ec/ec_key.c b/deps/openssl/openssl/crypto/ec/ec_key.c
index 462156f204..9349abf030 100644
--- a/deps/openssl/openssl/crypto/ec/ec_key.c
+++ b/deps/openssl/openssl/crypto/ec/ec_key.c
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,15 +8,10 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions originally developed by SUN MICROSYSTEMS, INC., and
- * contributed to the OpenSSL project.
- */
-
-#include <internal/cryptlib.h>
+#include "internal/cryptlib.h"
#include <string.h>
#include "ec_lcl.h"
+#include "internal/refcount.h"
#include <openssl/err.h>
#include <openssl/engine.h>
@@ -49,7 +45,7 @@ void EC_KEY_free(EC_KEY *r)
if (r == NULL)
return;
- CRYPTO_atomic_add(&r->references, -1, &i, r->lock);
+ CRYPTO_DOWN_REF(&r->references, &i, r->lock);
REF_PRINT_COUNT("EC_KEY", r);
if (i > 0)
return;
@@ -169,7 +165,7 @@ int EC_KEY_up_ref(EC_KEY *r)
{
int i;
- if (CRYPTO_atomic_add(&r->references, 1, &i, r->lock) <= 0)
+ if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
return 0;
REF_PRINT_COUNT("EC_KEY", r);
@@ -177,6 +173,11 @@ int EC_KEY_up_ref(EC_KEY *r)
return ((i > 1) ? 1 : 0);
}
+ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey)
+{
+ return eckey->engine;
+}
+
int EC_KEY_generate_key(EC_KEY *eckey)
{
if (eckey == NULL || eckey->group == NULL) {
@@ -191,7 +192,6 @@ int EC_KEY_generate_key(EC_KEY *eckey)
int ossl_ec_key_gen(EC_KEY *eckey)
{
- OPENSSL_assert(eckey->group->meth->keygen != NULL);
return eckey->group->meth->keygen(eckey);
}
@@ -218,7 +218,7 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
goto err;
do
- if (!BN_rand_range(priv_key, order))
+ if (!BN_priv_rand_range(priv_key, order))
goto err;
while (BN_is_zero(priv_key)) ;
@@ -341,9 +341,6 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
BIGNUM *tx, *ty;
EC_POINT *point = NULL;
int ok = 0;
-#ifndef OPENSSL_NO_EC2M
- int tmp_nid, is_char_two = 0;
-#endif
if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
@@ -365,29 +362,11 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
if (ty == NULL)
goto err;
-#ifndef OPENSSL_NO_EC2M
- tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
-
- if (tmp_nid == NID_X9_62_characteristic_two_field)
- is_char_two = 1;
+ if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx))
+ goto err;
+ if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx))
+ goto err;
- if (is_char_two) {
- if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
- x, y, ctx))
- goto err;
- if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
- tx, ty, ctx))
- goto err;
- } else
-#endif
- {
- if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
- x, y, ctx))
- goto err;
- if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
- tx, ty, ctx))
- goto err;
- }
/*
* Check if retrieved coordinates match originals and are less than field
* order: if not values are out of range.
@@ -613,12 +592,14 @@ size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf)
{
size_t len;
unsigned char *buf;
+
len = EC_KEY_priv2oct(eckey, NULL, 0);
if (len == 0)
return 0;
- buf = OPENSSL_malloc(len);
- if (buf == NULL)
+ if ((buf = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE);
return 0;
+ }
len = EC_KEY_priv2oct(eckey, buf, len);
if (len == 0) {
OPENSSL_free(buf);
diff --git a/deps/openssl/openssl/crypto/ec/ec_lcl.h b/deps/openssl/openssl/crypto/ec/ec_lcl.h
index ca1776efdb..e055ddab1c 100644
--- a/deps/openssl/openssl/crypto/ec/ec_lcl.h
+++ b/deps/openssl/openssl/crypto/ec/ec_lcl.h
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,27 +8,14 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * The elliptic curve binary polynomial software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
#include <stdlib.h>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
-
-#include "e_os.h"
+#include "internal/refcount.h"
+#include "internal/ec_int.h"
+#include "curve448/curve448_lcl.h"
#if defined(__SUNPRO_C)
# if __SUNPRO_C >= 0x520
@@ -62,8 +50,7 @@ struct ec_method_st {
void (*group_finish) (EC_GROUP *);
void (*group_clear_finish) (EC_GROUP *);
int (*group_copy) (EC_GROUP *, const EC_GROUP *);
- /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
- /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
+ /* used by EC_GROUP_set_curve, EC_GROUP_get_curve: */
int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b,
@@ -85,9 +72,9 @@ struct ec_method_st {
* used by EC_POINT_set_to_infinity,
* EC_POINT_set_Jprojective_coordinates_GFp,
* EC_POINT_get_Jprojective_coordinates_GFp,
- * EC_POINT_set_affine_coordinates_GFp, ..._GF2m,
- * EC_POINT_get_affine_coordinates_GFp, ..._GF2m,
- * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:
+ * EC_POINT_set_affine_coordinates,
+ * EC_POINT_get_affine_coordinates,
+ * EC_POINT_set_compressed_coordinates:
*/
int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *);
int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
@@ -133,6 +120,23 @@ struct ec_method_st {
* EC_POINT_have_precompute_mult (default implementations are used if the
* 'mul' pointer is 0):
*/
+ /*-
+ * mul() calculates the value
+ *
+ * r := generator * scalar
+ * + points[0] * scalars[0]
+ * + ...
+ * + points[num-1] * scalars[num-1].
+ *
+ * For a fixed point multiplication (scalar != NULL, num == 0)
+ * or a variable point multiplication (scalar == NULL, num == 1),
+ * mul() must use a constant time algorithm: in both cases callers
+ * should provide an input scalar (either scalar or scalars[0])
+ * in the range [0, ec_group_order); for robustness, implementers
+ * should handle the case when the scalar has not been reduced, but
+ * may treat it as an unusual input, without any constant-timeness
+ * guarantee.
+ */
int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
BN_CTX *);
@@ -169,7 +173,19 @@ struct ec_method_st {
/* custom ECDH operation */
int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
+ /* Inverse modulo order */
+ 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);
};
/*
@@ -262,7 +278,7 @@ struct ec_key_st {
BIGNUM *priv_key;
unsigned int enc_flag;
point_conversion_form_t conv_form;
- int references;
+ CRYPTO_REF_COUNT references;
int flags;
CRYPTO_EX_DATA ex_data;
CRYPTO_RWLOCK *lock;
@@ -284,7 +300,6 @@ struct ec_point_st {
* special case */
};
-
static ossl_inline int ec_point_is_compat(const EC_POINT *point,
const EC_GROUP *group)
{
@@ -297,7 +312,6 @@ static ossl_inline int ec_point_is_compat(const EC_POINT *point,
return 1;
}
-
NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *);
NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *);
NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *);
@@ -378,6 +392,15 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
BN_CTX *ctx);
+int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
+int ec_GFp_simple_ladder_step(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
+int ec_GFp_simple_ladder_post(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx);
/* method functions in ecp_mont.c */
int ec_GFp_mont_group_init(EC_GROUP *);
@@ -455,14 +478,6 @@ int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
-/* method functions in ec2_mult.c */
-int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
- const BIGNUM *scalar, size_t num,
- const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *);
-int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
-int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
-
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
/* method functions in ecp_nistp224.c */
int ec_GFp_nistp224_group_init(EC_GROUP *group);
@@ -553,7 +568,6 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
unsigned char *digit, unsigned char in);
#endif
-int ec_precompute_mont_data(EC_GROUP *);
int ec_group_simple_order_bits(const EC_GROUP *group);
#ifdef ECP_NISTZ256_ASM
@@ -626,9 +640,88 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
+int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+ const uint8_t public_key[32], const uint8_t private_key[32]);
+int ED25519_verify(const uint8_t *message, size_t message_len,
+ const uint8_t signature[64], const uint8_t public_key[32]);
+void ED25519_public_from_private(uint8_t out_public_key[32],
+ const uint8_t private_key[32]);
+
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[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 ossl_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 ossl_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 ossl_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;
+}
diff --git a/deps/openssl/openssl/crypto/ec/ec_lib.c b/deps/openssl/openssl/crypto/ec/ec_lib.c
index a7be03b627..b89e3979d9 100644
--- a/deps/openssl/openssl/crypto/ec/ec_lib.c
+++ b/deps/openssl/openssl/crypto/ec/ec_lib.c
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Binary polynomial ECC support in OpenSSL originally developed by
- * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
- */
-
#include <string.h>
#include <openssl/err.h>
@@ -66,13 +61,13 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
void EC_pre_comp_free(EC_GROUP *group)
{
switch (group->pre_comp_type) {
- default:
+ case PCT_none:
break;
-#ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
case PCT_nistz256:
+#ifdef ECP_NISTZ256_ASM
EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
- break;
#endif
+ break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
@@ -83,6 +78,11 @@ void EC_pre_comp_free(EC_GROUP *group)
case PCT_nistp521:
EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
break;
+#else
+ case PCT_nistp224:
+ case PCT_nistp256:
+ case PCT_nistp521:
+ break;
#endif
case PCT_ec:
EC_ec_pre_comp_free(group->pre_comp.ec);
@@ -145,14 +145,14 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
/* Copy precomputed */
dest->pre_comp_type = src->pre_comp_type;
switch (src->pre_comp_type) {
- default:
+ case PCT_none:
dest->pre_comp.ec = NULL;
break;
-#ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
case PCT_nistz256:
+#ifdef ECP_NISTZ256_ASM
dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
- break;
#endif
+ break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
@@ -163,6 +163,11 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
case PCT_nistp521:
dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
break;
+#else
+ case PCT_nistp224:
+ case PCT_nistp256:
+ case PCT_nistp521:
+ break;
#endif
case PCT_ec:
dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
@@ -209,9 +214,10 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
if (src->seed) {
OPENSSL_free(dest->seed);
- dest->seed = OPENSSL_malloc(src->seed_len);
- if (dest->seed == NULL)
+ if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
+ ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE);
return 0;
+ }
if (!memcpy(dest->seed, src->seed, src->seed_len))
return 0;
dest->seed_len = src->seed_len;
@@ -233,7 +239,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
return NULL;
if ((t = EC_GROUP_new(a->meth)) == NULL)
- return (NULL);
+ return NULL;
if (!EC_GROUP_copy(t, a))
goto err;
@@ -257,6 +263,8 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth)
return meth->field_type;
}
+static int ec_precompute_mont_data(EC_GROUP *);
+
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor)
{
@@ -326,7 +334,6 @@ const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
int EC_GROUP_order_bits(const EC_GROUP *group)
{
- OPENSSL_assert(group->meth->group_order_bits != NULL);
return group->meth->group_order_bits(group);
}
@@ -388,8 +395,10 @@ size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
if (!len || !p)
return 1;
- if ((group->seed = OPENSSL_malloc(len)) == NULL)
+ if ((group->seed = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE);
return 0;
+ }
memcpy(group->seed, p, len);
group->seed_len = len;
@@ -406,48 +415,52 @@ size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
return group->seed_len;
}
-int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
- const BIGNUM *b, BN_CTX *ctx)
+int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
{
if (group->meth->group_set_curve == 0) {
- ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_set_curve(group, p, a, b, ctx);
}
-int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
- BIGNUM *b, BN_CTX *ctx)
+int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
+ BN_CTX *ctx)
{
- if (group->meth->group_get_curve == 0) {
- ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ if (group->meth->group_get_curve == NULL) {
+ ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_curve(group, p, a, b, ctx);
}
-#ifndef OPENSSL_NO_EC2M
+#if OPENSSL_API_COMPAT < 0x10200000L
+int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+ const BIGNUM *b, BN_CTX *ctx)
+{
+ return EC_GROUP_set_curve(group, p, a, b, ctx);
+}
+
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
+ BIGNUM *b, BN_CTX *ctx)
+{
+ return EC_GROUP_get_curve(group, p, a, b, ctx);
+}
+
+# ifndef OPENSSL_NO_EC2M
int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
- if (group->meth->group_set_curve == 0) {
- ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
- return group->meth->group_set_curve(group, p, a, b, ctx);
+ return EC_GROUP_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
- if (group->meth->group_get_curve == 0) {
- ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
- return group->meth->group_get_curve(group, p, a, b, ctx);
+ return EC_GROUP_get_curve(group, p, a, b, ctx);
}
+# endif
#endif
int EC_GROUP_get_degree(const EC_GROUP *group)
@@ -552,7 +565,7 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group)
ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
- if (group->meth->point_init == 0) {
+ if (group->meth->point_init == NULL) {
ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
@@ -624,7 +637,7 @@ EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
t = EC_POINT_new(group);
if (t == NULL)
- return (NULL);
+ return NULL;
r = EC_POINT_copy(t, a);
if (!r) {
EC_POINT_free(t);
@@ -690,102 +703,83 @@ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
y, z, ctx);
}
-int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- const BIGNUM *y, BN_CTX *ctx)
+int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
+ const BIGNUM *x, const BIGNUM *y,
+ BN_CTX *ctx)
{
- if (group->meth->point_set_affine_coordinates == 0) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
+ if (group->meth->point_set_affine_coordinates == NULL) {
+ ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
- EC_R_INCOMPATIBLE_OBJECTS);
+ ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
return 0;
if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
- EC_R_POINT_IS_NOT_ON_CURVE);
+ ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE);
return 0;
}
return 1;
}
-#ifndef OPENSSL_NO_EC2M
+#if OPENSSL_API_COMPAT < 0x10200000L
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x,
+ const BIGNUM *y, BN_CTX *ctx)
+{
+ return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
+}
+
+# ifndef OPENSSL_NO_EC2M
int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
- if (group->meth->point_set_affine_coordinates == 0) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
- if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
- EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
- return 0;
-
- if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
- ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
- EC_R_POINT_IS_NOT_ON_CURVE);
- return 0;
- }
- return 1;
+ return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
}
+# endif
#endif
-int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
- const EC_POINT *point, BIGNUM *x,
- BIGNUM *y, BN_CTX *ctx)
+int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point, BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx)
{
- if (group->meth->point_get_affine_coordinates == 0) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
+ if (group->meth->point_get_affine_coordinates == NULL) {
+ ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
- EC_R_INCOMPATIBLE_OBJECTS);
+ ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
- EC_R_POINT_AT_INFINITY);
+ ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
return 0;
}
return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
}
-#ifndef OPENSSL_NO_EC2M
+#if OPENSSL_API_COMPAT < 0x10200000L
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
+ const EC_POINT *point, BIGNUM *x,
+ BIGNUM *y, BN_CTX *ctx)
+{
+ return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
+}
+
+# ifndef OPENSSL_NO_EC2M
int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
{
- if (group->meth->point_get_affine_coordinates == 0) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
- if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
- EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- if (EC_POINT_is_at_infinity(group, point)) {
- ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
- EC_R_POINT_AT_INFINITY);
- return 0;
- }
- return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+ return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
}
+# endif
#endif
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
@@ -920,11 +914,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)
+ int ret = 0;
+ size_t i = 0;
+ BN_CTX *new_ctx = NULL;
+
+ 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 */
- return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
- return group->meth->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,
@@ -972,7 +993,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
* returns one on success. On error it returns zero.
*/
-int ec_precompute_mont_data(EC_GROUP *group)
+static int ec_precompute_mont_data(EC_GROUP *group)
{
BN_CTX *ctx = BN_CTX_new();
int ret = 0;
@@ -1018,6 +1039,69 @@ int ec_group_simple_order_bits(const EC_GROUP *group)
return BN_num_bits(group->order);
}
+static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *x, BN_CTX *ctx)
+{
+ BIGNUM *e = NULL;
+ BN_CTX *new_ctx = NULL;
+ int ret = 0;
+
+ if (group->mont_data == NULL)
+ return 0;
+
+ if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
+ return 0;
+
+ BN_CTX_start(ctx);
+ if ((e = BN_CTX_get(ctx)) == NULL)
+ goto err;
+
+ /*-
+ * We want inverse in constant time, therefore we utilize the fact
+ * order must be prime and use Fermats Little Theorem instead.
+ */
+ if (!BN_set_word(e, 2))
+ goto err;
+ if (!BN_sub(e, group->order, e))
+ goto err;
+ /*-
+ * Exponent e is public.
+ * No need for scatter-gather or BN_FLG_CONSTTIME.
+ */
+ if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
+ goto err;
+
+ ret = 1;
+
+ err:
+ if (ctx != NULL)
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
+/*-
+ * Default behavior, if group->meth->field_inverse_mod_ord is NULL:
+ * - When group->order is even, this function returns an error.
+ * - When group->order is otherwise composite, the correctness
+ * of the output is not guaranteed.
+ * - When x is outside the range [1, group->order), the correctness
+ * of the output is not guaranteed.
+ * - Otherwise, this function returns the multiplicative inverse in the
+ * range [1, group->order).
+ *
+ * EC_METHODs must implement their own field_inverse_mod_ord for
+ * other functionality.
+ */
+int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
+ const BIGNUM *x, BN_CTX *ctx)
+{
+ if (group->meth->field_inverse_mod_ord != NULL)
+ return group->meth->field_inverse_mod_ord(group, res, x, ctx);
+ else
+ return ec_field_inverse_mod_ord(group, res, x, ctx);
+}
+
/*-
* Coordinate blinding for EC_POINT.
*
diff --git a/deps/openssl/openssl/crypto/ec/ec_mult.c b/deps/openssl/openssl/crypto/ec/ec_mult.c
index 8350082eb4..0e0a5e1394 100644
--- a/deps/openssl/openssl/crypto/ec/ec_mult.c
+++ b/deps/openssl/openssl/crypto/ec/ec_mult.c
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,18 +8,13 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions of this software developed by SUN MICROSYSTEMS, INC.,
- * and contributed to the OpenSSL project.
- */
-
#include <string.h>
#include <openssl/err.h>
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "ec_lcl.h"
+#include "internal/refcount.h"
/*
* This file implements the wNAF-based interleaving multi-exponentiation method
@@ -42,7 +38,7 @@ struct ec_pre_comp_st {
* generator: 'num' pointers to EC_POINT
* objects followed by a NULL */
size_t num; /* numblocks * 2^(w-1) */
- int references;
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -77,7 +73,7 @@ EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
{
int i;
if (pre != NULL)
- CRYPTO_atomic_add(&pre->references, 1, &i, pre->lock);
+ CRYPTO_UP_REF(&pre->references, &i, pre->lock);
return pre;
}
@@ -88,7 +84,7 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
if (pre == NULL)
return;
- CRYPTO_atomic_add(&pre->references, -1, &i, pre->lock);
+ CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
REF_PRINT_COUNT("EC_ec", pre);
if (i > 0)
return;
@@ -112,62 +108,95 @@ 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.
+ * 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.
*
- * At a high level, it is Montgomery ladder with conditional swaps.
- *
- * It performs either a fixed scalar point multiplication
+ * It performs either a fixed point multiplication
* (scalar * generator)
- * when point is NULL, or a generic scalar point multiplication
+ * when point is NULL, or a variable point multiplication
* (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).
+ *
+ * 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 EC_POINT_add and EC_POINT_dbl,
- * which of course are not constant time themselves.
+ * 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.
+ * 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))
+ 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(s, point))
+ 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.
@@ -178,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 + 2) == NULL)
- || (bn_wexpand(lambda, group_top + 2) == NULL))
+ || (bn_wexpand(lambda, group_top + 2) == 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);
@@ -191,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
@@ -213,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.
@@ -224,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;
+ }
- /* 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))
+ /* 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;
+ }
- pbit = 0;
+ /* top bit is a 1, in a fixed pos */
+ pbit = 1;
#define EC_POINT_CSWAP(c, a, b, w, t) do { \
BN_consttime_swap(c, (a)->X, (b)->X, w); \
@@ -308,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
@@ -322,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;
}
@@ -359,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;
@@ -384,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);
- }
- }
-
- 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;
+ return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
}
}
- 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) {
@@ -740,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);
diff --git a/deps/openssl/openssl/crypto/ec/ec_oct.c b/deps/openssl/openssl/crypto/ec/ec_oct.c
index e185df6edf..522f79e673 100644
--- a/deps/openssl/openssl/crypto/ec/ec_oct.c
+++ b/deps/openssl/openssl/crypto/ec/ec_oct.c
@@ -1,5 +1,6 @@
/*
* Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Binary polynomial ECC support in OpenSSL originally developed by
- * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
- */
-
#include <string.h>
#include <openssl/err.h>
@@ -20,18 +15,17 @@
#include "ec_lcl.h"
-int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- int y_bit, BN_CTX *ctx)
+int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
+ const BIGNUM *x, int y_bit, BN_CTX *ctx)
{
- if (group->meth->point_set_compressed_coordinates == 0
+ if (group->meth->point_set_compressed_coordinates == NULL
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
+ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
+ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -42,7 +36,7 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
else
#ifdef OPENSSL_NO_EC2M
{
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
+ ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
EC_R_GF2M_NOT_SUPPORTED);
return 0;
}
@@ -55,33 +49,22 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
y_bit, ctx);
}
-#ifndef OPENSSL_NO_EC2M
+#if OPENSSL_API_COMPAT < 0x10200000L
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x,
+ int y_bit, BN_CTX *ctx)
+{
+ return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
+}
+
+# ifndef OPENSSL_NO_EC2M
int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx)
{
- if (group->meth->point_set_compressed_coordinates == 0
- && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
- if (!ec_point_is_compat(point, group)) {
- ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
- EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
- if (group->meth->field_type == NID_X9_62_prime_field)
- return ec_GFp_simple_set_compressed_coordinates(group, point, x,
- y_bit, ctx);
- else
- return ec_GF2m_simple_set_compressed_coordinates(group, point, x,
- y_bit, ctx);
- }
- return group->meth->point_set_compressed_coordinates(group, point, x,
- y_bit, ctx);
+ return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
}
+# endif
#endif
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
@@ -149,12 +132,14 @@ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
{
size_t len;
unsigned char *buf;
+
len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL);
if (len == 0)
return 0;
- buf = OPENSSL_malloc(len);
- if (buf == NULL)
+ if ((buf = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_POINT_POINT2BUF, ERR_R_MALLOC_FAILURE);
return 0;
+ }
len = EC_POINT_point2oct(group, point, form, buf, len, ctx);
if (len == 0) {
OPENSSL_free(buf);
diff --git a/deps/openssl/openssl/crypto/ec/ec_pmeth.c b/deps/openssl/openssl/crypto/ec/ec_pmeth.c
index 68ff2bbccf..f4ad0749ef 100644
--- a/deps/openssl/openssl/crypto/ec/ec_pmeth.c
+++ b/deps/openssl/openssl/crypto/ec/ec_pmeth.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -42,9 +42,10 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx)
{
EC_PKEY_CTX *dctx;
- dctx = OPENSSL_zalloc(sizeof(*dctx));
- if (dctx == NULL)
+ if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
+ ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE);
return 0;
+ }
dctx->cofactor_mode = -1;
dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
@@ -87,11 +88,12 @@ static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
{
EC_PKEY_CTX *dctx = ctx->data;
- if (dctx) {
+ if (dctx != NULL) {
EC_GROUP_free(dctx->gen_group);
EC_KEY_free(dctx->co_key);
OPENSSL_free(dctx->kdf_ukm);
OPENSSL_free(dctx);
+ ctx->data = NULL;
}
}
@@ -102,19 +104,23 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
unsigned int sltmp;
EC_PKEY_CTX *dctx = ctx->data;
EC_KEY *ec = ctx->pkey->pkey.ec;
+ const int sig_sz = ECDSA_size(ec);
+
+ /* ensure cast to size_t is safe */
+ if (!ossl_assert(sig_sz > 0))
+ return 0;
- if (!sig) {
- *siglen = ECDSA_size(ec);
+ if (sig == NULL) {
+ *siglen = (size_t)sig_sz;
return 1;
- } else if (*siglen < (size_t)ECDSA_size(ec)) {
+ }
+
+ if (*siglen < (size_t)sig_sz) {
ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
return 0;
}
- if (dctx->md)
- type = EVP_MD_type(dctx->md);
- else
- type = NID_sha1;
+ type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
@@ -143,8 +149,7 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
}
#ifndef OPENSSL_NO_EC
-static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- size_t *keylen)
+static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
{
int ret;
size_t outlen;
@@ -197,13 +202,14 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
return 0;
if (!pkey_ec_derive(ctx, NULL, &ktmplen))
return 0;
- ktmp = OPENSSL_malloc(ktmplen);
- if (ktmp == NULL)
+ if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
+ ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE);
return 0;
+ }
if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
goto err;
/* Do KDF stuff */
- if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen,
+ if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
goto err;
rv = 1;
@@ -244,8 +250,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return dctx->cofactor_mode;
else {
EC_KEY *ec_key = ctx->pkey->pkey.ec;
- return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 :
- 0;
+ return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
}
} else if (p1 < -1 || p1 > 1)
return -2;
@@ -276,7 +281,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_EC_KDF_TYPE:
if (p1 == -2)
return dctx->kdf_type;
- if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
+ if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
return -2;
dctx->kdf_type = p1;
return 1;
@@ -386,7 +391,8 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
EC_KEY *ec = NULL;
EC_PKEY_CTX *dctx = ctx->data;
- int ret = 0;
+ int ret;
+
if (dctx->gen_group == NULL) {
ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
return 0;
@@ -394,10 +400,8 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
ec = EC_KEY_new();
if (ec == NULL)
return 0;
- ret = EC_KEY_set_group(ec, dctx->gen_group);
- if (ret)
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- else
+ if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
+ || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
EC_KEY_free(ec);
return ret;
}
@@ -406,23 +410,26 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
EC_KEY *ec = NULL;
EC_PKEY_CTX *dctx = ctx->data;
+ int ret;
+
if (ctx->pkey == NULL && dctx->gen_group == NULL) {
ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
- if (!ec)
+ if (ec == NULL)
+ return 0;
+ if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
+ EC_KEY_free(ec);
return 0;
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- if (ctx->pkey) {
- /* Note: if error return, pkey is freed by parent routine */
- if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
- return 0;
- } else {
- if (!EC_KEY_set_group(ec, dctx->gen_group))
- return 0;
}
- return EC_KEY_generate_key(pkey->pkey.ec);
+ /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
+ if (ctx->pkey != NULL)
+ ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
+ else
+ ret = EC_KEY_set_group(ec, dctx->gen_group);
+
+ return ret ? EC_KEY_generate_key(ec) : 0;
}
const EVP_PKEY_METHOD ec_pkey_meth = {
@@ -448,9 +455,11 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
0, 0, 0, 0,
- 0, 0,
+ 0,
+ 0,
- 0, 0,
+ 0,
+ 0,
0,
#ifndef OPENSSL_NO_EC
diff --git a/deps/openssl/openssl/crypto/ec/ec_print.c b/deps/openssl/openssl/crypto/ec/ec_print.c
index 1afa2ce875..027a51928a 100644
--- a/deps/openssl/openssl/crypto/ec/ec_print.c
+++ b/deps/openssl/openssl/crypto/ec/ec_print.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -8,6 +8,7 @@
*/
#include <openssl/crypto.h>
+#include <openssl/err.h>
#include "ec_lcl.h"
BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,
@@ -39,9 +40,10 @@ EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
if ((buf_len = BN_num_bytes(bn)) == 0)
return NULL;
- buf = OPENSSL_malloc(buf_len);
- if (buf == NULL)
+ if ((buf = OPENSSL_malloc(buf_len)) == NULL) {
+ ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE);
return NULL;
+ }
if (!BN_bn2bin(bn, buf)) {
OPENSSL_free(buf);
diff --git a/deps/openssl/openssl/crypto/ec/ecdh_kdf.c b/deps/openssl/openssl/crypto/ec/ecdh_kdf.c
index d47486eb34..d686f9d897 100644
--- a/deps/openssl/openssl/crypto/ec/ecdh_kdf.c
+++ b/deps/openssl/openssl/crypto/ec/ecdh_kdf.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -10,12 +10,13 @@
#include <string.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
+#include "ec_lcl.h"
-/* Key derivation function from X9.62/SECG */
+/* Key derivation function from X9.63/SECG */
/* Way more than we will ever need */
#define ECDH_KDF_MAX (1 << 30)
-int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
const unsigned char *Z, size_t Zlen,
const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md)
@@ -66,3 +67,15 @@ int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
EVP_MD_CTX_free(mctx);
return rv;
}
+
+/*-
+ * The old name for ecdh_KDF_X9_63
+ * Retained for ABI compatibility
+ */
+int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
+ const unsigned char *Z, size_t Zlen,
+ const unsigned char *sinfo, size_t sinfolen,
+ const EVP_MD *md)
+{
+ return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md);
+}
diff --git a/deps/openssl/openssl/crypto/ec/ecdh_ossl.c b/deps/openssl/openssl/crypto/ec/ecdh_ossl.c
index a865145974..bd93793a18 100644
--- a/deps/openssl/openssl/crypto/ec/ecdh_ossl.c
+++ b/deps/openssl/openssl/crypto/ec/ecdh_ossl.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,21 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
- * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
- * to the OpenSSL project.
- *
- * The ECC Code is licensed pursuant to the OpenSSL open source
- * license provided below.
- *
- * The ECDH software is originally written by Douglas Stebila of
- * Sun Microsystems Laboratories.
- *
- */
-
#include <string.h>
#include <limits.h>
@@ -54,7 +40,7 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
{
BN_CTX *ctx;
EC_POINT *tmp = NULL;
- BIGNUM *x = NULL, *y = NULL;
+ BIGNUM *x = NULL;
const BIGNUM *priv_key;
const EC_GROUP *group;
int ret = 0;
@@ -65,8 +51,7 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
goto err;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
- y = BN_CTX_get(ctx);
- if (y == NULL) {
+ if (x == NULL) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -98,21 +83,10 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
goto err;
}
- 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, x, y, ctx)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
- }
-#ifndef OPENSSL_NO_EC2M
- else {
- if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) {
- ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
- goto err;
- }
+ if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) {
+ ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
+ goto err;
}
-#endif
buflen = (EC_GROUP_get_degree(group) + 7) / 8;
len = BN_num_bytes(x);
diff --git a/deps/openssl/openssl/crypto/ec/ecdsa_ossl.c b/deps/openssl/openssl/crypto/ec/ecdsa_ossl.c
index 9e4a68d9ca..e35c7600d8 100644
--- a/deps/openssl/openssl/crypto/ec/ecdsa_ossl.c
+++ b/deps/openssl/openssl/crypto/ec/ecdsa_ossl.c
@@ -19,7 +19,7 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
{
ECDSA_SIG *s;
- RAND_seed(dgst, dlen);
+
s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
if (s == NULL) {
*siglen = 0;
@@ -91,7 +91,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
goto err;
}
} else {
- if (!BN_rand_range(k, order)) {
+ if (!BN_priv_rand_range(k, order)) {
ECerr(EC_F_ECDSA_SIGN_SETUP,
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
@@ -99,45 +99,17 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
}
} while (BN_is_zero(k));
- /*
- * We do not want timing information to leak the length of k, so we
- * compute G*k using an equivalent scalar of fixed bit-length.
- *
- * We unconditionally perform both of these additions to prevent a
- * small timing information leakage. We then choose the sum that is
- * one bit longer than the order. This guarantees the code
- * path used in the constant time implementations elsewhere.
- *
- * TODO: revisit the BN_copy aiming for a memory access agnostic
- * conditional copy.
- */
- if (!BN_add(r, k, order)
- || !BN_add(X, r, order)
- || !BN_copy(k, BN_num_bits(r) > order_bits ? r : X))
- goto err;
-
/* compute r the x-coordinate of generator * k */
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
goto err;
}
- 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)) {
- 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)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
- goto err;
- }
+
+ if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) {
+ ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+ goto err;
}
-#endif
+
if (!BN_nnmod(r, X, order, ctx)) {
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
goto err;
@@ -145,30 +117,9 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
} while (BN_is_zero(r));
/* compute the inverse of k */
- if (EC_GROUP_get_mont_data(group) != NULL) {
- /*
- * We want inverse in constant time, therefore we utilize the fact
- * order must be prime and use Fermats Little Theorem instead.
- */
- if (!BN_set_word(X, 2)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
- goto err;
- }
- if (!BN_mod_sub(X, order, X, order, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
- goto err;
- }
- BN_set_flags(X, BN_FLG_CONSTTIME);
- if (!BN_mod_exp_mont_consttime
- (k, k, X, order, ctx, EC_GROUP_get_mont_data(group))) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
- goto err;
- }
- } else {
- if (!BN_mod_inverse(k, k, order, ctx)) {
- ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
- goto err;
- }
+ if (!ec_group_do_inverse_ord(group, k, k, ctx)) {
+ ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+ goto err;
}
/* clear old values if necessary */
@@ -187,7 +138,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
BN_CTX_free(ctx);
EC_POINT_free(tmp_point);
BN_clear_free(X);
- return (ret);
+ return ret;
}
int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
@@ -299,7 +250,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
if (BN_is_zero(s)) {
/*
- * if kinv and r have been supplied by the caller don't to
+ * if kinv and r have been supplied by the caller, don't
* generate new kinv and r values
*/
if (in_kinv != NULL && in_r != NULL) {
@@ -341,7 +292,7 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
s = ECDSA_SIG_new();
if (s == NULL)
- return (ret);
+ return ret;
if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL)
goto err;
/* Ensure signature uses DER and doesn't have trailing garbage */
@@ -352,7 +303,7 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
err:
OPENSSL_clear_free(der, derlen);
ECDSA_SIG_free(s);
- return (ret);
+ return ret;
}
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
@@ -407,7 +358,7 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
goto err;
}
/* calculate tmp1 = inv(S) mod order */
- if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
+ if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
goto err;
}
@@ -446,22 +397,12 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
goto err;
}
- if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
- NID_X9_62_prime_field) {
- if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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, point, X, NULL, ctx)) {
- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
- goto err;
- }
+ if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
+ ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+ goto err;
}
-#endif
+
if (!BN_nnmod(u1, X, order, ctx)) {
ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
goto err;
diff --git a/deps/openssl/openssl/crypto/ec/eck_prn.c b/deps/openssl/openssl/crypto/ec/eck_prn.c
index 3e826cb138..b538fadcb1 100644
--- a/deps/openssl/openssl/crypto/ec/eck_prn.c
+++ b/deps/openssl/openssl/crypto/ec/eck_prn.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions originally developed by SUN MICROSYSTEMS, INC., and
- * contributed to the OpenSSL project.
- */
-
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
@@ -27,12 +22,12 @@ int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
if ((b = BIO_new(BIO_s_file())) == NULL) {
ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = ECPKParameters_print(b, x, off);
BIO_free(b);
- return (ret);
+ return ret;
}
int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
@@ -42,12 +37,12 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
if ((b = BIO_new(BIO_s_file())) == NULL) {
ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
- return (0);
+ return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = EC_KEY_print(b, x, off);
BIO_free(b);
- return (ret);
+ return ret;
}
int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
@@ -57,12 +52,12 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
if ((b = BIO_new(BIO_s_file())) == NULL) {
ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
- return (0);
+ return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = ECParameters_print(b, x);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
@@ -130,19 +125,10 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
reason = ERR_R_MALLOC_FAILURE;
goto err;
}
-#ifndef OPENSSL_NO_EC2M
- if (is_char_two) {
- if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) {
- reason = ERR_R_EC_LIB;
- goto err;
- }
- } else /* prime field */
-#endif
- {
- if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) {
- reason = ERR_R_EC_LIB;
- goto err;
- }
+
+ if (!EC_GROUP_get_curve(x, p, a, b, ctx)) {
+ reason = ERR_R_EC_LIB;
+ goto err;
}
if ((point = EC_GROUP_get0_generator(x)) == NULL) {
@@ -231,7 +217,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
BN_free(b);
BN_free(gen);
BN_CTX_free(ctx);
- return (ret);
+ return ret;
}
static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
diff --git a/deps/openssl/openssl/crypto/ec/ecp_mont.c b/deps/openssl/openssl/crypto/ec/ecp_mont.c
index d837d4d465..36682e5cfb 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_mont.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_mont.c
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions of this software developed by SUN MICROSYSTEMS, INC.,
- * and contributed to the OpenSSL project.
- */
-
#include <openssl/err.h>
#include "ec_lcl.h"
@@ -67,7 +62,11 @@ const EC_METHOD *EC_GFp_mont_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- ec_GFp_simple_blind_coordinates
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates,
+ ec_GFp_simple_ladder_pre,
+ ec_GFp_simple_ladder_step,
+ ec_GFp_simple_ladder_post
};
return &ret;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_nist.c b/deps/openssl/openssl/crypto/ec/ecp_nist.c
index 143f21f3f9..f53de1a163 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_nist.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_nist.c
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions of this software developed by SUN MICROSYSTEMS, INC.,
- * and contributed to the OpenSSL project.
- */
-
#include <limits.h>
#include <openssl/err.h>
@@ -69,7 +64,11 @@ const EC_METHOD *EC_GFp_nist_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- ec_GFp_simple_blind_coordinates
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates,
+ ec_GFp_simple_ladder_pre,
+ ec_GFp_simple_ladder_step,
+ ec_GFp_simple_ladder_post
};
return &ret;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_nistp224.c b/deps/openssl/openssl/crypto/ec/ecp_nistp224.c
index 52056ff591..555bf307dd 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_nistp224.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_nistp224.c
@@ -40,12 +40,12 @@ NON_EMPTY_TRANSLATION_UNIT
# include <openssl/err.h>
# include "ec_lcl.h"
-# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
/* even with gcc, the typedef won't work for 32-bit platforms */
typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
* platforms */
# else
-# error "Need GCC 3.1 or later to define type uint128_t"
+# error "Your compiler doesn't appear to support 128-bit integer types"
# endif
typedef uint8_t u8;
@@ -78,7 +78,7 @@ typedef limb felem[4];
typedef widelimb widefelem[7];
/*
- * Field element represented as a byte arrary. 28*8 = 224 bits is also the
+ * Field element represented as a byte array. 28*8 = 224 bits is also the
* group order size for the elliptic curve, and we also use this type for
* scalars for point multiplication.
*/
@@ -235,7 +235,7 @@ static const felem gmul[2][16][3] = {
/* Precomputation for the group generator. */
struct nistp224_pre_comp_st {
felem g_pre_comp[2][16][3];
- int references;
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -291,7 +291,11 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- 0 /* blind_coordinates */
+ 0, /* field_inverse_mod_ord */
+ 0, /* blind_coordinates */
+ 0, /* ladder_pre */
+ 0, /* ladder_step */
+ 0 /* ladder_post */
};
return &ret;
@@ -396,22 +400,6 @@ static void felem_sum(felem out, const felem in)
out[3] += in[3];
}
-/* Get negative value: out = -in */
-/* Assumes in[i] < 2^57 */
-static void felem_neg(felem out, const felem in)
-{
- static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
- static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
- static const limb two58m42m2 = (((limb) 1) << 58) -
- (((limb) 1) << 42) - (((limb) 1) << 2);
-
- /* Set to 0 mod 2^224-2^96+1 to ensure out > in */
- out[0] = two58p2 - in[0];
- out[1] = two58m42m2 - in[1];
- out[2] = two58m2 - in[2];
- out[3] = two58m2 - in[3];
-}
-
/* Subtract field elements: out -= in */
/* Assumes in[i] < 2^57 */
static void felem_diff(felem out, const felem in)
@@ -681,6 +669,18 @@ static void felem_contract(felem out, const felem in)
}
/*
+ * Get negative value: out = -in
+ * Requires in[i] < 2^63,
+ * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16
+ */
+static void felem_neg(felem out, const felem in)
+{
+ widefelem tmp = {0};
+ felem_diff_128_64(tmp, in);
+ felem_reduce(out, tmp);
+}
+
+/*
* Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field
* elements are reduced to in < 2^225, so we only need to check three cases:
* 0, 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2
@@ -818,7 +818,7 @@ static void copy_conditional(felem out, const felem in, limb icopy)
* Double an elliptic curve point:
* (X', Y', Z') = 2 * (X, Y, Z), where
* X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2
- * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2
+ * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^4
* Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z
* Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed,
* while x_out == y_in is not (maybe this works, but it's not tested).
@@ -1215,7 +1215,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
* FUNCTIONS TO MANAGE PRECOMPUTATION
*/
-static NISTP224_PRE_COMP *nistp224_pre_comp_new()
+static NISTP224_PRE_COMP *nistp224_pre_comp_new(void)
{
NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -1239,7 +1239,7 @@ NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *p)
{
int i;
if (p != NULL)
- CRYPTO_atomic_add(&p->references, 1, &i, p->lock);
+ CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
@@ -1250,7 +1250,7 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p)
if (p == NULL)
return;
- CRYPTO_atomic_add(&p->references, -1, &i, p->lock);
+ CRYPTO_DOWN_REF(&p->references, &i, p->lock);
REF_PRINT_COUNT("EC_nistp224", x);
if (i > 0)
return;
@@ -1285,9 +1285,10 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
- ((curve_a = BN_CTX_get(ctx)) == NULL) ||
- ((curve_b = BN_CTX_get(ctx)) == NULL))
+ curve_p = BN_CTX_get(ctx);
+ curve_a = BN_CTX_get(ctx);
+ curve_b = BN_CTX_get(ctx);
+ if (curve_b == NULL)
goto err;
BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p);
BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
@@ -1395,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;
@@ -1412,14 +1412,12 @@ 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);
- if (((x = BN_CTX_get(ctx)) == NULL) ||
- ((y = BN_CTX_get(ctx)) == NULL) ||
- ((z = BN_CTX_get(ctx)) == NULL) ||
- ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ tmp_scalar = BN_CTX_get(ctx);
+ if (tmp_scalar == NULL)
goto err;
if (scalar != NULL) {
@@ -1576,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);
@@ -1599,7 +1596,9 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
goto err;
/* get the generator */
if (group->generator == NULL)
@@ -1609,7 +1608,7 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
goto err;
BN_bin2bn(nistp224_curve_params[3], sizeof(felem_bytearray), x);
BN_bin2bn(nistp224_curve_params[4], sizeof(felem_bytearray), y);
- if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx))
goto err;
if ((pre = nistp224_pre_comp_new()) == NULL)
goto err;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_nistp256.c b/deps/openssl/openssl/crypto/ec/ecp_nistp256.c
index ffd2a7d93a..c87a5e548d 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_nistp256.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_nistp256.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -41,13 +41,13 @@ NON_EMPTY_TRANSLATION_UNIT
# include <openssl/err.h>
# include "ec_lcl.h"
-# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
/* even with gcc, the typedef won't work for 32-bit platforms */
typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
* platforms */
typedef __int128_t int128_t;
# else
-# error "Need GCC 3.1 or later to define type uint128_t"
+# error "Your compiler doesn't appear to support 128-bit integer types"
# endif
typedef uint8_t u8;
@@ -1766,7 +1766,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Precomputation for the group generator. */
struct nistp256_pre_comp_st {
smallfelem g_pre_comp[2][16][3];
- int references;
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -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;
@@ -1832,7 +1837,7 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
* FUNCTIONS TO MANAGE PRECOMPUTATION
*/
-static NISTP256_PRE_COMP *nistp256_pre_comp_new()
+static NISTP256_PRE_COMP *nistp256_pre_comp_new(void)
{
NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -1856,7 +1861,7 @@ NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *p)
{
int i;
if (p != NULL)
- CRYPTO_atomic_add(&p->references, 1, &i, p->lock);
+ CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
@@ -1867,7 +1872,7 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre)
if (pre == NULL)
return;
- CRYPTO_atomic_add(&pre->references, -1, &i, pre->lock);
+ CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
REF_PRINT_COUNT("EC_nistp256", x);
if (i > 0)
return;
@@ -1902,9 +1907,10 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
- ((curve_a = BN_CTX_get(ctx)) == NULL) ||
- ((curve_b = BN_CTX_get(ctx)) == NULL))
+ curve_p = BN_CTX_get(ctx);
+ curve_a = BN_CTX_get(ctx);
+ curve_b = BN_CTX_get(ctx);
+ if (curve_b == NULL)
goto err;
BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
@@ -2012,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;
@@ -2030,14 +2035,12 @@ 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);
- if (((x = BN_CTX_get(ctx)) == NULL) ||
- ((y = BN_CTX_get(ctx)) == NULL) ||
- ((z = BN_CTX_get(ctx)) == NULL) ||
- ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ tmp_scalar = BN_CTX_get(ctx);
+ if (tmp_scalar == NULL)
goto err;
if (scalar != NULL) {
@@ -2200,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);
@@ -2224,7 +2226,9 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
goto err;
/* get the generator */
if (group->generator == NULL)
@@ -2234,7 +2238,7 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
goto err;
BN_bin2bn(nistp256_curve_params[3], sizeof(felem_bytearray), x);
BN_bin2bn(nistp256_curve_params[4], sizeof(felem_bytearray), y);
- if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx))
goto err;
if ((pre = nistp256_pre_comp_new()) == NULL)
goto err;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_nistp521.c b/deps/openssl/openssl/crypto/ec/ecp_nistp521.c
index 0a82abca1b..14f2feeb69 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_nistp521.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_nistp521.c
@@ -40,12 +40,12 @@ NON_EMPTY_TRANSLATION_UNIT
# include <openssl/err.h>
# include "ec_lcl.h"
-# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
/* even with gcc, the typedef won't work for 32-bit platforms */
typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
* platforms */
# else
-# error "Need GCC 3.1 or later to define type uint128_t"
+# error "Your compiler doesn't appear to support 128-bit integer types"
# endif
typedef uint8_t u8;
@@ -1156,9 +1156,9 @@ static void copy_conditional(felem out, const felem in, limb mask)
* adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
*
* This function includes a branch for checking whether the two input points
- * are equal (while not equal to the point at infinity). This case never
- * happens during single point multiplication, so there is no timing leak for
- * ECDH or ECDSA signing. */
+ * are equal (while not equal to the point at infinity). See comment below
+ * on constant-time.
+ */
static void point_add(felem x3, felem y3, felem z3,
const felem x1, const felem y1, const felem z1,
const int mixed, const felem x2, const felem y2,
@@ -1252,6 +1252,22 @@ static void point_add(felem x3, felem y3, felem z3,
/* ftmp5[i] < 2^61 */
if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
+ /*
+ * This is obviously not constant-time but it will almost-never happen
+ * for ECDH / ECDSA. The case where it can happen is during scalar-mult
+ * where the intermediate value gets very close to the group order.
+ * Since |ec_GFp_nistp_recode_scalar_bits| produces signed digits for
+ * the scalar, it's possible for the intermediate value to be a small
+ * negative multiple of the base point, and for the final signed digit
+ * to be the same value. We believe that this only occurs for the scalar
+ * 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ * ffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb
+ * 71e913863f7, in that case the penultimate intermediate is -9G and
+ * the final digit is also -9G. Since this only happens for a single
+ * scalar, the timing leak is irrelevent. (Any attacker who wanted to
+ * check whether a secret scalar was that exact value, can already do
+ * so.)
+ */
point_double(x3, y3, z3, x1, y1, z1);
return;
}
@@ -1587,7 +1603,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out,
/* Precomputation for the group generator. */
struct nistp521_pre_comp_st {
felem g_pre_comp[16][3];
- int references;
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -1643,7 +1659,11 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- 0 /* blind_coordinates */
+ 0, /* field_inverse_mod_ord */
+ 0, /* blind_coordinates */
+ 0, /* ladder_pre */
+ 0, /* ladder_step */
+ 0 /* ladder_post */
};
return &ret;
@@ -1654,7 +1674,7 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
* FUNCTIONS TO MANAGE PRECOMPUTATION
*/
-static NISTP521_PRE_COMP *nistp521_pre_comp_new()
+static NISTP521_PRE_COMP *nistp521_pre_comp_new(void)
{
NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -1678,7 +1698,7 @@ NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *p)
{
int i;
if (p != NULL)
- CRYPTO_atomic_add(&p->references, 1, &i, p->lock);
+ CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
@@ -1689,7 +1709,7 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p)
if (p == NULL)
return;
- CRYPTO_atomic_add(&p->references, -1, &i, p->lock);
+ CRYPTO_DOWN_REF(&p->references, &i, p->lock);
REF_PRINT_COUNT("EC_nistp521", x);
if (i > 0)
return;
@@ -1724,9 +1744,10 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
- ((curve_a = BN_CTX_get(ctx)) == NULL) ||
- ((curve_b = BN_CTX_get(ctx)) == NULL))
+ curve_p = BN_CTX_get(ctx);
+ curve_a = BN_CTX_get(ctx);
+ curve_b = BN_CTX_get(ctx);
+ if (curve_b == NULL)
goto err;
BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p);
BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a);
@@ -1834,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;
@@ -1851,14 +1871,12 @@ 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);
- if (((x = BN_CTX_get(ctx)) == NULL) ||
- ((y = BN_CTX_get(ctx)) == NULL) ||
- ((z = BN_CTX_get(ctx)) == NULL) ||
- ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ z = BN_CTX_get(ctx);
+ tmp_scalar = BN_CTX_get(ctx);
+ if (tmp_scalar == NULL)
goto err;
if (scalar != NULL) {
@@ -2019,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);
@@ -2042,7 +2059,9 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
- if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL))
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (y == NULL)
goto err;
/* get the generator */
if (group->generator == NULL)
@@ -2052,7 +2071,7 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
goto err;
BN_bin2bn(nistp521_curve_params[3], sizeof(felem_bytearray), x);
BN_bin2bn(nistp521_curve_params[4], sizeof(felem_bytearray), y);
- if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx))
goto err;
if ((pre = nistp521_pre_comp_new()) == NULL)
goto err;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_nistz256.c b/deps/openssl/openssl/crypto/ec/ecp_nistz256.c
index 7eafce649b..b0564bdbd0 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_nistz256.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_nistz256.c
@@ -1,45 +1,29 @@
/*
* Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2014, Intel Corporation. All Rights Reserved.
+ * Copyright (c) 2015, CloudFlare, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+ *
+ * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3)
+ * (1) Intel Corporation, Israel Development Center, Haifa, Israel
+ * (2) University of Haifa, Israel
+ * (3) CloudFlare, Inc.
+ *
+ * Reference:
+ * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
+ * 256 Bit Primes"
*/
-/******************************************************************************
- * *
- * Copyright 2014 Intel Corporation *
- * *
- * Licensed under the Apache License, Version 2.0 (the "License"); *
- * you may not use this file except in compliance with the License. *
- * You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, software *
- * distributed under the License is distributed on an "AS IS" BASIS, *
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
- * See the License for the specific language governing permissions and *
- * limitations under the License. *
- * *
- ******************************************************************************
- * *
- * Developers and authors: *
- * Shay Gueron (1, 2), and Vlad Krasnov (1) *
- * (1) Intel Corporation, Israel Development Center *
- * (2) University of Haifa *
- * Reference: *
- * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with *
- * 256 Bit Primes" *
- * *
- ******************************************************************************/
-
#include <string.h>
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "ec_lcl.h"
+#include "internal/refcount.h"
#if BN_BITS2 != 64
# define TOBN(hi,lo) lo,hi
@@ -84,7 +68,7 @@ struct nistz256_pre_comp_st {
*/
PRECOMP256_ROW *precomp;
void *precomp_storage;
- int references;
+ CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -254,6 +238,16 @@ static BN_ULONG is_one(const BIGNUM *z)
return res;
}
+/*
+ * For reference, this macro is used only when new ecp_nistz256 assembly
+ * module is being developed. For example, configure with
+ * -DECP_NISTZ256_REFERENCE_IMPLEMENTATION and implement only functions
+ * performing simplest arithmetic operations on 256-bit vectors. Then
+ * work on implementation of higher-level functions performing point
+ * operations. Then remove ECP_NISTZ256_REFERENCE_IMPLEMENTATION
+ * and never define it again. (The correct macro denoting presence of
+ * ecp_nistz256 module is ECP_NISTZ256_ASM.)
+ */
#ifndef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
void ecp_nistz256_point_add(P256_POINT *r,
@@ -916,7 +910,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
*/
#if defined(ECP_NISTZ256_AVX2)
# if !(defined(__x86_64) || defined(__x86_64__) || \
- defined(_M_AMD64) || defined(_MX64)) || \
+ defined(_M_AMD64) || defined(_M_X64)) || \
!(defined(__GNUC__) || defined(_MSC_VER)) /* this is for ALIGN32 */
# undef ECP_NISTZ256_AVX2
# else
@@ -1129,12 +1123,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;
@@ -1152,27 +1144,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) {
@@ -1368,9 +1339,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
ret = 1;
err:
- if (ctx)
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
+ BN_CTX_end(ctx);
OPENSSL_free(new_points);
OPENSSL_free(new_scalars);
return ret;
@@ -1451,7 +1420,7 @@ NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *p)
{
int i;
if (p != NULL)
- CRYPTO_atomic_add(&p->references, 1, &i, p->lock);
+ CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
@@ -1462,7 +1431,7 @@ void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre)
if (pre == NULL)
return;
- CRYPTO_atomic_add(&pre->references, -1, &i, pre->lock);
+ CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
REF_PRINT_COUNT("EC_nistz256", x);
if (i > 0)
return;
@@ -1487,6 +1456,189 @@ static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group)
return HAVEPRECOMP(group, nistz256);
}
+#if defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64) || \
+ defined(__powerpc64__) || defined(_ARCH_PP64) || \
+ defined(__aarch64__)
+/*
+ * Montgomery mul modulo Order(P): res = a*b*2^-256 mod Order(P)
+ */
+void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS],
+ const BN_ULONG a[P256_LIMBS],
+ const BN_ULONG b[P256_LIMBS]);
+void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS],
+ const BN_ULONG a[P256_LIMBS],
+ int rep);
+
+static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
+ const BIGNUM *x, BN_CTX *ctx)
+{
+ /* RR = 2^512 mod ord(p256) */
+ static const BN_ULONG RR[P256_LIMBS] = {
+ TOBN(0x83244c95,0xbe79eea2), TOBN(0x4699799c,0x49bd6fa6),
+ TOBN(0x2845b239,0x2b6bec59), TOBN(0x66e12d94,0xf3d95620)
+ };
+ /* The constant 1 (unlike ONE that is one in Montgomery representation) */
+ static const BN_ULONG one[P256_LIMBS] = {
+ TOBN(0,1), TOBN(0,0), TOBN(0,0), TOBN(0,0)
+ };
+ /*
+ * We don't use entry 0 in the table, so we omit it and address
+ * with -1 offset.
+ */
+ BN_ULONG table[15][P256_LIMBS];
+ BN_ULONG out[P256_LIMBS], t[P256_LIMBS];
+ int i, ret = 0;
+ enum {
+ i_1 = 0, i_10, i_11, i_101, i_111, i_1010, i_1111,
+ i_10101, i_101010, i_101111, i_x6, i_x8, i_x16, i_x32
+ };
+
+ /*
+ * Catch allocation failure early.
+ */
+ if (bn_wexpand(r, P256_LIMBS) == NULL) {
+ ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if ((BN_num_bits(x) > 256) || BN_is_negative(x)) {
+ BIGNUM *tmp;
+
+ if ((tmp = BN_CTX_get(ctx)) == NULL
+ || !BN_nnmod(tmp, x, group->order, ctx)) {
+ ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
+ goto err;
+ }
+ x = tmp;
+ }
+
+ if (!ecp_nistz256_bignum_to_field_elem(t, x)) {
+ ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE);
+ goto err;
+ }
+
+ ecp_nistz256_ord_mul_mont(table[0], t, RR);
+#if 0
+ /*
+ * Original sparse-then-fixed-window algorithm, retained for reference.
+ */
+ for (i = 2; i < 16; i += 2) {
+ ecp_nistz256_ord_sqr_mont(table[i-1], table[i/2-1], 1);
+ ecp_nistz256_ord_mul_mont(table[i], table[i-1], table[0]);
+ }
+
+ /*
+ * The top 128bit of the exponent are highly redudndant, so we
+ * perform an optimized flow
+ */
+ ecp_nistz256_ord_sqr_mont(t, table[15-1], 4); /* f0 */
+ ecp_nistz256_ord_mul_mont(t, t, table[15-1]); /* ff */
+
+ ecp_nistz256_ord_sqr_mont(out, t, 8); /* ff00 */
+ ecp_nistz256_ord_mul_mont(out, out, t); /* ffff */
+
+ ecp_nistz256_ord_sqr_mont(t, out, 16); /* ffff0000 */
+ ecp_nistz256_ord_mul_mont(t, t, out); /* ffffffff */
+
+ ecp_nistz256_ord_sqr_mont(out, t, 64); /* ffffffff0000000000000000 */
+ ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffff */
+
+ ecp_nistz256_ord_sqr_mont(out, out, 32); /* ffffffff00000000ffffffff00000000 */
+ ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffffffffffff */
+
+ /*
+ * The bottom 128 bit of the exponent are processed with fixed 4-bit window
+ */
+ for(i = 0; i < 32; i++) {
+ /* expLo - the low 128 bits of the exponent we use (ord(p256) - 2),
+ * split into nibbles */
+ static const unsigned char expLo[32] = {
+ 0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd,0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4,
+ 0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2,0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf
+ };
+
+ ecp_nistz256_ord_sqr_mont(out, out, 4);
+ /* The exponent is public, no need in constant-time access */
+ ecp_nistz256_ord_mul_mont(out, out, table[expLo[i]-1]);
+ }
+#else
+ /*
+ * https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion
+ *
+ * Even though this code path spares 12 squarings, 4.5%, and 13
+ * multiplications, 25%, on grand scale sign operation is not that
+ * much faster, not more that 2%...
+ */
+
+ /* pre-calculate powers */
+ ecp_nistz256_ord_sqr_mont(table[i_10], table[i_1], 1);
+
+ ecp_nistz256_ord_mul_mont(table[i_11], table[i_1], table[i_10]);
+
+ ecp_nistz256_ord_mul_mont(table[i_101], table[i_11], table[i_10]);
+
+ ecp_nistz256_ord_mul_mont(table[i_111], table[i_101], table[i_10]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_1010], table[i_101], 1);
+
+ ecp_nistz256_ord_mul_mont(table[i_1111], table[i_1010], table[i_101]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_10101], table[i_1010], 1);
+ ecp_nistz256_ord_mul_mont(table[i_10101], table[i_10101], table[i_1]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_101010], table[i_10101], 1);
+
+ ecp_nistz256_ord_mul_mont(table[i_101111], table[i_101010], table[i_101]);
+
+ ecp_nistz256_ord_mul_mont(table[i_x6], table[i_101010], table[i_10101]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_x8], table[i_x6], 2);
+ ecp_nistz256_ord_mul_mont(table[i_x8], table[i_x8], table[i_11]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_x16], table[i_x8], 8);
+ ecp_nistz256_ord_mul_mont(table[i_x16], table[i_x16], table[i_x8]);
+
+ ecp_nistz256_ord_sqr_mont(table[i_x32], table[i_x16], 16);
+ ecp_nistz256_ord_mul_mont(table[i_x32], table[i_x32], table[i_x16]);
+
+ /* calculations */
+ ecp_nistz256_ord_sqr_mont(out, table[i_x32], 64);
+ ecp_nistz256_ord_mul_mont(out, out, table[i_x32]);
+
+ for (i = 0; i < 27; i++) {
+ static const struct { unsigned char p, i; } chain[27] = {
+ { 32, i_x32 }, { 6, i_101111 }, { 5, i_111 },
+ { 4, i_11 }, { 5, i_1111 }, { 5, i_10101 },
+ { 4, i_101 }, { 3, i_101 }, { 3, i_101 },
+ { 5, i_111 }, { 9, i_101111 }, { 6, i_1111 },
+ { 2, i_1 }, { 5, i_1 }, { 6, i_1111 },
+ { 5, i_111 }, { 4, i_111 }, { 5, i_111 },
+ { 5, i_101 }, { 3, i_11 }, { 10, i_101111 },
+ { 2, i_11 }, { 5, i_11 }, { 5, i_11 },
+ { 3, i_1 }, { 7, i_10101 }, { 6, i_1111 }
+ };
+
+ ecp_nistz256_ord_sqr_mont(out, out, chain[i].p);
+ ecp_nistz256_ord_mul_mont(out, out, table[chain[i].i]);
+ }
+#endif
+ ecp_nistz256_ord_mul_mont(out, out, one);
+
+ /*
+ * Can't fail, but check return code to be consistent anyway.
+ */
+ if (!bn_set_words(r, out, P256_LIMBS))
+ goto err;
+
+ ret = 1;
+err:
+ return ret;
+}
+#else
+# define ecp_nistz256_inv_mod_ord NULL
+#endif
+
const EC_METHOD *EC_GFp_nistz256_method(void)
{
static const EC_METHOD ret = {
@@ -1537,7 +1689,11 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- 0 /* blind_coordinates */
+ ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
+ 0, /* blind_coordinates */
+ 0, /* ladder_pre */
+ 0, /* ladder_step */
+ 0 /* ladder_post */
};
return &ret;
diff --git a/deps/openssl/openssl/crypto/ec/ecp_oct.c b/deps/openssl/openssl/crypto/ec/ecp_oct.c
index 4d142a4ab9..7ade1b3d21 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_oct.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_oct.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions of this software developed by SUN MICROSYSTEMS, INC.,
- * and contributed to the OpenSSL project.
- */
-
#include <openssl/err.h>
#include <openssl/symhacks.h>
@@ -130,7 +125,7 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
EC_R_INVALID_COMPRESSION_BIT);
else
/*
- * BN_mod_sqrt() should have cought this error (not a square)
+ * BN_mod_sqrt() should have caught this error (not a square)
*/
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
EC_R_INVALID_COMPRESSED_POINT);
@@ -145,7 +140,7 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
}
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
ret = 1;
@@ -211,7 +206,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
if (y == NULL)
goto err;
- if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
if ((form == POINT_CONVERSION_COMPRESSED
@@ -338,8 +333,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
}
if (form == POINT_CONVERSION_COMPRESSED) {
- if (!EC_POINT_set_compressed_coordinates_GFp
- (group, point, x, y_bit, ctx))
+ if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx))
goto err;
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
@@ -356,10 +350,10 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
}
/*
- * EC_POINT_set_affine_coordinates_GFp is responsible for checking that
+ * EC_POINT_set_affine_coordinates is responsible for checking that
* the point is on the curve.
*/
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
}
diff --git a/deps/openssl/openssl/crypto/ec/ecp_smpl.c b/deps/openssl/openssl/crypto/ec/ecp_smpl.c
index adfb194576..d0c5557ff4 100644
--- a/deps/openssl/openssl/crypto/ec/ecp_smpl.c
+++ b/deps/openssl/openssl/crypto/ec/ecp_smpl.c
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,12 +8,6 @@
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- * Portions of this software developed by SUN MICROSYSTEMS, INC.,
- * and contributed to the OpenSSL project.
- */
-
#include <openssl/err.h>
#include <openssl/symhacks.h>
@@ -68,7 +63,11 @@ const EC_METHOD *EC_GFp_simple_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- ec_GFp_simple_blind_coordinates
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates,
+ ec_GFp_simple_ladder_pre,
+ ec_GFp_simple_ladder_step,
+ ec_GFp_simple_ladder_post
};
return &ret;
@@ -1182,9 +1181,9 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
if (y == NULL)
goto err;
- if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
+ if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!point->Z_is_one) {
ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
@@ -1220,7 +1219,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
tmp_Z = BN_CTX_get(ctx);
- if (tmp == NULL || tmp_Z == NULL)
+ if (tmp_Z == NULL)
goto err;
prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0]));
@@ -1394,7 +1393,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
/* make sure lambda is not zero */
do {
- if (!BN_rand_range(lambda, group->field)) {
+ if (!BN_priv_rand_range(lambda, group->field)) {
ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB);
goto err;
}
@@ -1419,6 +1418,227 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
ret = 1;
err:
- BN_CTX_end(ctx);
- return ret;
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*-
+ * Set s := p, r := 2p.
+ *
+ * For doubling we use Formula 3 from Izu-Takagi "A fast parallel elliptic curve
+ * multiplication resistant against side channel attacks" appendix, as described
+ * at
+ * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#doubling-dbl-2002-it-2
+ *
+ * The input point p will be in randomized Jacobian projective coords:
+ * x = X/Z**2, y=Y/Z**3
+ *
+ * The output points p, s, and r are converted to standard (homogeneous)
+ * projective coords:
+ * x = X/Z, y=Y/Z
+ */
+int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx)
+{
+ BIGNUM *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
+
+ t1 = r->Z;
+ t2 = r->Y;
+ t3 = s->X;
+ t4 = r->X;
+ t5 = s->Y;
+ t6 = s->Z;
+
+ /* convert p: (X,Y,Z) -> (XZ,Y,Z**3) */
+ if (!group->meth->field_mul(group, p->X, p->X, p->Z, ctx)
+ || !group->meth->field_sqr(group, t1, p->Z, ctx)
+ || !group->meth->field_mul(group, p->Z, p->Z, t1, ctx)
+ /* r := 2p */
+ || !group->meth->field_sqr(group, t2, p->X, ctx)
+ || !group->meth->field_sqr(group, t3, p->Z, ctx)
+ || !group->meth->field_mul(group, t4, t3, group->a, ctx)
+ || !BN_mod_sub_quick(t5, t2, t4, group->field)
+ || !BN_mod_add_quick(t2, t2, t4, group->field)
+ || !group->meth->field_sqr(group, t5, t5, ctx)
+ || !group->meth->field_mul(group, t6, t3, group->b, ctx)
+ || !group->meth->field_mul(group, t1, p->X, p->Z, ctx)
+ || !group->meth->field_mul(group, t4, t1, t6, ctx)
+ || !BN_mod_lshift_quick(t4, t4, 3, group->field)
+ /* r->X coord output */
+ || !BN_mod_sub_quick(r->X, t5, t4, group->field)
+ || !group->meth->field_mul(group, t1, t1, t2, ctx)
+ || !group->meth->field_mul(group, t2, t3, t6, ctx)
+ || !BN_mod_add_quick(t1, t1, t2, group->field)
+ /* r->Z coord output */
+ || !BN_mod_lshift_quick(r->Z, t1, 2, group->field)
+ || !EC_POINT_copy(s, p))
+ return 0;
+
+ r->Z_is_one = 0;
+ s->Z_is_one = 0;
+ p->Z_is_one = 0;
+
+ return 1;
+}
+
+/*-
+ * Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi
+ * "A fast parallel elliptic curve multiplication resistant against side channel
+ * attacks", as described at
+ * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-ladd-2002-it-4
+ */
+int ec_GFp_simple_ladder_step(const EC_GROUP *group,
+ EC_POINT *r, EC_POINT *s,
+ EC_POINT *p, BN_CTX *ctx)
+{
+ int ret = 0;
+ BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7 = NULL;
+
+ BN_CTX_start(ctx);
+ t0 = BN_CTX_get(ctx);
+ t1 = BN_CTX_get(ctx);
+ t2 = BN_CTX_get(ctx);
+ t3 = BN_CTX_get(ctx);
+ t4 = BN_CTX_get(ctx);
+ t5 = BN_CTX_get(ctx);
+ t6 = BN_CTX_get(ctx);
+ t7 = BN_CTX_get(ctx);
+
+ if (t7 == NULL
+ || !group->meth->field_mul(group, t0, r->X, s->X, ctx)
+ || !group->meth->field_mul(group, t1, r->Z, s->Z, ctx)
+ || !group->meth->field_mul(group, t2, r->X, s->Z, ctx)
+ || !group->meth->field_mul(group, t3, r->Z, s->X, ctx)
+ || !group->meth->field_mul(group, t4, group->a, t1, ctx)
+ || !BN_mod_add_quick(t0, t0, t4, group->field)
+ || !BN_mod_add_quick(t4, t3, t2, group->field)
+ || !group->meth->field_mul(group, t0, t4, t0, ctx)
+ || !group->meth->field_sqr(group, t1, t1, ctx)
+ || !BN_mod_lshift_quick(t7, group->b, 2, group->field)
+ || !group->meth->field_mul(group, t1, t7, t1, ctx)
+ || !BN_mod_lshift1_quick(t0, t0, group->field)
+ || !BN_mod_add_quick(t0, t1, t0, group->field)
+ || !BN_mod_sub_quick(t1, t2, t3, group->field)
+ || !group->meth->field_sqr(group, t1, t1, ctx)
+ || !group->meth->field_mul(group, t3, t1, p->X, ctx)
+ || !group->meth->field_mul(group, t0, p->Z, t0, ctx)
+ /* s->X coord output */
+ || !BN_mod_sub_quick(s->X, t0, t3, group->field)
+ /* s->Z coord output */
+ || !group->meth->field_mul(group, s->Z, p->Z, t1, ctx)
+ || !group->meth->field_sqr(group, t3, r->X, ctx)
+ || !group->meth->field_sqr(group, t2, r->Z, ctx)
+ || !group->meth->field_mul(group, t4, t2, group->a, ctx)
+ || !BN_mod_add_quick(t5, r->X, r->Z, group->field)
+ || !group->meth->field_sqr(group, t5, t5, ctx)
+ || !BN_mod_sub_quick(t5, t5, t3, group->field)
+ || !BN_mod_sub_quick(t5, t5, t2, group->field)
+ || !BN_mod_sub_quick(t6, t3, t4, group->field)
+ || !group->meth->field_sqr(group, t6, t6, ctx)
+ || !group->meth->field_mul(group, t0, t2, t5, ctx)
+ || !group->meth->field_mul(group, t0, t7, t0, ctx)
+ /* r->X coord output */
+ || !BN_mod_sub_quick(r->X, t6, t0, group->field)
+ || !BN_mod_add_quick(t6, t3, t4, group->field)
+ || !group->meth->field_sqr(group, t3, t2, ctx)
+ || !group->meth->field_mul(group, t7, t3, t7, ctx)
+ || !group->meth->field_mul(group, t5, t5, t6, ctx)
+ || !BN_mod_lshift1_quick(t5, t5, group->field)
+ /* r->Z coord output */
+ || !BN_mod_add_quick(r->Z, t7, t5, group->field))
+ goto err;
+
+ ret = 1;
+
+ err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+/*-
+ * Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass
+ * Elliptic Curves and Side-Channel Attacks", modified to work in projective
+ * coordinates and return r in Jacobian projective coordinates.
+ *
+ * X4 = two*Y1*X2*Z3*Z2*Z1;
+ * Y4 = two*b*Z3*SQR(Z2*Z1) + Z3*(a*Z2*Z1+X1*X2)*(X1*Z2+X2*Z1) - X3*SQR(X1*Z2-X2*Z1);
+ * Z4 = two*Y1*Z3*SQR(Z2)*Z1;
+ *
+ * Z4 != 0 because:
+ * - Z1==0 implies p is at infinity, which would have caused an early exit in
+ * the caller;
+ * - Z2==0 implies r is at infinity (handled by the BN_is_zero(r->Z) branch);
+ * - Z3==0 implies s is at infinity (handled by the BN_is_zero(s->Z) branch);
+ * - Y1==0 implies p has order 2, so either r or s are infinity and handled by
+ * one of the BN_is_zero(...) branches.
+ */
+int ec_GFp_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, *t3, *t4, *t5, *t6 = NULL;
+
+ if (BN_is_zero(r->Z))
+ return EC_POINT_set_to_infinity(group, r);
+
+ if (BN_is_zero(s->Z)) {
+ /* (X,Y,Z) -> (XZ,YZ**2,Z) */
+ if (!group->meth->field_mul(group, r->X, p->X, p->Z, ctx)
+ || !group->meth->field_sqr(group, r->Z, p->Z, ctx)
+ || !group->meth->field_mul(group, r->Y, p->Y, r->Z, ctx)
+ || !BN_copy(r->Z, p->Z)
+ || !EC_POINT_invert(group, r, ctx))
+ return 0;
+ return 1;
+ }
+
+ BN_CTX_start(ctx);
+ t0 = BN_CTX_get(ctx);
+ t1 = BN_CTX_get(ctx);
+ t2 = BN_CTX_get(ctx);
+ t3 = BN_CTX_get(ctx);
+ t4 = BN_CTX_get(ctx);
+ t5 = BN_CTX_get(ctx);
+ t6 = BN_CTX_get(ctx);
+
+ if (t6 == NULL
+ || !BN_mod_lshift1_quick(t0, p->Y, group->field)
+ || !group->meth->field_mul(group, t1, r->X, p->Z, ctx)
+ || !group->meth->field_mul(group, t2, r->Z, s->Z, ctx)
+ || !group->meth->field_mul(group, t2, t1, t2, ctx)
+ || !group->meth->field_mul(group, t3, t2, t0, ctx)
+ || !group->meth->field_mul(group, t2, r->Z, p->Z, ctx)
+ || !group->meth->field_sqr(group, t4, t2, ctx)
+ || !BN_mod_lshift1_quick(t5, group->b, group->field)
+ || !group->meth->field_mul(group, t4, t4, t5, ctx)
+ || !group->meth->field_mul(group, t6, t2, group->a, ctx)
+ || !group->meth->field_mul(group, t5, r->X, p->X, ctx)
+ || !BN_mod_add_quick(t5, t6, t5, group->field)
+ || !group->meth->field_mul(group, t6, r->Z, p->X, ctx)
+ || !BN_mod_add_quick(t2, t6, t1, group->field)
+ || !group->meth->field_mul(group, t5, t5, t2, ctx)
+ || !BN_mod_sub_quick(t6, t6, t1, group->field)
+ || !group->meth->field_sqr(group, t6, t6, ctx)
+ || !group->meth->field_mul(group, t6, t6, s->X, ctx)
+ || !BN_mod_add_quick(t4, t5, t4, group->field)
+ || !group->meth->field_mul(group, t4, t4, s->Z, ctx)
+ || !BN_mod_sub_quick(t4, t4, t6, group->field)
+ || !group->meth->field_sqr(group, t5, r->Z, ctx)
+ || !group->meth->field_mul(group, r->Z, p->Z, s->Z, ctx)
+ || !group->meth->field_mul(group, r->Z, t5, r->Z, ctx)
+ || !group->meth->field_mul(group, r->Z, r->Z, t0, ctx)
+ /* t3 := X, t4 := Y */
+ /* (X,Y,Z) -> (XZ,YZ**2,Z) */
+ || !group->meth->field_mul(group, r->X, t3, r->Z, ctx)
+ || !group->meth->field_sqr(group, t3, r->Z, ctx)
+ || !group->meth->field_mul(group, r->Y, t4, t3, ctx))
+ goto err;
+
+ ret = 1;
+
+ err:
+ BN_CTX_end(ctx);
+ return ret;
}
diff --git a/deps/openssl/openssl/crypto/ec/ecx_meth.c b/deps/openssl/openssl/crypto/ec/ecx_meth.c
index 018a9419f0..b76bfdb6dc 100644
--- a/deps/openssl/openssl/crypto/ec/ecx_meth.c
+++ b/deps/openssl/openssl/crypto/ec/ecx_meth.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -16,28 +16,39 @@
#include "internal/evp_int.h"
#include "ec_lcl.h"
-#define X25519_KEYLEN 32
#define X25519_BITS 253
#define X25519_SECURITY_BITS 128
-typedef struct {
- unsigned char pubkey[X25519_KEYLEN];
- unsigned char *privkey;
-} X25519_KEY;
+#define ED25519_SIGSIZE 64
+
+#define X448_BITS 448
+#define ED448_BITS 456
+#define X448_SECURITY_BITS 224
+
+#define ED448_SIGSIZE 114
+
+#define ISX448(id) ((id) == EVP_PKEY_X448)
+#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
+#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
+ : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
+ : ED448_KEYLEN))
+#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
+
typedef enum {
- X25519_PUBLIC,
- X25519_PRIVATE,
- X25519_KEYGEN
+ KEY_OP_PUBLIC,
+ KEY_OP_PRIVATE,
+ KEY_OP_KEYGEN
} ecx_key_op_t;
/* Setup EVP_PKEY using public, private or generation */
-static int ecx_key_op(EVP_PKEY *pkey, const X509_ALGOR *palg,
+static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
const unsigned char *p, int plen, ecx_key_op_t op)
{
- X25519_KEY *xkey;
+ ECX_KEY *key = NULL;
+ unsigned char *privkey, *pubkey;
- if (op != X25519_KEYGEN) {
+ if (op != KEY_OP_KEYGEN) {
if (palg != NULL) {
int ptype;
@@ -49,64 +60,85 @@ static int ecx_key_op(EVP_PKEY *pkey, const X509_ALGOR *palg,
}
}
- if (p == NULL || plen != X25519_KEYLEN) {
+ if (p == NULL || plen != KEYLENID(id)) {
ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
return 0;
}
}
- xkey = OPENSSL_zalloc(sizeof(*xkey));
- if (xkey == NULL) {
+ key = OPENSSL_zalloc(sizeof(*key));
+ if (key == NULL) {
ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
return 0;
}
+ pubkey = key->pubkey;
- if (op == X25519_PUBLIC) {
- memcpy(xkey->pubkey, p, plen);
+ if (op == KEY_OP_PUBLIC) {
+ memcpy(pubkey, p, plen);
} else {
- xkey->privkey = OPENSSL_secure_malloc(X25519_KEYLEN);
- if (xkey->privkey == NULL) {
+ privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id));
+ if (privkey == NULL) {
ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(xkey);
- return 0;
+ goto err;
}
- if (op == X25519_KEYGEN) {
- if (RAND_bytes(xkey->privkey, X25519_KEYLEN) <= 0) {
- OPENSSL_secure_free(xkey->privkey);
- OPENSSL_free(xkey);
- return 0;
+ if (op == KEY_OP_KEYGEN) {
+ if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) {
+ OPENSSL_secure_free(privkey);
+ key->privkey = NULL;
+ goto err;
+ }
+ if (id == EVP_PKEY_X25519) {
+ privkey[0] &= 248;
+ privkey[X25519_KEYLEN - 1] &= 127;
+ privkey[X25519_KEYLEN - 1] |= 64;
+ } else if (id == EVP_PKEY_X448) {
+ privkey[0] &= 252;
+ privkey[X448_KEYLEN - 1] |= 128;
}
- xkey->privkey[0] &= 248;
- xkey->privkey[31] &= 127;
- xkey->privkey[31] |= 64;
} else {
- memcpy(xkey->privkey, p, X25519_KEYLEN);
+ memcpy(privkey, p, KEYLENID(id));
+ }
+ switch (id) {
+ case EVP_PKEY_X25519:
+ X25519_public_from_private(pubkey, privkey);
+ break;
+ case EVP_PKEY_ED25519:
+ ED25519_public_from_private(pubkey, privkey);
+ break;
+ case EVP_PKEY_X448:
+ X448_public_from_private(pubkey, privkey);
+ break;
+ case EVP_PKEY_ED448:
+ ED448_public_from_private(pubkey, privkey);
+ break;
}
- X25519_public_from_private(xkey->pubkey, xkey->privkey);
}
- EVP_PKEY_assign(pkey, NID_X25519, xkey);
+ EVP_PKEY_assign(pkey, id, key);
return 1;
+ err:
+ OPENSSL_free(key);
+ return 0;
}
static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
- const X25519_KEY *xkey = pkey->pkey.ptr;
+ const ECX_KEY *ecxkey = pkey->pkey.ecx;
unsigned char *penc;
- if (xkey == NULL) {
+ if (ecxkey == NULL) {
ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
return 0;
}
- penc = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
+ penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
if (penc == NULL) {
ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
return 0;
}
- if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(NID_X25519), V_ASN1_UNDEF,
- NULL, penc, X25519_KEYLEN)) {
+ if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
+ V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
OPENSSL_free(penc);
ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
return 0;
@@ -122,17 +154,19 @@ static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
- return ecx_key_op(pkey, palg, p, pklen, X25519_PUBLIC);
+ return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
+ KEY_OP_PUBLIC);
}
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
- const X25519_KEY *akey = a->pkey.ptr;
- const X25519_KEY *bkey = b->pkey.ptr;
+ const ECX_KEY *akey = a->pkey.ecx;
+ const ECX_KEY *bkey = b->pkey.ecx;
if (akey == NULL || bkey == NULL)
return -2;
- return !CRYPTO_memcmp(akey->pubkey, bkey->pubkey, X25519_KEYLEN);
+
+ return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
}
static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
@@ -155,25 +189,25 @@ static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
plen = ASN1_STRING_length(oct);
}
- rv = ecx_key_op(pkey, palg, p, plen, X25519_PRIVATE);
+ rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE);
ASN1_OCTET_STRING_free(oct);
return rv;
}
static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
{
- const X25519_KEY *xkey = pkey->pkey.ptr;
+ const ECX_KEY *ecxkey = pkey->pkey.ecx;
ASN1_OCTET_STRING oct;
unsigned char *penc = NULL;
int penclen;
- if (xkey == NULL || xkey->privkey == NULL) {
+ if (ecxkey == NULL || ecxkey->privkey == NULL) {
ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
- oct.data = xkey->privkey;
- oct.length = X25519_KEYLEN;
+ oct.data = ecxkey->privkey;
+ oct.length = KEYLEN(pkey);
oct.flags = 0;
penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
@@ -182,7 +216,7 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
return 0;
}
- if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X25519), 0,
+ if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
V_ASN1_UNDEF, NULL, penc, penclen)) {
OPENSSL_clear_free(penc, penclen);
ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
@@ -194,26 +228,34 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
static int ecx_size(const EVP_PKEY *pkey)
{
- return X25519_KEYLEN;
+ return KEYLEN(pkey);
}
static int ecx_bits(const EVP_PKEY *pkey)
{
- return X25519_BITS;
+ if (IS25519(pkey->ameth->pkey_id)) {
+ return X25519_BITS;
+ } else if(ISX448(pkey->ameth->pkey_id)) {
+ return X448_BITS;
+ } else {
+ return ED448_BITS;
+ }
}
static int ecx_security_bits(const EVP_PKEY *pkey)
{
- return X25519_SECURITY_BITS;
+ if (IS25519(pkey->ameth->pkey_id)) {
+ return X25519_SECURITY_BITS;
+ } else {
+ return X448_SECURITY_BITS;
+ }
}
static void ecx_free(EVP_PKEY *pkey)
{
- X25519_KEY *xkey = pkey->pkey.ptr;
-
- if (xkey)
- OPENSSL_secure_clear_free(xkey->privkey, X25519_KEYLEN);
- OPENSSL_free(xkey);
+ if (pkey->pkey.ecx != NULL)
+ OPENSSL_secure_clear_free(pkey->pkey.ecx->privkey, KEYLEN(pkey));
+ OPENSSL_free(pkey->pkey.ecx);
}
/* "parameters" are always equal */
@@ -225,32 +267,36 @@ static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx, ecx_key_op_t op)
{
- const X25519_KEY *xkey = pkey->pkey.ptr;
+ const ECX_KEY *ecxkey = pkey->pkey.ecx;
+ const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
- if (op == X25519_PRIVATE) {
- if (xkey == NULL || xkey->privkey == NULL) {
+ if (op == KEY_OP_PRIVATE) {
+ if (ecxkey == NULL || ecxkey->privkey == NULL) {
if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
return 0;
return 1;
}
- if (BIO_printf(bp, "%*sX25519 Private-Key:\n", indent, "") <= 0)
+ if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
return 0;
if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
return 0;
- if (ASN1_buf_print(bp, xkey->privkey, X25519_KEYLEN, indent + 4) == 0)
+ if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
+ indent + 4) == 0)
return 0;
} else {
- if (xkey == NULL) {
+ if (ecxkey == NULL) {
if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
return 0;
return 1;
}
- if (BIO_printf(bp, "%*sX25519 Public-Key:\n", indent, "") <= 0)
+ if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
return 0;
}
if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
return 0;
- if (ASN1_buf_print(bp, xkey->pubkey, X25519_KEYLEN, indent + 4) == 0)
+
+ if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
+ indent + 4) == 0)
return 0;
return 1;
}
@@ -258,13 +304,13 @@ static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
- return ecx_key_print(bp, pkey, indent, ctx, X25519_PRIVATE);
+ return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
}
static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
- return ecx_key_print(bp, pkey, indent, ctx, X25519_PUBLIC);
+ return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
}
static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
@@ -272,20 +318,31 @@ static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
switch (op) {
case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
- return ecx_key_op(pkey, NULL, arg2, arg1, X25519_PUBLIC);
+ return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
+ KEY_OP_PUBLIC);
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
- if (pkey->pkey.ptr != NULL) {
- const X25519_KEY *xkey = pkey->pkey.ptr;
+ if (pkey->pkey.ecx != NULL) {
unsigned char **ppt = arg2;
- *ppt = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
+
+ *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
if (*ppt != NULL)
- return X25519_KEYLEN;
+ return KEYLEN(pkey);
}
return 0;
+ default:
+ return -2;
+
+ }
+}
+
+static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+ switch (op) {
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
- *(int *)arg2 = NID_sha256;
+ /* We currently only support Pure EdDSA which takes no digest */
+ *(int *)arg2 = NID_undef;
return 2;
default:
@@ -294,9 +351,63 @@ static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
}
}
+static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
+ size_t len)
+{
+ return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
+ KEY_OP_PRIVATE);
+}
+
+static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
+{
+ return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
+ KEY_OP_PUBLIC);
+}
+
+static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
+ size_t *len)
+{
+ const ECX_KEY *key = pkey->pkey.ecx;
+
+ if (priv == NULL) {
+ *len = KEYLENID(pkey->ameth->pkey_id);
+ return 1;
+ }
+
+ if (key == NULL
+ || key->privkey == NULL
+ || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
+ return 0;
+
+ *len = KEYLENID(pkey->ameth->pkey_id);
+ memcpy(priv, key->privkey, *len);
+
+ return 1;
+}
+
+static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
+ size_t *len)
+{
+ const ECX_KEY *key = pkey->pkey.ecx;
+
+ if (pub == NULL) {
+ *len = KEYLENID(pkey->ameth->pkey_id);
+ return 1;
+ }
+
+ if (key == NULL
+ || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
+ return 0;
+
+ *len = KEYLENID(pkey->ameth->pkey_id);
+ memcpy(pub, key->pubkey, *len);
+
+ return 1;
+}
+
const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
- NID_X25519,
- NID_X25519,
+ EVP_PKEY_X25519,
+ EVP_PKEY_X25519,
0,
"X25519",
"OpenSSL X25519 algorithm",
@@ -321,36 +432,277 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
ecx_free,
ecx_ctrl,
NULL,
- NULL
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+
+ ecx_set_priv_key,
+ ecx_set_pub_key,
+ ecx_get_priv_key,
+ ecx_get_pub_key,
+};
+
+const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
+ EVP_PKEY_X448,
+ EVP_PKEY_X448,
+ 0,
+ "X448",
+ "OpenSSL X448 algorithm",
+
+ ecx_pub_decode,
+ ecx_pub_encode,
+ ecx_pub_cmp,
+ ecx_pub_print,
+
+ ecx_priv_decode,
+ ecx_priv_encode,
+ ecx_priv_print,
+
+ ecx_size,
+ ecx_bits,
+ ecx_security_bits,
+
+ 0, 0, 0, 0,
+ ecx_cmp_parameters,
+ 0, 0,
+
+ ecx_free,
+ ecx_ctrl,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+
+ ecx_set_priv_key,
+ ecx_set_pub_key,
+ ecx_get_priv_key,
+ ecx_get_pub_key,
+};
+
+static int ecd_size25519(const EVP_PKEY *pkey)
+{
+ return ED25519_SIGSIZE;
+}
+
+static int ecd_size448(const EVP_PKEY *pkey)
+{
+ return ED448_SIGSIZE;
+}
+
+static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *sigalg, ASN1_BIT_STRING *str,
+ EVP_PKEY *pkey)
+{
+ const ASN1_OBJECT *obj;
+ int ptype;
+ int nid;
+
+ /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
+ X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
+ nid = OBJ_obj2nid(obj);
+ if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
+ ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING);
+ return 0;
+ }
+
+ if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
+ return 0;
+
+ return 2;
+}
+
+static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *alg1, X509_ALGOR *alg2,
+ ASN1_BIT_STRING *str)
+{
+ /* Set algorithms identifiers */
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
+ if (alg2)
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
+ /* Algorithm idetifiers set: carry on as normal */
+ return 3;
+}
+
+static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
+ const ASN1_STRING *sig)
+{
+ X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
+ X509_SIG_INFO_TLS);
+ return 1;
+}
+
+static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+ X509_ALGOR *alg1, X509_ALGOR *alg2,
+ ASN1_BIT_STRING *str)
+{
+ /* Set algorithm identifier */
+ X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
+ if (alg2 != NULL)
+ X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
+ /* Algorithm identifier set: carry on as normal */
+ return 3;
+}
+
+static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
+ const ASN1_STRING *sig)
+{
+ X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
+ X509_SIG_INFO_TLS);
+ return 1;
+}
+
+
+const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
+ EVP_PKEY_ED25519,
+ EVP_PKEY_ED25519,
+ 0,
+ "ED25519",
+ "OpenSSL ED25519 algorithm",
+
+ ecx_pub_decode,
+ ecx_pub_encode,
+ ecx_pub_cmp,
+ ecx_pub_print,
+
+ ecx_priv_decode,
+ ecx_priv_encode,
+ ecx_priv_print,
+
+ ecd_size25519,
+ ecx_bits,
+ ecx_security_bits,
+
+ 0, 0, 0, 0,
+ ecx_cmp_parameters,
+ 0, 0,
+
+ ecx_free,
+ ecd_ctrl,
+ NULL,
+ NULL,
+ ecd_item_verify,
+ ecd_item_sign25519,
+ ecd_sig_info_set25519,
+
+ NULL,
+ NULL,
+ NULL,
+
+ ecx_set_priv_key,
+ ecx_set_pub_key,
+ ecx_get_priv_key,
+ ecx_get_pub_key,
+};
+
+const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
+ EVP_PKEY_ED448,
+ EVP_PKEY_ED448,
+ 0,
+ "ED448",
+ "OpenSSL ED448 algorithm",
+
+ ecx_pub_decode,
+ ecx_pub_encode,
+ ecx_pub_cmp,
+ ecx_pub_print,
+
+ ecx_priv_decode,
+ ecx_priv_encode,
+ ecx_priv_print,
+
+ ecd_size448,
+ ecx_bits,
+ ecx_security_bits,
+
+ 0, 0, 0, 0,
+ ecx_cmp_parameters,
+ 0, 0,
+
+ ecx_free,
+ ecd_ctrl,
+ NULL,
+ NULL,
+ ecd_item_verify,
+ ecd_item_sign448,
+ ecd_sig_info_set448,
+
+ NULL,
+ NULL,
+ NULL,
+
+ ecx_set_priv_key,
+ ecx_set_pub_key,
+ ecx_get_priv_key,
+ ecx_get_pub_key,
};
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
- return ecx_key_op(pkey, NULL, NULL, 0, X25519_KEYGEN);
+ return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN);
}
-static int pkey_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
- size_t *keylen)
+static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
+ size_t *keylen,
+ const unsigned char **privkey,
+ const unsigned char **pubkey)
{
- const X25519_KEY *pkey, *peerkey;
+ const ECX_KEY *ecxkey, *peerkey;
if (ctx->pkey == NULL || ctx->peerkey == NULL) {
- ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_KEYS_NOT_SET);
+ ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET);
return 0;
}
- pkey = ctx->pkey->pkey.ptr;
- peerkey = ctx->peerkey->pkey.ptr;
- if (pkey == NULL || pkey->privkey == NULL) {
- ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
+ ecxkey = ctx->pkey->pkey.ecx;
+ peerkey = ctx->peerkey->pkey.ecx;
+ if (ecxkey == NULL || ecxkey->privkey == NULL) {
+ ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
if (peerkey == NULL) {
- ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
+ ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
return 0;
}
+ *privkey = ecxkey->privkey;
+ *pubkey = peerkey->pubkey;
+
+ return 1;
+}
+
+static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
+ size_t *keylen)
+{
+ const unsigned char *privkey, *pubkey;
+
+ if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
+ || (key != NULL
+ && X25519(key, privkey, pubkey) == 0))
+ return 0;
*keylen = X25519_KEYLEN;
- if (key != NULL && X25519(key, pkey->privkey, peerkey->pubkey) == 0)
+ return 1;
+}
+
+static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
+ size_t *keylen)
+{
+ const unsigned char *privkey, *pubkey;
+
+ if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
+ || (key != NULL
+ && X448(key, privkey, pubkey) == 0))
return 0;
+ *keylen = X448_KEYLEN;
return 1;
}
@@ -363,11 +715,126 @@ static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
}
const EVP_PKEY_METHOD ecx25519_pkey_meth = {
- NID_X25519,
+ EVP_PKEY_X25519,
+ 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecx_keygen,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecx_derive25519,
+ pkey_ecx_ctrl,
+ 0
+};
+
+const EVP_PKEY_METHOD ecx448_pkey_meth = {
+ EVP_PKEY_X448,
0, 0, 0, 0, 0, 0, 0,
pkey_ecx_keygen,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- pkey_ecx_derive,
+ pkey_ecx_derive448,
pkey_ecx_ctrl,
0
};
+
+static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
+ size_t *siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+
+ if (sig == NULL) {
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+ }
+ if (*siglen < ED25519_SIGSIZE) {
+ ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0)
+ return 0;
+ *siglen = ED25519_SIGSIZE;
+ return 1;
+}
+
+static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
+ size_t *siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+
+ if (sig == NULL) {
+ *siglen = ED448_SIGSIZE;
+ return 1;
+ }
+ if (*siglen < ED448_SIGSIZE) {
+ ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
+ 0) == 0)
+ return 0;
+ *siglen = ED448_SIGSIZE;
+ return 1;
+}
+
+static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+
+ if (siglen != ED25519_SIGSIZE)
+ return 0;
+
+ return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
+}
+
+static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
+ size_t siglen, const unsigned char *tbs,
+ size_t tbslen)
+{
+ const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
+
+ if (siglen != ED448_SIGSIZE)
+ return 0;
+
+ return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0);
+}
+
+static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+ switch (type) {
+ case EVP_PKEY_CTRL_MD:
+ /* Only NULL allowed as digest */
+ if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
+ return 1;
+ ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
+ return 0;
+
+ case EVP_PKEY_CTRL_DIGESTINIT:
+ return 1;
+ }
+ return -2;
+}
+
+const EVP_PKEY_METHOD ed25519_pkey_meth = {
+ EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+ 0, 0, 0, 0, 0, 0,
+ pkey_ecx_keygen,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecd_ctrl,
+ 0,
+ pkey_ecd_digestsign25519,
+ pkey_ecd_digestverify25519
+};
+
+const EVP_PKEY_METHOD ed448_pkey_meth = {
+ EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+ 0, 0, 0, 0, 0, 0,
+ pkey_ecx_keygen,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pkey_ecd_ctrl,
+ 0,
+ pkey_ecd_digestsign448,
+ pkey_ecd_digestverify448
+};