OpenSSL 1.1.1-pre2

This commit is contained in:
Hakase
2018-04-07 17:29:40 +09:00
parent 82a44d2483
commit bbac8ca55d
17755 changed files with 221242 additions and 98415 deletions
+2 -2
View File
@@ -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
+2 -2
View File
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
# 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
@@ -663,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
+11 -31
View File
@@ -1,39 +1,19 @@
#! /usr/bin/env perl
# Copyright 2014-2016 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));
+2382
View File
@@ -0,0 +1,2382 @@
#! /usr/bin/env perl
# Copyright 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
#
# ====================================================================
# 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-1($out)
srdi r0,r0,8
stb r0,64*1-1($out)
srdi r0,r0,8
stb r0,64*2-1($out)
srdi r0,r0,8
stb r0,64*3-1($out)
srdi r0,r0,8
stb r0,64*4-1($out)
srdi r0,r0,8
stb r0,64*5-1($out)
srdi r0,r0,8
stb r0,64*6-1($out)
srdi r0,r0,8
stb r0,64*7-1($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
+4 -4
View File
@@ -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.=<<___;
+2 -2
View File
@@ -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);
+4 -2
View File
@@ -1,15 +1,17 @@
#! /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
#
# Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1)
# 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
+818
View File
@@ -0,0 +1,818 @@
#!/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_86.
#
# 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(***) +26% +30%
# Skylake(***) +30% +47%
# Silvermont +20% +26%
# Goldmont +40% +50%
# Bulldozer +20% +9%
# Ryzen(***) +35% +32%
# 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:
push %rbp
push %rbx
push %r12
push %r13
push %r14
push %r15
lea -8*5(%rsp),%rsp
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
.size x25519_fe51_mul,.-x25519_fe51_mul
.globl x25519_fe51_sqr
.type x25519_fe51_sqr,\@function,2
.align 32
x25519_fe51_sqr:
push %rbp
push %rbx
push %r12
push %r13
push %r14
push %r15
lea -8*5(%rsp),%rsp
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
mov 8*6(%rsp),%r14
mov 8*7(%rsp),%r13
mov 8*8(%rsp),%r12
mov 8*9(%rsp),%rbx
mov 8*10(%rsp),%rbp
lea 8*11(%rsp),%rsp
ret
.size x25519_fe51_sqr,.-x25519_fe51_sqr
.globl x25519_fe51_mul121666
.type x25519_fe51_mul121666,\@function,2
.align 32
x25519_fe51_mul121666:
push %rbp
push %rbx
push %r12
push %r13
push %r14
push %r15
mov \$121666,%eax
lea -8*5(%rsp),%rsp
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
.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:
push %rbp
push %rbx
push %r12
push %r13
push %r14
push %r15
push %rdi # offload dst
lea -8*2(%rsp),%rsp
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
.size x25519_fe64_mul,.-x25519_fe64_mul
.globl x25519_fe64_sqr
.type x25519_fe64_sqr,\@function,2
.align 32
x25519_fe64_sqr:
push %rbp
push %rbx
push %r12
push %r13
push %r14
push %r15
push %rdi # offload dst
lea -8*2(%rsp),%rsp
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
adc \$0,$acc1
mov $acc0,8*0(%rdi)
adc \$0,$acc2
mov $acc1,8*1(%rdi)
adc \$0,$acc3
mov $acc2,8*2(%rdi)
mov $acc3,8*3(%rdi)
mov 8*3(%rsp),%r15
mov 8*4(%rsp),%r14
mov 8*5(%rsp),%r13
mov 8*6(%rsp),%r12
mov 8*7(%rsp),%rbx
mov 8*8(%rsp),%rbp
lea 8*9(%rsp),%rsp
ret
.size x25519_fe64_sqr,.-x25519_fe64_sqr
.globl x25519_fe64_mul121666
.type x25519_fe64_mul121666,\@function,2
.align 32
x25519_fe64_mul121666:
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
adc \$0,$acc1
mov $acc0,8*0(%rdi)
adc \$0,$acc2
mov $acc1,8*1(%rdi)
adc \$0,$acc3
mov $acc2,8*2(%rdi)
mov $acc3,8*3(%rdi)
ret
.size x25519_fe64_mul121666,.-x25519_fe64_mul121666
.globl x25519_fe64_add
.type x25519_fe64_add,\@function,3
.align 32
x25519_fe64_add:
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
mov $acc0,8*0(%rdi)
adc \$0,$acc2
mov $acc1,8*1(%rdi)
adc \$0,$acc3
mov $acc2,8*2(%rdi)
mov $acc3,8*3(%rdi)
ret
.size x25519_fe64_add,.-x25519_fe64_add
.globl x25519_fe64_sub
.type x25519_fe64_sub,\@function,3
.align 32
x25519_fe64_sub:
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
mov $acc0,8*0(%rdi)
sbb \$0,$acc2
mov $acc1,8*1(%rdi)
sbb \$0,$acc3
mov $acc2,8*2(%rdi)
mov $acc3,8*3(%rdi)
ret
.size x25519_fe64_sub,.-x25519_fe64_sub
.globl x25519_fe64_tobytes
.type x25519_fe64_tobytes,\@function,2
.align 32
x25519_fe64_tobytes:
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 $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
and \$19,%rax
add %rax,$acc0
adc \$0,$acc1
adc \$0,$acc2
adc \$0,$acc3
mov $acc0,8*0(%rdi)
mov $acc1,8*1(%rdi)
mov $acc2,8*2(%rdi)
mov $acc3,8*3(%rdi)
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>"
___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
print $code;
close $STDOUT;
+14 -1
View File
@@ -6,9 +6,12 @@ SOURCE[../../libcrypto]=\
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,18 @@ 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)
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
+1726 -154
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 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
@@ -11,15 +11,18 @@
#include "ec_lcl.h"
#include <openssl/sha.h>
#if !defined(PEDANTIC) && \
(defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16)
#if defined(X25519_ASM) \
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
&& !defined(__sparc__) )
/*
* Base 2^51 implementation.
*/
# define BASE_2_51_IMPLEMENTED
typedef uint64_t fe51[5];
typedef unsigned __int128 u128;
# if !defined(X25519_ASM)
typedef __uint128_t u128;
# endif
static const uint64_t MASK51 = 0x7ffffffffffff;
@@ -97,40 +100,284 @@ static void fe51_tobytes(uint8_t *s, const fe51 h)
h4 &= MASK51;
/* smash */
s[0] = h0 >> 0;
s[1] = h0 >> 8;
s[2] = h0 >> 16;
s[3] = h0 >> 24;
s[4] = h0 >> 32;
s[5] = h0 >> 40;
s[6] = (h0 >> 48) | ((uint32_t)h1 << 3);
s[7] = h1 >> 5;
s[8] = h1 >> 13;
s[9] = h1 >> 21;
s[10] = h1 >> 29;
s[11] = h1 >> 37;
s[12] = (h1 >> 45) | ((uint32_t)h2 << 6);
s[13] = h2 >> 2;
s[14] = h2 >> 10;
s[15] = h2 >> 18;
s[16] = h2 >> 26;
s[17] = h2 >> 34;
s[18] = h2 >> 42;
s[19] = (h2 >> 50) | ((uint32_t)h3 << 1);
s[20] = h3 >> 7;
s[21] = h3 >> 15;
s[22] = h3 >> 23;
s[23] = h3 >> 31;
s[24] = h3 >> 39;
s[25] = (h3 >> 47) | ((uint32_t)h4 << 4);
s[26] = h4 >> 4;
s[27] = h4 >> 12;
s[28] = h4 >> 20;
s[29] = h4 >> 28;
s[30] = h4 >> 36;
s[31] = h4 >> 44;
s[0] = (uint8_t)(h0 >> 0);
s[1] = (uint8_t)(h0 >> 8);
s[2] = (uint8_t)(h0 >> 16);
s[3] = (uint8_t)(h0 >> 24);
s[4] = (uint8_t)(h0 >> 32);
s[5] = (uint8_t)(h0 >> 40);
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
s[7] = (uint8_t)(h1 >> 5);
s[8] = (uint8_t)(h1 >> 13);
s[9] = (uint8_t)(h1 >> 21);
s[10] = (uint8_t)(h1 >> 29);
s[11] = (uint8_t)(h1 >> 37);
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
s[13] = (uint8_t)(h2 >> 2);
s[14] = (uint8_t)(h2 >> 10);
s[15] = (uint8_t)(h2 >> 18);
s[16] = (uint8_t)(h2 >> 26);
s[17] = (uint8_t)(h2 >> 34);
s[18] = (uint8_t)(h2 >> 42);
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
s[20] = (uint8_t)(h3 >> 7);
s[21] = (uint8_t)(h3 >> 15);
s[22] = (uint8_t)(h3 >> 23);
s[23] = (uint8_t)(h3 >> 31);
s[24] = (uint8_t)(h3 >> 39);
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
s[26] = (uint8_t)(h4 >> 4);
s[27] = (uint8_t)(h4 >> 12);
s[28] = (uint8_t)(h4 >> 20);
s[29] = (uint8_t)(h4 >> 28);
s[30] = (uint8_t)(h4 >> 36);
s[31] = (uint8_t)(h4 >> 44);
}
# ifdef X25519_ASM
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
void x25519_fe51_sqr(fe51 h, const fe51 f);
void x25519_fe51_mul121666(fe51 h, fe51 f);
# define fe51_mul x25519_fe51_mul
# define fe51_sq x25519_fe51_sqr
# define fe51_mul121666 x25519_fe51_mul121666
# if defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64)
# define BASE_2_64_IMPLEMENTED
typedef uint64_t fe64[4];
int x25519_fe64_eligible();
/*
* There are no reference C implementations for this radix.
*/
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
# else
static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
{
u128 h0, h1, h2, h3, h4;
@@ -191,9 +438,9 @@ static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
static void fe51_sq(fe51 h, const fe51 f)
{
# if defined(OPENSSL_SMALL_FOOTPRINT)
# if defined(OPENSSL_SMALL_FOOTPRINT)
fe51_mul(h, f, f);
# else
# else
/* dedicated squaring gives 16-25% overall improvement */
uint64_t g0 = f[0];
uint64_t g1 = f[1];
@@ -221,7 +468,7 @@ static void fe51_sq(fe51 h, const fe51 f)
h2 += (u128)(g0 * 2) * g4;
h4 += (u128)g2 * g2; g2 *= 2;
h0 += (u128)g2 * g3;
h0 += (u128)g2 * g3;
h1 += (u128)g2 * g4;
/* partial [lazy] reduction */
@@ -240,9 +487,36 @@ static void fe51_sq(fe51 h, const fe51 f)
h[2] = g2;
h[3] = g3;
h[4] = g4;
# endif
# 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];
@@ -258,8 +532,8 @@ 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[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];
@@ -396,32 +670,6 @@ static void fe51_invert(fe51 out, const fe51 z)
fe51_mul(out, t1, t0);
}
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;
}
/*
* Duplicate of original x25519_scalar_mult_generic, but using
* fe51_* subroutines.
@@ -434,6 +682,13 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[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;
@@ -470,8 +725,6 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
fe51_mul(z3, x1, z2);
fe51_mul(z2, tmp1, tmp0);
}
fe51_cswap(x2, x3, swap);
fe51_cswap(z2, z3, swap);
fe51_invert(z2, z2);
fe51_mul(x2, x2, z2);
@@ -554,16 +807,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:
@@ -634,38 +887,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 */
@@ -945,16 +1198,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
@@ -1086,16 +1339,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) {
@@ -1221,6 +1474,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.
*
@@ -1361,16 +1638,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.
@@ -1418,6 +1752,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);
@@ -1438,6 +1851,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);
@@ -1491,6 +1915,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;
@@ -3773,16 +4247,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],
@@ -3828,8 +4302,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);
@@ -3844,6 +4316,1106 @@ static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
}
#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]) {
static const uint8_t kZeros[32] = {0};
@@ -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 */
+95
View File
@@ -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 */
}
+60
View File
@@ -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 */
+727
View File
@@ -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 << 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);
}
+38
View File
@@ -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 */
+475
View File
@@ -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;
+78
View File
@@ -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__ */
+195
View File
@@ -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 */
+353
View File
@@ -0,0 +1,353 @@
/*
* 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))
|| (context_len > 0
&& !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)
|| (message_len > 0
&& !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)
|| (message_len > 0
&& !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;
unsigned int c;
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);
for (c = 1; c < C448_EDDSA_DECODE_RATIO; c <<= 1)
curve448_scalar_add(response_scalar, response_scalar, response_scalar);
/* 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;
}
+204
View File
@@ -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(word_is_zero(scarry) | word_is_zero(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(word_is_zero(carry + scarry_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);
}
+168
View File
@@ -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__(32)))
# 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 */
+301
View File
@@ -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 */
+235
View File
@@ -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,
unsigned int nbytes)
{
unsigned int 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));
}
+81
View File
@@ -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 */
+1 -15
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2016 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"
+1 -15
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2011-2016 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"
+5 -21
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2016 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"
@@ -617,9 +603,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;
}
@@ -670,8 +656,7 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
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;
}
@@ -712,8 +697,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;
}
+49 -1
View File
@@ -520,6 +520,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,
@@ -551,7 +593,13 @@ 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
};
int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
+22 -21
View File
@@ -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)
@@ -359,7 +360,7 @@ 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)
@@ -465,7 +466,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
OPENSSL_free(buffer_2);
BN_free(tmp_1);
BN_free(tmp_2);
return (ok);
return ok;
}
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
@@ -571,7 +572,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) {
@@ -827,7 +828,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)
@@ -893,7 +894,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 +911,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 +986,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)
@@ -1233,5 +1234,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;
}
+3 -16
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2016 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
+1 -14
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2016 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"
+283 -224
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-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,272 +8,332 @@
* 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"},
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_FUNC(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE),
{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_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_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_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_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_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_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_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_POINT_ADD, 0), "EC_POINT_add"},
{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_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_POINT2OCT, 0), "EC_POINT_point2oct"},
{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_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_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_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_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"},
{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_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_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_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 +342,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;
+12 -12
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2002-2017 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)) ;
+11 -18
View File
@@ -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,27 +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 <stdlib.h>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include "e_os.h"
#include "internal/refcount.h"
#if defined(__SUNPRO_C)
# if __SUNPRO_C >= 0x520
@@ -264,7 +250,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;
@@ -609,6 +595,13 @@ 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],
+20 -16
View File
@@ -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,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);
@@ -143,14 +143,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);
@@ -161,6 +161,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);
@@ -232,7 +237,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;
@@ -327,7 +332,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);
}
@@ -621,7 +625,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);
+6 -10
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2001-2017 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;
+1 -6
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2011-2016 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>
+1 -15
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2002-2016 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>
+7 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 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
@@ -20,7 +20,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;
@@ -97,7 +97,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;
@@ -199,7 +199,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,
@@ -301,7 +301,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) {
@@ -344,7 +344,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 */
@@ -355,7 +355,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,
+8 -13
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2006-2016 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
@@ -231,7 +226,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,
+1 -6
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2016 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"
+1 -6
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2016 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>
+19 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2010-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
@@ -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 "Need GCC 4.0 or later to define type uint128_t"
# 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;
};
@@ -1238,7 +1238,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;
}
@@ -1249,7 +1249,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;
@@ -1284,9 +1284,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);
@@ -1415,10 +1416,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
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) {
@@ -1598,7 +1600,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)
+18 -14
View File
@@ -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 "Need GCC 4.0 or later to define type uint128_t"
# 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;
};
@@ -1856,7 +1856,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 +1867,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 +1902,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);
@@ -2034,10 +2035,11 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
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) {
@@ -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)
+37 -17
View File
@@ -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
@@ -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 "Need GCC 4.0 or later to define type uint128_t"
# 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;
};
@@ -1677,7 +1693,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;
}
@@ -1688,7 +1704,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;
@@ -1723,9 +1739,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);
@@ -1854,10 +1871,11 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
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) {
@@ -2041,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)
+29 -37
View File
@@ -1,47 +1,29 @@
/*
* 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
*
* 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 *
* (3) CloudFlare, Inc. *
* 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
@@ -86,7 +68,7 @@ struct nistz256_pre_comp_st {
*/
PRECOMP256_ROW *precomp;
void *precomp_storage;
int references;
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
@@ -256,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,
@@ -1469,7 +1461,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;
}
@@ -1480,7 +1472,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;
@@ -1538,6 +1530,10 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
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.
@@ -1615,10 +1611,6 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
* multiplications, 25%, on grand scale sign operation is not that
* much faster, not more that 2%...
*/
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
};
/* pre-calculate powers */
ecp_nistz256_ord_sqr_mont(table[i_10], table[i_1], 1);
+2 -7
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2011-2016 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);
+3 -8
View File
@@ -1,5 +1,6 @@
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2001-2017 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>
@@ -1218,7 +1213,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]));
+167 -18
View File
@@ -20,6 +20,8 @@
#define X25519_BITS 253
#define X25519_SECURITY_BITS 128
#define ED25519_SIGSIZE 64
typedef struct {
unsigned char pubkey[X25519_KEYLEN];
unsigned char *privkey;
@@ -32,7 +34,7 @@ typedef enum {
} 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;
@@ -76,16 +78,21 @@ static int ecx_key_op(EVP_PKEY *pkey, const X509_ALGOR *palg,
OPENSSL_free(xkey);
return 0;
}
xkey->privkey[0] &= 248;
xkey->privkey[31] &= 127;
xkey->privkey[31] |= 64;
if (id == EVP_PKEY_X25519) {
xkey->privkey[0] &= 248;
xkey->privkey[31] &= 127;
xkey->privkey[31] |= 64;
}
} else {
memcpy(xkey->privkey, p, X25519_KEYLEN);
}
X25519_public_from_private(xkey->pubkey, xkey->privkey);
if (id == EVP_PKEY_X25519)
X25519_public_from_private(xkey->pubkey, xkey->privkey);
else
ED25519_public_from_private(xkey->pubkey, xkey->privkey);
}
EVP_PKEY_assign(pkey, NID_X25519, xkey);
EVP_PKEY_assign(pkey, id, xkey);
return 1;
}
@@ -105,8 +112,8 @@ static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
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, X25519_KEYLEN)) {
OPENSSL_free(penc);
ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
return 0;
@@ -122,7 +129,8 @@ 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,
X25519_PUBLIC);
}
static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -155,7 +163,7 @@ 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, X25519_PRIVATE);
ASN1_OCTET_STRING_free(oct);
return rv;
}
@@ -182,7 +190,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);
@@ -227,13 +235,15 @@ static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
{
const X25519_KEY *xkey = pkey->pkey.ptr;
const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
if (op == X25519_PRIVATE) {
if (xkey == NULL || xkey->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;
@@ -245,7 +255,7 @@ static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
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)
@@ -272,7 +282,8 @@ 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, EVP_PKEY_X25519, NULL, arg2, arg1,
X25519_PUBLIC);
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
if (pkey->pkey.ptr != NULL) {
@@ -295,8 +306,8 @@ static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
}
const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
NID_X25519,
NID_X25519,
EVP_PKEY_X25519,
EVP_PKEY_X25519,
0,
"X25519",
"OpenSSL X25519 algorithm",
@@ -324,9 +335,87 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
NULL
};
static int ecd_size(const EVP_PKEY *pkey)
{
return ED25519_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;
X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
/* Sanity check: make sure it is ED25519 with absent parameters */
if (OBJ_obj2nid(obj) != NID_ED25519 || 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_sign(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_set(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;
}
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_size,
ecx_bits,
ecx_security_bits,
0, 0, 0, 0,
ecx_cmp_parameters,
0, 0,
ecx_free,
0,
NULL,
NULL,
ecd_item_verify,
ecd_item_sign,
ecd_sig_info_set
};
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, X25519_KEYGEN);
}
static int pkey_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
@@ -363,7 +452,7 @@ 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,
@@ -371,3 +460,63 @@ const EVP_PKEY_METHOD ecx25519_pkey_meth = {
pkey_ecx_ctrl,
0
};
static int pkey_ecd_digestsign(EVP_MD_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
const X25519_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ptr;
if (sig == NULL) {
*siglen = ED25519_SIGSIZE;
return 1;
}
if (*siglen < ED25519_SIGSIZE) {
ECerr(EC_F_PKEY_ECD_DIGESTSIGN, 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_digestverify(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen)
{
const X25519_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ptr;
if (siglen != ED25519_SIGSIZE)
return 0;
return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
}
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)
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_digestsign,
pkey_ecd_digestverify
};