diff options
Diffstat (limited to 'crypto/ec')
69 files changed, 7925 insertions, 3512 deletions
diff --git a/crypto/ec/asm/ecp_nistp521-ppc64.pl b/crypto/ec/asm/ecp_nistp521-ppc64.pl new file mode 100755 index 000000000000..cf3bc79085f8 --- /dev/null +++ b/crypto/ec/asm/ecp_nistp521-ppc64.pl @@ -0,0 +1,436 @@ +#! /usr/bin/env perl +# Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (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 Amitay Isaacs <amitay@ozlabs.org> and Martin Schwenke +# <martin@meltin.net> for the OpenSSL project. +# ==================================================================== +# +# p521 lower-level primitives for PPC64 using vector instructions. +# + +use strict; +use warnings; + +my $flavour = shift; +my $output = ""; +while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +if (!$output) { + $output = "-"; +} + +my ($xlate, $dir); +$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 $code = ""; + +my ($sp, $outp, $savelr, $savesp) = ("r1", "r3", "r10", "r12"); + +my $vzero = "v32"; + +sub startproc($) +{ + my ($name) = @_; + + $code.=<<___; + .globl ${name} + .align 5 +${name}: + +___ +} + +sub endproc($) +{ + my ($name) = @_; + + $code.=<<___; + blr + .size ${name},.-${name} + +___ +} + + +sub push_vrs($$) +{ + my ($min, $max) = @_; + + my $count = $max - $min + 1; + + $code.=<<___; + mr $savesp,$sp + stdu $sp,-16*`$count+1`($sp) + +___ + for (my $i = $min; $i <= $max; $i++) { + my $mult = $max - $i + 1; + $code.=<<___; + stxv $i,-16*$mult($savesp) +___ + + } + + $code.=<<___; + +___ +} + +sub pop_vrs($$) +{ + my ($min, $max) = @_; + + $code.=<<___; + ld $savesp,0($sp) +___ + for (my $i = $min; $i <= $max; $i++) { + my $mult = $max - $i + 1; + $code.=<<___; + lxv $i,-16*$mult($savesp) +___ + } + + $code.=<<___; + mr $sp,$savesp + +___ +} + +sub load_vrs($$) +{ + my ($pointer, $reg_list) = @_; + + for (my $i = 0; $i <= 8; $i++) { + my $offset = $i * 8; + $code.=<<___; + lxsd $reg_list->[$i],$offset($pointer) +___ + } + + $code.=<<___; + +___ +} + +sub store_vrs($$) +{ + my ($pointer, $reg_list) = @_; + + for (my $i = 0; $i <= 8; $i++) { + my $offset = $i * 16; + $code.=<<___; + stxv $reg_list->[$i],$offset($pointer) +___ + } + + $code.=<<___; + +___ +} + +$code.=<<___; +.machine "any" +.text + +___ + +{ + # mul/square common + my ($t1, $t2, $t3, $t4) = ("v33", "v34", "v44", "v54"); + my ($zero, $one) = ("r8", "r9"); + my @out = map("v$_",(55..63)); + + { + # + # p521_felem_mul + # + + my ($in1p, $in2p) = ("r4", "r5"); + my @in1 = map("v$_",(45..53)); + my @in2 = map("v$_",(35..43)); + + startproc("p521_felem_mul"); + + push_vrs(52, 63); + + $code.=<<___; + vspltisw $vzero,0 + +___ + + load_vrs($in1p, \@in1); + load_vrs($in2p, \@in2); + + $code.=<<___; + vmsumudm $out[0],$in1[0],$in2[0],$vzero + + xxpermdi $t1,$in1[0],$in1[1],0b00 + xxpermdi $t2,$in2[1],$in2[0],0b00 + vmsumudm $out[1],$t1,$t2,$vzero + + xxpermdi $t2,$in2[2],$in2[1],0b00 + vmsumudm $out[2],$t1,$t2,$vzero + vmsumudm $out[2],$in1[2],$in2[0],$out[2] + + xxpermdi $t2,$in2[3],$in2[2],0b00 + vmsumudm $out[3],$t1,$t2,$vzero + xxpermdi $t3,$in1[2],$in1[3],0b00 + xxpermdi $t4,$in2[1],$in2[0],0b00 + vmsumudm $out[3],$t3,$t4,$out[3] + + xxpermdi $t2,$in2[4],$in2[3],0b00 + vmsumudm $out[4],$t1,$t2,$vzero + xxpermdi $t4,$in2[2],$in2[1],0b00 + vmsumudm $out[4],$t3,$t4,$out[4] + vmsumudm $out[4],$in1[4],$in2[0],$out[4] + + xxpermdi $t2,$in2[5],$in2[4],0b00 + vmsumudm $out[5],$t1,$t2,$vzero + xxpermdi $t4,$in2[3],$in2[2],0b00 + vmsumudm $out[5],$t3,$t4,$out[5] + + xxpermdi $t2,$in2[6],$in2[5],0b00 + vmsumudm $out[6],$t1,$t2,$vzero + xxpermdi $t4,$in2[4],$in2[3],0b00 + vmsumudm $out[6],$t3,$t4,$out[6] + + xxpermdi $t2,$in2[7],$in2[6],0b00 + vmsumudm $out[7],$t1,$t2,$vzero + xxpermdi $t4,$in2[5],$in2[4],0b00 + vmsumudm $out[7],$t3,$t4,$out[7] + + xxpermdi $t2,$in2[8],$in2[7],0b00 + vmsumudm $out[8],$t1,$t2,$vzero + xxpermdi $t4,$in2[6],$in2[5],0b00 + vmsumudm $out[8],$t3,$t4,$out[8] + + xxpermdi $t1,$in1[4],$in1[5],0b00 + xxpermdi $t2,$in2[1],$in2[0],0b00 + vmsumudm $out[5],$t1,$t2,$out[5] + + xxpermdi $t2,$in2[2],$in2[1],0b00 + vmsumudm $out[6],$t1,$t2,$out[6] + vmsumudm $out[6],$in1[6],$in2[0],$out[6] + + xxpermdi $t2,$in2[3],$in2[2],0b00 + vmsumudm $out[7],$t1,$t2,$out[7] + xxpermdi $t3,$in1[6],$in1[7],0b00 + xxpermdi $t4,$in2[1],$in2[0],0b00 + vmsumudm $out[7],$t3,$t4,$out[7] + + xxpermdi $t2,$in2[4],$in2[3],0b00 + vmsumudm $out[8],$t1,$t2,$out[8] + xxpermdi $t4,$in2[2],$in2[1],0b00 + vmsumudm $out[8],$t3,$t4,$out[8] + vmsumudm $out[8],$in1[8],$in2[0],$out[8] + + li $zero,0 + li $one,1 + mtvsrdd $t1,$one,$zero +___ + + for (my $i = 0; $i <= 8; $i++) { + $code.=<<___; + vsld $in2[$i],$in2[$i],$t1 +___ + } + + $code.=<<___; + + vmsumudm $out[7],$in1[8],$in2[8],$out[7] + + xxpermdi $t2,$in2[8],$in2[7],0b00 + xxpermdi $t1,$in1[7],$in1[8],0b00 + vmsumudm $out[6],$t1,$t2,$out[6] + + xxpermdi $t1,$in1[6],$in1[7],0b00 + vmsumudm $out[5],$t1,$t2,$out[5] + vmsumudm $out[5],$in1[8],$in2[6],$out[5] + + xxpermdi $t1,$in1[5],$in1[6],0b00 + vmsumudm $out[4],$t1,$t2,$out[4] + xxpermdi $t4,$in2[6],$in2[5],0b00 + xxpermdi $t3,$in1[7],$in1[8],0b00 + vmsumudm $out[4],$t3,$t4,$out[4] + + xxpermdi $t1,$in1[4],$in1[5],0b00 + vmsumudm $out[3],$t1,$t2,$out[3] + xxpermdi $t3,$in1[6],$in1[7],0b00 + vmsumudm $out[3],$t3,$t4,$out[3] + vmsumudm $out[3],$in1[8],$in2[4],$out[3] + + xxpermdi $t1,$in1[3],$in1[4],0b00 + vmsumudm $out[2],$t1,$t2,$out[2] + xxpermdi $t3,$in1[5],$in1[6],0b00 + vmsumudm $out[2],$t3,$t4,$out[2] + + xxpermdi $t1,$in1[2],$in1[3],0b00 + vmsumudm $out[1],$t1,$t2,$out[1] + xxpermdi $t3,$in1[4],$in1[5],0b00 + vmsumudm $out[1],$t3,$t4,$out[1] + + xxpermdi $t1,$in1[1],$in1[2],0b00 + vmsumudm $out[0],$t1,$t2,$out[0] + xxpermdi $t3,$in1[3],$in1[4],0b00 + vmsumudm $out[0],$t3,$t4,$out[0] + + xxpermdi $t2,$in2[4],$in2[3],0b00 + xxpermdi $t1,$in1[7],$in1[8],0b00 + vmsumudm $out[2],$t1,$t2,$out[2] + + xxpermdi $t1,$in1[6],$in1[7],0b00 + vmsumudm $out[1],$t1,$t2,$out[1] + vmsumudm $out[1],$in1[8],$in2[2],$out[1] + + xxpermdi $t1,$in1[5],$in1[6],0b00 + vmsumudm $out[0],$t1,$t2,$out[0] + xxpermdi $t4,$in2[2],$in2[1],0b00 + xxpermdi $t3,$in1[7],$in1[8],0b00 + vmsumudm $out[0],$t3,$t4,$out[0] + +___ + + store_vrs($outp, \@out); + + pop_vrs(52, 63); + + endproc("p521_felem_mul"); + } + + { + # + # p51_felem_square + # + + my ($inp) = ("r4"); + my @in = map("v$_",(45..53)); + my @inx2 = map("v$_",(35..43)); + + startproc("p521_felem_square"); + + push_vrs(52, 63); + + $code.=<<___; + vspltisw $vzero,0 + +___ + + load_vrs($inp, \@in); + + $code.=<<___; + li $zero,0 + li $one,1 + mtvsrdd $t1,$one,$zero +___ + + for (my $i = 0; $i <= 8; $i++) { + $code.=<<___; + vsld $inx2[$i],$in[$i],$t1 +___ + } + + $code.=<<___; + vmsumudm $out[0],$in[0],$in[0],$vzero + + vmsumudm $out[1],$in[0],$inx2[1],$vzero + + xxpermdi $t1,$in[0],$in[1],0b00 + xxpermdi $t2,$inx2[2],$in[1],0b00 + vmsumudm $out[2],$t1,$t2,$vzero + + xxpermdi $t2,$inx2[3],$inx2[2],0b00 + vmsumudm $out[3],$t1,$t2,$vzero + + xxpermdi $t2,$inx2[4],$inx2[3],0b00 + vmsumudm $out[4],$t1,$t2,$vzero + vmsumudm $out[4],$in[2],$in[2],$out[4] + + xxpermdi $t2,$inx2[5],$inx2[4],0b00 + vmsumudm $out[5],$t1,$t2,$vzero + vmsumudm $out[5],$in[2],$inx2[3],$out[5] + + xxpermdi $t2,$inx2[6],$inx2[5],0b00 + vmsumudm $out[6],$t1,$t2,$vzero + xxpermdi $t3,$in[2],$in[3],0b00 + xxpermdi $t4,$inx2[4],$in[3],0b00 + vmsumudm $out[6],$t3,$t4,$out[6] + + xxpermdi $t2,$inx2[7],$inx2[6],0b00 + vmsumudm $out[7],$t1,$t2,$vzero + xxpermdi $t4,$inx2[5],$inx2[4],0b00 + vmsumudm $out[7],$t3,$t4,$out[7] + + xxpermdi $t2,$inx2[8],$inx2[7],0b00 + vmsumudm $out[8],$t1,$t2,$vzero + xxpermdi $t4,$inx2[6],$inx2[5],0b00 + vmsumudm $out[8],$t3,$t4,$out[8] + vmsumudm $out[8],$in[4],$in[4],$out[8] + + vmsumudm $out[1],$in[5],$inx2[5],$out[1] + + vmsumudm $out[3],$in[6],$inx2[6],$out[3] + + vmsumudm $out[5],$in[7],$inx2[7],$out[5] + + vmsumudm $out[7],$in[8],$inx2[8],$out[7] + + mtvsrdd $t1,$one,$zero +___ + + for (my $i = 5; $i <= 8; $i++) { + $code.=<<___; + vsld $inx2[$i],$inx2[$i],$t1 +___ + } + + $code.=<<___; + + vmsumudm $out[6],$in[7],$inx2[8],$out[6] + + vmsumudm $out[5],$in[6],$inx2[8],$out[5] + + xxpermdi $t2,$inx2[8],$inx2[7],0b00 + xxpermdi $t1,$in[5],$in[6],0b00 + vmsumudm $out[4],$t1,$t2,$out[4] + + xxpermdi $t1,$in[4],$in[5],0b00 + vmsumudm $out[3],$t1,$t2,$out[3] + + xxpermdi $t1,$in[3],$in[4],0b00 + vmsumudm $out[2],$t1,$t2,$out[2] + vmsumudm $out[2],$in[5],$inx2[6],$out[2] + + xxpermdi $t1,$in[2],$in[3],0b00 + vmsumudm $out[1],$t1,$t2,$out[1] + vmsumudm $out[1],$in[4],$inx2[6],$out[1] + + xxpermdi $t1,$in[1],$in[2],0b00 + vmsumudm $out[0],$t1,$t2,$out[0] + xxpermdi $t2,$inx2[6],$inx2[5],0b00 + xxpermdi $t1,$in[3],$in[4],0b00 + vmsumudm $out[0],$t1,$t2,$out[0] + +___ + + store_vrs($outp, \@out); + + pop_vrs(52, 63); + + endproc("p521_felem_square"); + } +} + +$code =~ s/\`([^\`]*)\`/eval $1/gem; +print $code; +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/ec/asm/ecp_nistz256-armv4.pl b/crypto/ec/asm/ecp_nistz256-armv4.pl index fa833ce6aaf3..0adad26cb11f 100755 --- a/crypto/ec/asm/ecp_nistz256-armv4.pl +++ b/crypto/ec/asm/ecp_nistz256-armv4.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -33,9 +33,10 @@ # on benchmark. Lower coefficients are for ECDSA sign, server-side # operation. Keep in mind that +200% means 3x improvement. -$flavour = shift; -if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; } -else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; if ($flavour && $flavour ne "void") { $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; @@ -43,15 +44,15 @@ if ($flavour && $flavour ne "void") { ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; - open STDOUT,"| \"$^X\" $xlate $flavour $output"; + open STDOUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; } else { - open STDOUT,">$output"; + $output and open STDOUT,">$output"; } $code.=<<___; #include "arm_arch.h" -.text #if defined(__thumb2__) .syntax unified .thumb @@ -80,6 +81,7 @@ close TABLE; die "insane number of elements" if ($#arr != 64*16*37-1); $code.=<<___; +.rodata .globl ecp_nistz256_precomputed .type ecp_nistz256_precomputed,%object .align 12 @@ -104,6 +106,8 @@ for(1..37) { } $code.=<<___; .size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed + +.text .align 5 .LRR: @ 2^512 mod P precomputed for NIST P256 polynomial .long 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb diff --git a/crypto/ec/asm/ecp_nistz256-armv8.pl b/crypto/ec/asm/ecp_nistz256-armv8.pl index e93e18f29f19..81ee3947d7e4 100644 --- a/crypto/ec/asm/ecp_nistz256-armv8.pl +++ b/crypto/ec/asm/ecp_nistz256-armv8.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -31,15 +31,18 @@ # on benchmark. Lower coefficients are for ECDSA sign, server-side # operation. Keep in mind that +400% means 5x improvement. -$flavour = shift; -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or die "can't locate arm-xlate.pl"; -open OUT,"| \"$^X\" $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; { @@ -1479,7 +1482,7 @@ $code.=<<___; //////////////////////////////////////////////////////////////////////// // void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4], -// int rep); +// uint64_t rep); .globl ecp_nistz256_ord_sqr_mont .type ecp_nistz256_ord_sqr_mont,%function .align 4 @@ -1645,7 +1648,7 @@ ecp_nistz256_scatter_w5: ldp x4,x5,[$inp] // X ldp x6,x7,[$inp,#16] - str w4,[$out,#64*0-4] + stur w4,[$out,#64*0-4] lsr x4,x4,#32 str w5,[$out,#64*1-4] lsr x5,x5,#32 @@ -1661,7 +1664,7 @@ ecp_nistz256_scatter_w5: ldp x4,x5,[$inp,#32] // Y ldp x6,x7,[$inp,#48] - str w4,[$out,#64*0-4] + stur w4,[$out,#64*0-4] lsr x4,x4,#32 str w5,[$out,#64*1-4] lsr x5,x5,#32 @@ -1677,7 +1680,7 @@ ecp_nistz256_scatter_w5: ldp x4,x5,[$inp,#64] // Z ldp x6,x7,[$inp,#80] - str w4,[$out,#64*0-4] + stur w4,[$out,#64*0-4] lsr x4,x4,#32 str w5,[$out,#64*1-4] lsr x5,x5,#32 diff --git a/crypto/ec/asm/ecp_nistz256-ppc64.pl b/crypto/ec/asm/ecp_nistz256-ppc64.pl index 2bf54e2aa544..7f600cece9d7 100755 --- a/crypto/ec/asm/ecp_nistz256-ppc64.pl +++ b/crypto/ec/asm/ecp_nistz256-ppc64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -25,15 +25,18 @@ # POWER7 +260-530% # POWER8 +220-340% -$flavour = shift; -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $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"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; my $sp="r1"; @@ -1919,7 +1922,7 @@ $code.=<<___; ################################################################################ # void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4], -# int rep); +# uint64_t rep); .globl ecp_nistz256_ord_sqr_mont .align 5 ecp_nistz256_ord_sqr_mont: diff --git a/crypto/ec/asm/ecp_nistz256-sparcv9.pl b/crypto/ec/asm/ecp_nistz256-sparcv9.pl index 042e122718b7..986e002cc94d 100755 --- a/crypto/ec/asm/ecp_nistz256-sparcv9.pl +++ b/crypto/ec/asm/ecp_nistz256-sparcv9.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -31,11 +31,13 @@ # on benchmark. Lower coefficients are for ECDSA sign, server-side # operation. Keep in mind that +200% means 3x improvement. -$output = pop; -open STDOUT,">$output"; +$output = pop and open STDOUT,">$output"; $code.=<<___; -#include "sparc_arch.h" +#ifndef __ASSEMBLER__ +# define __ASSEMBLER__ 1 +#endif +#include "crypto/sparc_arch.h" #define LOCALS (STACK_BIAS+STACK_FRAME) #ifdef __arch64__ diff --git a/crypto/ec/asm/ecp_nistz256-x86.pl b/crypto/ec/asm/ecp_nistz256-x86.pl index e926d69b020b..e78f0cd7266d 100755 --- a/crypto/ec/asm/ecp_nistz256-x86.pl +++ b/crypto/ec/asm/ecp_nistz256-x86.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -42,8 +42,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; push(@INC,"${dir}","${dir}../../perlasm"); require "x86asm.pl"; -$output=pop; -open STDOUT,">$output"; +$output=pop and open STDOUT,">$output"; &asm_init($ARGV[0],$ARGV[$#ARGV] eq "386"); diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl index b50ee70191b2..430b14c86d8d 100755 --- a/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -3,7 +3,7 @@ # Copyright (c) 2014, Intel Corporation. All Rights Reserved. # Copyright (c) 2015 CloudFlare, Inc. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -40,9 +40,10 @@ # higher - for ECDSA sign, relatively fastest server-side operation. # Keep in mind that +100% means 2x improvement. -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -51,7 +52,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $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\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` @@ -826,7 +828,7 @@ $code.=<<___; # void ecp_nistz256_ord_sqr_mont( # uint64_t res[4], # uint64_t a[4], -# int rep); +# uint64_t rep); .globl ecp_nistz256_ord_sqr_mont .type ecp_nistz256_ord_sqr_mont,\@function,3 diff --git a/crypto/ec/asm/x25519-ppc64.pl b/crypto/ec/asm/x25519-ppc64.pl index f4b523bf8a08..c1d9650c6bfa 100755 --- a/crypto/ec/asm/x25519-ppc64.pl +++ b/crypto/ec/asm/x25519-ppc64.pl @@ -1,7 +1,7 @@ #! /usr/bin/env perl # Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -27,15 +27,18 @@ # this module delivers more than 2x improvement, and when it does, # from 12% to 30% improvement was measured... -$flavour = shift; -while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $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"; +open OUT,"| \"$^X\" $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; my $sp = "r1"; diff --git a/crypto/ec/asm/x25519-x86_64.pl b/crypto/ec/asm/x25519-x86_64.pl index 62599dacaccd..d2285269a308 100755 --- a/crypto/ec/asm/x25519-x86_64.pl +++ b/crypto/ec/asm/x25519-x86_64.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl # Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. # -# Licensed under the OpenSSL license (the "License"). You may not use +# Licensed under the Apache License 2.0 (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 @@ -61,9 +61,10 @@ # C implementation, so that comparison is always against # 2^51 radix; -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } +# $output is the last argument if it looks like a file (it has an extension) +# $flavour is the first argument if it doesn't look like a file +$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; +$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); @@ -72,7 +73,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $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\""; +open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" + or die "can't call $xlate: $!"; *STDOUT=*OUT; if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` diff --git a/crypto/ec/build.info b/crypto/ec/build.info index a1e673e347d0..6dd98e9f4f17 100644 --- a/crypto/ec/build.info +++ b/crypto/ec/build.info @@ -1,42 +1,105 @@ -LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \ - ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \ - ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \ - ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \ - ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \ - ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \ - curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \ +$ECASM= +IF[{- !$disabled{asm} -}] + $ECASM_x86=ecp_nistz256.c ecp_nistz256-x86.S + $ECDEF_x86=ECP_NISTZ256_ASM + + $ECASM_x86_64=ecp_nistz256.c ecp_nistz256-x86_64.s x25519-x86_64.s + $ECDEF_x86_64=ECP_NISTZ256_ASM X25519_ASM + + $ECASM_ia64= + + $ECASM_sparcv9=ecp_nistz256.c ecp_nistz256-sparcv9.S + $ECDEF_sparcv9=ECP_NISTZ256_ASM + + $ECASM_sparcv8= + + $ECASM_alpha= + + $ECASM_mips32= + $ECASM_mips64= + + $ECASM_s390x=ecp_s390x_nistp.c ecx_s390x.c + $ECDEF_s390x=S390X_EC_ASM + + $ECASM_armv4=ecp_nistz256.c ecp_nistz256-armv4.S + $ECDEF_armv4=ECP_NISTZ256_ASM + $ECASM_aarch64=ecp_nistz256.c ecp_nistz256-armv8.S + $ECDEF_aarch64=ECP_NISTZ256_ASM + + $ECASM_parisc11= + $ECASM_parisc20_64= + + $ECASM_ppc32= + $ECASM_ppc64=ecp_nistz256.c ecp_ppc.c ecp_nistz256-ppc64.s x25519-ppc64.s + $ECDEF_ppc64=ECP_NISTZ256_ASM X25519_ASM + IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}] + $ECASM_ppc64=$ECASM_ppc64 ecp_nistp521-ppc64.s + $ECDEF_ppc64=$ECDEF_ppc64 ECP_NISTP521_ASM + INCLUDE[ecp_nistp521.o]=.. + ENDIF + + $ECASM_c64xplus= + + # Now that we have defined all the arch specific variables, use the + # appropriate one, and define the appropriate macros + IF[$ECASM_{- $target{asm_arch} -}] + $ECASM=$ECASM_{- $target{asm_arch} -} + $ECDEF=$ECDEF_{- $target{asm_arch} -} + ENDIF +ENDIF + +$COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \ + ec_curve.c ec_check.c ec_key.c ec_kmeth.c ecx_key.c ec_asn1.c \ + ec2_smpl.c \ + ecp_oct.c ec2_oct.c ec_oct.c ecdh_ossl.c \ + ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \ + curve448/f_generic.c curve448/scalar.c \ curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \ - {- $target{ec_asm_src} -} + $ECASM ec_backend.c ecx_backend.c ecdh_kdf.c curve448/arch_64/f_impl64.c \ + curve448/arch_32/f_impl32.c + +IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}] + $COMMON=$COMMON ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c +ENDIF + +SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c \ + ec_err.c eck_prn.c \ + ec_deprecated.c ec_print.c +SOURCE[../../providers/libfips.a]=$COMMON -GENERATE[ecp_nistz256-x86.s]=asm/ecp_nistz256-x86.pl \ - $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) +# Implementations are now spread across several libraries, so the defines +# need to be applied to all affected libraries and modules. +DEFINE[../../libcrypto]=$ECDEF +DEFINE[../../providers/libfips.a]=$ECDEF +DEFINE[../../providers/libdefault.a]=$ECDEF +# We only need to include the ECDEF stuff in the legacy provider when +# it's a separate module and it's dynamically linked with libcrypto. +# Otherwise, it already gets everything that the static libcrypto.a +# has, and doesn't need it added again. +IF[{- !$disabled{module} && !$disabled{shared} -}] + DEFINE[../../providers/liblegacy.a]=$ECDEF +ENDIF -GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl $(PERLASM_SCHEME) +GENERATE[ecp_nistz256-x86.S]=asm/ecp_nistz256-x86.pl -GENERATE[ecp_nistz256-avx2.s]=asm/ecp_nistz256-avx2.pl $(PERLASM_SCHEME) +GENERATE[ecp_nistz256-x86_64.s]=asm/ecp_nistz256-x86_64.pl -GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl $(PERLASM_SCHEME) +GENERATE[ecp_nistz256-avx2.s]=asm/ecp_nistz256-avx2.pl + +GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl INCLUDE[ecp_nistz256-sparcv9.o]=.. -GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl $(PERLASM_SCHEME) +INCLUDE[ecp_s390x_nistp.o]=.. +INCLUDE[ecx_s390x.o]=.. +INCLUDE[ecx_meth.o]=.. + +GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl INCLUDE[ecp_nistz256-armv4.o]=.. -GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl $(PERLASM_SCHEME) +GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl INCLUDE[ecp_nistz256-armv8.o]=.. -GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl $(PERLASM_SCHEME) - -GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl $(PERLASM_SCHEME) -GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl $(PERLASM_SCHEME) - -BEGINRAW[Makefile] -{- $builddir -}/ecp_nistz256-%.S: {- $sourcedir -}/asm/ecp_nistz256-%.pl - CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@ -ENDRAW[Makefile] - -INCLUDE[curve448/arch_32/f_impl.o]=curve448/arch_32 curve448 -INCLUDE[curve448/f_generic.o]=curve448/arch_32 curve448 -INCLUDE[curve448/scalar.o]=curve448/arch_32 curve448 -INCLUDE[curve448/curve448_tables.o]=curve448/arch_32 curve448 -INCLUDE[curve448/eddsa.o]=curve448/arch_32 curve448 -INCLUDE[curve448/curve448.o]=curve448/arch_32 curve448 +GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl + +GENERATE[ecp_nistp521-ppc64.s]=asm/ecp_nistp521-ppc64.pl + +GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl +GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index 952da0e65385..50a8e6b169d2 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -1,16 +1,26 @@ /* - * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> +#include "crypto/ecx.h" #include "ec_local.h" +#include <openssl/evp.h> #include <openssl/sha.h> +#include "internal/numbers.h" + #if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \ defined(_M_AMD64) || defined(_M_X64)) @@ -252,7 +262,7 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32], #endif #if defined(X25519_ASM) \ - || ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \ + || ( defined(INT128_MAX) \ && !defined(__sparc__) \ && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) \ && !(defined(__ANDROID__) && !defined(__clang__)) ) @@ -385,7 +395,7 @@ void x25519_fe51_mul121666(fe51 h, fe51 f); # define fe51_mul121666 x25519_fe51_mul121666 # else -typedef __uint128_t u128; +typedef uint128_t u128; static void fe51_mul(fe51 h, const fe51 f, const fe51 g) { @@ -5429,57 +5439,75 @@ static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, 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]) +int +ossl_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], + OSSL_LIB_CTX *libctx, const char *propq) { 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; + EVP_MD *sha512 = EVP_MD_fetch(libctx, SN_sha512, propq); + EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new(); + unsigned int sz; + int res = 0; - SHA512_Init(&hash_ctx); - SHA512_Update(&hash_ctx, private_key, 32); - SHA512_Final(az, &hash_ctx); + if (sha512 == NULL || hash_ctx == NULL) + goto err; + + if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + || !EVP_DigestUpdate(hash_ctx, private_key, 32) + || !EVP_DigestFinal_ex(hash_ctx, az, &sz)) + goto err; 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); + if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + || !EVP_DigestUpdate(hash_ctx, az + 32, 32) + || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestFinal_ex(hash_ctx, nonce, &sz)) + goto err; 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); + if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + || !EVP_DigestUpdate(hash_ctx, out_sig, 32) + || !EVP_DigestUpdate(hash_ctx, public_key, 32) + || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestFinal_ex(hash_ctx, hram, &sz)) + goto err; x25519_sc_reduce(hram); sc_muladd(out_sig + 32, hram, az, nonce); - OPENSSL_cleanse(&hash_ctx, sizeof(hash_ctx)); + res = 1; +err: OPENSSL_cleanse(nonce, sizeof(nonce)); OPENSSL_cleanse(az, sizeof(az)); - - return 1; + EVP_MD_free(sha512); + EVP_MD_CTX_free(hash_ctx); + return res; } static const char allzeroes[15]; -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], const uint8_t public_key[32]) +int +ossl_ed25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], const uint8_t public_key[32], + OSSL_LIB_CTX *libctx, const char *propq) { int i; ge_p3 A; const uint8_t *r, *s; - SHA512_CTX hash_ctx; + EVP_MD *sha512; + EVP_MD_CTX *hash_ctx = NULL; + unsigned int sz; + int res = 0; ge_p2 R; uint8_t rcheck[32]; uint8_t h[SHA512_DIGEST_LENGTH]; @@ -5526,11 +5554,19 @@ int ED25519_verify(const uint8_t *message, size_t message_len, fe_neg(A.X, A.X); fe_neg(A.T, A.T); - SHA512_Init(&hash_ctx); - SHA512_Update(&hash_ctx, r, 32); - SHA512_Update(&hash_ctx, public_key, 32); - SHA512_Update(&hash_ctx, message, message_len); - SHA512_Final(h, &hash_ctx); + sha512 = EVP_MD_fetch(libctx, SN_sha512, propq); + if (sha512 == NULL) + return 0; + hash_ctx = EVP_MD_CTX_new(); + if (hash_ctx == NULL) + goto err; + + if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + || !EVP_DigestUpdate(hash_ctx, r, 32) + || !EVP_DigestUpdate(hash_ctx, public_key, 32) + || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestFinal_ex(hash_ctx, h, &sz)) + goto err; x25519_sc_reduce(h); @@ -5538,16 +5574,32 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ge_tobytes(rcheck, &R); - return CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0; + res = CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0; +err: + EVP_MD_free(sha512); + EVP_MD_CTX_free(hash_ctx); + return res; } -void ED25519_public_from_private(uint8_t out_public_key[32], - const uint8_t private_key[32]) +int +ossl_ed25519_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[32], + const uint8_t private_key[32], + const char *propq) { uint8_t az[SHA512_DIGEST_LENGTH]; ge_p3 A; + int r; + EVP_MD *sha512 = NULL; - SHA512(private_key, 32, az); + sha512 = EVP_MD_fetch(ctx, SN_sha512, propq); + if (sha512 == NULL) + return 0; + r = EVP_Digest(private_key, 32, az, NULL, sha512, NULL); + EVP_MD_free(sha512); + if (!r) { + OPENSSL_cleanse(az, sizeof(az)); + return 0; + } az[0] &= 248; az[31] &= 63; @@ -5557,10 +5609,12 @@ void ED25519_public_from_private(uint8_t out_public_key[32], ge_p3_tobytes(out_public_key, &A); OPENSSL_cleanse(az, sizeof(az)); + return 1; } -int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], - const uint8_t peer_public_value[32]) +int +ossl_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}; x25519_scalar_mult(out_shared_key, private_key, peer_public_value); @@ -5568,7 +5622,8 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0; } -void X25519_public_from_private(uint8_t out_public_value[32], +void +ossl_x25519_public_from_private(uint8_t out_public_value[32], const uint8_t private_key[32]) { uint8_t e[32]; diff --git a/crypto/ec/curve448/arch_32/arch_intrinsics.h b/crypto/ec/curve448/arch_32/arch_intrinsics.h index 5f6389863d15..7a54903ac95a 100644 --- a/crypto/ec/curve448/arch_32/arch_intrinsics.h +++ b/crypto/ec/curve448/arch_32/arch_intrinsics.h @@ -2,7 +2,7 @@ * 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 + * Licensed under the Apache License 2.0 (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 diff --git a/crypto/ec/curve448/arch_32/f_impl.h b/crypto/ec/curve448/arch_32/f_impl.h index e1ddddaee08d..5cd25c04e123 100644 --- a/crypto/ec/curve448/arch_32/f_impl.h +++ b/crypto/ec/curve448/arch_32/f_impl.h @@ -2,7 +2,7 @@ * 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 + * Licensed under the Apache License 2.0 (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 diff --git a/crypto/ec/curve448/arch_32/f_impl.c b/crypto/ec/curve448/arch_32/f_impl32.c index 8a89d276edb6..8714a5142216 100644 --- a/crypto/ec/curve448/arch_32/f_impl.c +++ b/crypto/ec/curve448/arch_32/f_impl32.c @@ -1,8 +1,8 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -10,7 +10,16 @@ * Originally written by Mike Hamburg */ -#include "field.h" +#include "e_os.h" +#include <openssl/macros.h> +#include "internal/numbers.h" + +#ifdef UINT128_MAX +/* We have support for 128 bit ints, so do nothing here */ +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "../field.h" void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) { @@ -93,3 +102,4 @@ void gf_sqr(gf_s * RESTRICT cs, const gf as) { gf_mul(cs, as, as); /* Performs better with a dedicated square */ } +#endif diff --git a/crypto/ec/curve448/arch_64/arch_intrinsics.h b/crypto/ec/curve448/arch_64/arch_intrinsics.h new file mode 100644 index 000000000000..e12b8cf22624 --- /dev/null +++ b/crypto/ec/curve448/arch_64/arch_intrinsics.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016 Cryptography Research, Inc. + * + * Licensed under the Apache License 2.0 (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 OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H +# define OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H + +# include "internal/constant_time.h" + +# define ARCH_WORD_BITS 64 + +# define word_is_zero(a) constant_time_is_zero_64(a) + +static ossl_inline uint128_t widemul(uint64_t a, uint64_t b) +{ + return ((uint128_t) a) * b; +} + +#endif /* OSSL_CRYPTO_EC_CURVE448_ARCH_64_INTRINSICS_H */ diff --git a/crypto/ec/curve448/arch_64/f_impl.h b/crypto/ec/curve448/arch_64/f_impl.h new file mode 100644 index 000000000000..faaeb8d9944b --- /dev/null +++ b/crypto/ec/curve448/arch_64/f_impl.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2016 Cryptography Research, Inc. + * + * Licensed under the Apache License 2.0 (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 OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H +# define OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H + +# define GF_HEADROOM 9999 /* Everything is reduced anyway */ +# define FIELD_LITERAL(a,b,c,d,e,f,g,h) {{a,b,c,d,e,f,g,h}} + +# define LIMB_PLACE_VALUE(i) 56 + +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]; + + gf_weak_reduce(out); +} + +void gf_sub_RAW(gf out, const gf a, const gf b) +{ + uint64_t co1 = ((1ULL << 56) - 1) * 2, co2 = co1 - 2; + unsigned int i; + + for (i = 0; i < NLIMBS; i++) + out->limb[i] = a->limb[i] - b->limb[i] + ((i == NLIMBS / 2) ? co2 : co1); + + gf_weak_reduce(out); +} + +void gf_bias(gf a, int amt) +{ +} + +void gf_weak_reduce(gf a) +{ + uint64_t mask = (1ULL << 56) - 1; + uint64_t tmp = a->limb[NLIMBS - 1] >> 56; + 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] >> 56); + a->limb[0] = (a->limb[0] & mask) + tmp; +} + +#endif /* OSSL_CRYPTO_EC_CURVE448_ARCH_64_F_IMPL_H */ diff --git a/crypto/ec/curve448/arch_64/f_impl64.c b/crypto/ec/curve448/arch_64/f_impl64.c new file mode 100644 index 000000000000..dfe75b8fc5ca --- /dev/null +++ b/crypto/ec/curve448/arch_64/f_impl64.c @@ -0,0 +1,210 @@ +/* + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014 Cryptography Research, Inc. + * + * Licensed under the Apache License 2.0 (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 "e_os.h" +#include <openssl/macros.h> +#include "internal/numbers.h" + +#ifndef UINT128_MAX +/* No support for 128 bit ints, so do nothing here */ +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "../field.h" + +void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) +{ + const uint64_t *a = as->limb, *b = bs->limb; + uint64_t *c = cs->limb; + uint128_t accum0 = 0, accum1 = 0, accum2; + uint64_t mask = (1ULL << 56) - 1; + uint64_t aa[4], bb[4], bbb[4]; + unsigned int i, j; + + for (i = 0; i < 4; i++) { + aa[i] = a[i] + a[i + 4]; + bb[i] = b[i] + b[i + 4]; + bbb[i] = bb[i] + b[i + 4]; + } + + for (i = 0; i < 4; i++) { + accum2 = 0; + + for (j = 0; j <= i; j++) { + accum2 += widemul(a[j], b[i - j]); + accum1 += widemul(aa[j], bb[i - j]); + accum0 += widemul(a[j + 4], b[i - j + 4]); + } + for (; j < 4; j++) { + accum2 += widemul(a[j], b[i + 8 - j]); + accum1 += widemul(aa[j], bbb[i + 4 - j]); + accum0 += widemul(a[j + 4], bb[i + 4 - j]); + } + + accum1 -= accum2; + accum0 += accum2; + + c[i] = ((uint64_t)(accum0)) & mask; + c[i + 4] = ((uint64_t)(accum1)) & mask; + + accum0 >>= 56; + accum1 >>= 56; + } + + accum0 += accum1; + accum0 += c[4]; + accum1 += c[0]; + c[4] = ((uint64_t)(accum0)) & mask; + c[0] = ((uint64_t)(accum1)) & mask; + + accum0 >>= 56; + accum1 >>= 56; + + c[5] += ((uint64_t)(accum0)); + c[1] += ((uint64_t)(accum1)); +} + +void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) +{ + const uint64_t *a = as->limb; + uint64_t *c = cs->limb; + uint128_t accum0 = 0, accum4 = 0; + uint64_t mask = (1ULL << 56) - 1; + int i; + + for (i = 0; i < 4; i++) { + accum0 += widemul(b, a[i]); + accum4 += widemul(b, a[i + 4]); + c[i] = accum0 & mask; + accum0 >>= 56; + c[i + 4] = accum4 & mask; + accum4 >>= 56; + } + + accum0 += accum4 + c[4]; + c[4] = accum0 & mask; + c[5] += accum0 >> 56; + + accum4 += c[0]; + c[0] = accum4 & mask; + c[1] += accum4 >> 56; +} + +void gf_sqr(gf_s * RESTRICT cs, const gf as) +{ + const uint64_t *a = as->limb; + uint64_t *c = cs->limb; + uint128_t accum0 = 0, accum1 = 0, accum2; + uint64_t mask = (1ULL << 56) - 1; + uint64_t aa[4]; + unsigned int i; + + /* For some reason clang doesn't vectorize this without prompting? */ + for (i = 0; i < 4; i++) + aa[i] = a[i] + a[i + 4]; + + accum2 = widemul(a[0], a[3]); + accum0 = widemul(aa[0], aa[3]); + accum1 = widemul(a[4], a[7]); + + accum2 += widemul(a[1], a[2]); + accum0 += widemul(aa[1], aa[2]); + accum1 += widemul(a[5], a[6]); + + accum0 -= accum2; + accum1 += accum2; + + c[3] = ((uint64_t)(accum1)) << 1 & mask; + c[7] = ((uint64_t)(accum0)) << 1 & mask; + + accum0 >>= 55; + accum1 >>= 55; + + accum0 += widemul(2 * aa[1], aa[3]); + accum1 += widemul(2 * a[5], a[7]); + accum0 += widemul(aa[2], aa[2]); + accum1 += accum0; + + accum0 -= widemul(2 * a[1], a[3]); + accum1 += widemul(a[6], a[6]); + + accum2 = widemul(a[0], a[0]); + accum1 -= accum2; + accum0 += accum2; + + accum0 -= widemul(a[2], a[2]); + accum1 += widemul(aa[0], aa[0]); + accum0 += widemul(a[4], a[4]); + + c[0] = ((uint64_t)(accum0)) & mask; + c[4] = ((uint64_t)(accum1)) & mask; + + accum0 >>= 56; + accum1 >>= 56; + + accum2 = widemul(2 * aa[2], aa[3]); + accum0 -= widemul(2 * a[2], a[3]); + accum1 += widemul(2 * a[6], a[7]); + + accum1 += accum2; + accum0 += accum2; + + accum2 = widemul(2 * a[0], a[1]); + accum1 += widemul(2 * aa[0], aa[1]); + accum0 += widemul(2 * a[4], a[5]); + + accum1 -= accum2; + accum0 += accum2; + + c[1] = ((uint64_t)(accum0)) & mask; + c[5] = ((uint64_t)(accum1)) & mask; + + accum0 >>= 56; + accum1 >>= 56; + + accum2 = widemul(aa[3], aa[3]); + accum0 -= widemul(a[3], a[3]); + accum1 += widemul(a[7], a[7]); + + accum1 += accum2; + accum0 += accum2; + + accum2 = widemul(2 * a[0], a[2]); + accum1 += widemul(2 * aa[0], aa[2]); + accum0 += widemul(2 * a[4], a[6]); + + accum2 += widemul(a[1], a[1]); + accum1 += widemul(aa[1], aa[1]); + accum0 += widemul(a[5], a[5]); + + accum1 -= accum2; + accum0 += accum2; + + c[2] = ((uint64_t)(accum0)) & mask; + c[6] = ((uint64_t)(accum1)) & mask; + + accum0 >>= 56; + accum1 >>= 56; + + accum0 += c[3]; + accum1 += c[7]; + c[3] = ((uint64_t)(accum0)) & mask; + c[7] = ((uint64_t)(accum1)) & mask; + + /* we could almost stop here, but it wouldn't be stable, so... */ + + accum0 >>= 56; + accum1 >>= 56; + c[4] += ((uint64_t)(accum0)) + ((uint64_t)(accum1)); + c[0] += ((uint64_t)(accum1)); +} +#endif diff --git a/crypto/ec/curve448/curve448.c b/crypto/ec/curve448/curve448.c index 3d4db44564e9..6928d9693ca5 100644 --- a/crypto/ec/curve448/curve448.c +++ b/crypto/ec/curve448/curve448.c @@ -2,7 +2,7 @@ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -15,6 +15,7 @@ #include "point_448.h" #include "ed448.h" +#include "crypto/ecx.h" #include "curve448_local.h" #define COFACTOR 4 @@ -54,7 +55,7 @@ static void gf_invert(gf y, const gf x, int assert_nonzero) } /** identity = (0,1) */ -const curve448_point_t curve448_point_identity = +const curve448_point_t ossl_curve448_point_identity = { {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} }; static void point_double_internal(curve448_point_t p, const curve448_point_t q, @@ -81,7 +82,7 @@ static void point_double_internal(curve448_point_t p, const curve448_point_t q, gf_mul(p->t, b, d); } -void curve448_point_double(curve448_point_t p, const curve448_point_t q) +void ossl_curve448_point_double(curve448_point_t p, const curve448_point_t q) { point_double_internal(p, q, 0); } @@ -183,8 +184,9 @@ static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn, 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) +c448_bool_t +ossl_curve448_point_eq(const curve448_point_t p, + const curve448_point_t q) { mask_t succ; gf a, b; @@ -197,7 +199,8 @@ c448_bool_t curve448_point_eq(const curve448_point_t p, return mask_to_bool(succ); } -c448_bool_t curve448_point_valid(const curve448_point_t p) +c448_bool_t +ossl_curve448_point_valid(const curve448_point_t p) { mask_t out; gf a, b, c; @@ -224,7 +227,8 @@ static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni, constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx); } -void curve448_precomputed_scalarmul(curve448_point_t out, +void +ossl_curve448_precomputed_scalarmul(curve448_point_t out, const curve448_precomputed_s * table, const curve448_scalar_t scalar) { @@ -233,8 +237,8 @@ void curve448_precomputed_scalarmul(curve448_point_t out, niels_t ni; curve448_scalar_t scalar1x; - curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment); - curve448_scalar_halve(scalar1x, scalar1x); + ossl_curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment); + ossl_curve448_scalar_halve(scalar1x, scalar1x); for (i = s; i > 0; i--) { if (i != s) @@ -271,7 +275,8 @@ void curve448_precomputed_scalarmul(curve448_point_t out, OPENSSL_cleanse(scalar1x, sizeof(scalar1x)); } -void curve448_point_mul_by_ratio_and_encode_like_eddsa( +void +ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa( uint8_t enc[EDDSA_448_PUBLIC_BYTES], const curve448_point_t p) { @@ -315,10 +320,11 @@ void curve448_point_mul_by_ratio_and_encode_like_eddsa( OPENSSL_cleanse(y, sizeof(y)); OPENSSL_cleanse(z, sizeof(z)); OPENSSL_cleanse(t, sizeof(t)); - curve448_point_destroy(q); + ossl_curve448_point_destroy(q); } -c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio( +c448_error_t +ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio( curve448_point_t p, const uint8_t enc[EDDSA_448_PUBLIC_BYTES]) { @@ -371,14 +377,15 @@ c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio( } OPENSSL_cleanse(enc2, sizeof(enc2)); - assert(curve448_point_valid(p) || ~succ); + assert(ossl_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]) +c448_error_t +ossl_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; @@ -455,7 +462,8 @@ c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES], return c448_succeed_if(mask_to_bool(nz)); } -void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t +void +ossl_curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t out[X_PUBLIC_BYTES], const curve448_point_t p) { @@ -466,11 +474,11 @@ void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t 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); + ossl_curve448_point_destroy(q); } -void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES], - const uint8_t scalar[X_PRIVATE_BYTES]) +void ossl_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]; @@ -484,15 +492,16 @@ void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES], 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)); + ossl_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); + ossl_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); + ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, + the_scalar); + ossl_curve448_point_mul_by_ratio_and_encode_like_x448(out, p); + ossl_curve448_point_destroy(p); } /* Control for variable-time scalar multiply algorithms. */ @@ -501,9 +510,9 @@ struct smvt_control { }; #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) -# define NUMTRAILINGZEROS __builtin_ctz +# define NUMTRAILINGZEROS __builtin_ctz #else -# define NUMTRAILINGZEROS numtrailingzeros +# define NUMTRAILINGZEROS numtrailingzeros static uint32_t numtrailingzeros(uint32_t i) { uint32_t tmp; @@ -610,7 +619,7 @@ static void prepare_wnaf_table(pniels_t * output, if (tbits == 0) return; - curve448_point_double(tmp, working); + ossl_curve448_point_double(tmp, working); pt_to_pniels(twop, tmp); add_pniels_to_pt(tmp, output[0], 0); @@ -621,11 +630,12 @@ static void prepare_wnaf_table(pniels_t * output, pt_to_pniels(output[i], tmp); } - curve448_point_destroy(tmp); + ossl_curve448_point_destroy(tmp); OPENSSL_cleanse(twop, sizeof(twop)); } -void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, +void +ossl_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) @@ -645,7 +655,7 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, i = control_var[0].power; if (i < 0) { - curve448_point_copy(combo, curve448_point_identity); + curve448_point_copy(combo, ossl_curve448_point_identity); return; } if (i > control_pre[0].power) { @@ -653,13 +663,14 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, 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], + add_niels_to_pt(combo, + ossl_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]); + niels_to_pt(combo, ossl_curve448_wnaf_base[control_pre[0].addend >> 1]); contp++; } @@ -688,11 +699,11 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, if (control_pre[contp].addend > 0) add_niels_to_pt(combo, - curve448_wnaf_base[control_pre[contp].addend + ossl_curve448_wnaf_base[control_pre[contp].addend >> 1], i); else sub_niels_from_pt(combo, - curve448_wnaf_base[(-control_pre + ossl_curve448_wnaf_base[(-control_pre [contp].addend) >> 1], i); contp++; } @@ -709,20 +720,20 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, (void)ncb_pre; } -void curve448_point_destroy(curve448_point_t point) +void ossl_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]) +int ossl_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) + return ossl_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]) +void ossl_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); + ossl_x448_derive_public_key(out_public_value, private_key); } diff --git a/crypto/ec/curve448/curve448_local.h b/crypto/ec/curve448/curve448_local.h index b27770661f89..3410f091a655 100644 --- a/crypto/ec/curve448/curve448_local.h +++ b/crypto/ec/curve448/curve448_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -10,29 +10,15 @@ # define OSSL_CRYPTO_EC_CURVE448_LOCAL_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]); +int +ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, 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, const char *propq); -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]); +int +ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], + const uint8_t signature[114], const uint8_t public_key[57], + const uint8_t *context, size_t context_len, + const char *propq); #endif /* OSSL_CRYPTO_EC_CURVE448_LOCAL_H */ diff --git a/crypto/ec/curve448/curve448_tables.c b/crypto/ec/curve448/curve448_tables.c index 9ef29769e3b3..0c6f626b3e6e 100644 --- a/crypto/ec/curve448/curve448_tables.c +++ b/crypto/ec/curve448/curve448_tables.c @@ -1,8 +1,8 @@ /* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -1058,7 +1058,7 @@ static const curve448_precomputed_s curve448_precomputed_base_table = { }} } }; -const struct curve448_precomputed_s *curve448_precomputed_base +const struct curve448_precomputed_s *ossl_curve448_precomputed_base = &curve448_precomputed_base_table; static const niels_t curve448_wnaf_base_table[32] = { @@ -1480,4 +1480,4 @@ static const niels_t curve448_wnaf_base_table[32] = { 0x001979c0df237316ULL, 0x00501e953a919b87ULL)}, }} }; -const niels_t *curve448_wnaf_base = curve448_wnaf_base_table; +const niels_t *ossl_curve448_wnaf_base = curve448_wnaf_base_table; diff --git a/crypto/ec/curve448/curve448utils.h b/crypto/ec/curve448/curve448utils.h index 86c258e745e4..664c6e6ff306 100644 --- a/crypto/ec/curve448/curve448utils.h +++ b/crypto/ec/curve448/curve448utils.h @@ -1,8 +1,8 @@ /* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -15,6 +15,8 @@ # include <openssl/e_os2.h> +# include "internal/numbers.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 @@ -41,9 +43,9 @@ 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; +typedef uint128_t c448_dword_t; /* Signed double-word size for internal computations */ -typedef __int128_t c448_dsword_t; +typedef int128_t c448_dsword_t; # elif C448_WORD_BITS == 32 /* Word size for internal computations */ typedef uint32_t c448_word_t; diff --git a/crypto/ec/curve448/ed448.h b/crypto/ec/curve448/ed448.h index c1e5c2832f9b..00b2bae580ba 100644 --- a/crypto/ec/curve448/ed448.h +++ b/crypto/ec/curve448/ed448.h @@ -1,8 +1,8 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -37,9 +37,12 @@ * 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]); +c448_error_t +ossl_c448_ed448_derive_public_key( + OSSL_LIB_CTX *ctx, + uint8_t pubkey [EDDSA_448_PUBLIC_BYTES], + const uint8_t privkey [EDDSA_448_PRIVATE_BYTES], + const char *propq); /* * EdDSA signing. @@ -58,13 +61,15 @@ c448_error_t c448_ed448_derive_public_key( * 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); +c448_error_t +ossl_c448_ed448_sign(OSSL_LIB_CTX *ctx, + 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, + const char *propq); /* * EdDSA signing with prehash. @@ -82,13 +87,15 @@ c448_error_t c448_ed448_sign( * 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); +c448_error_t +ossl_c448_ed448_sign_prehash(OSSL_LIB_CTX *ctx, + 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, + const char *propq); /* * EdDSA signature verification. @@ -108,13 +115,16 @@ c448_error_t c448_ed448_sign_prehash( * 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); +c448_error_t +ossl_c448_ed448_verify(OSSL_LIB_CTX *ctx, + 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, + const char *propq); /* * EdDSA signature verification. @@ -133,12 +143,15 @@ c448_error_t c448_ed448_verify(const uint8_t * 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); +c448_error_t +ossl_c448_ed448_verify_prehash( + OSSL_LIB_CTX *ctx, + 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, + const char *propq); /* * EdDSA point encoding. Used internally, exposed externally. @@ -163,7 +176,8 @@ c448_error_t c448_ed448_verify_prehash( * enc (out): The encoded point. * p (in): The point. */ -void curve448_point_mul_by_ratio_and_encode_like_eddsa( +void +ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa( uint8_t enc [EDDSA_448_PUBLIC_BYTES], const curve448_point_t p); @@ -176,7 +190,8 @@ void 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( +c448_error_t +ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio( curve448_point_t p, const uint8_t enc[EDDSA_448_PUBLIC_BYTES]); @@ -188,8 +203,11 @@ c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio( * 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]); +c448_error_t +ossl_c448_ed448_convert_private_key_to_x448( + OSSL_LIB_CTX *ctx, + uint8_t x[X448_PRIVATE_BYTES], + const uint8_t ed[EDDSA_448_PRIVATE_BYTES], + const char *propq); #endif /* OSSL_CRYPTO_EC_CURVE448_ED448_H */ diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index 82741f543549..6648692ff395 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -1,8 +1,8 @@ /* - * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -12,6 +12,7 @@ #include <string.h> #include <openssl/crypto.h> #include <openssl/evp.h> +#include "crypto/ecx.h" #include "curve448_local.h" #include "word.h" #include "ed448.h" @@ -19,23 +20,31 @@ #define COFACTOR 4 -static c448_error_t oneshot_hash(uint8_t *out, size_t outlen, - const uint8_t *in, size_t inlen) +static c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen, + const uint8_t *in, size_t inlen, + const char *propq) { EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); + EVP_MD *shake256 = NULL; + c448_error_t ret = C448_FAILURE; if (hashctx == NULL) return C448_FAILURE; - if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) + shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); + if (shake256 == NULL) + goto err; + + if (!EVP_DigestInit_ex(hashctx, shake256, NULL) || !EVP_DigestUpdate(hashctx, in, inlen) - || !EVP_DigestFinalXOF(hashctx, out, outlen)) { - EVP_MD_CTX_free(hashctx); - return C448_FAILURE; - } + || !EVP_DigestFinalXOF(hashctx, out, outlen)) + goto err; + ret = C448_SUCCESS; + err: EVP_MD_CTX_free(hashctx); - return C448_SUCCESS; + EVP_MD_free(shake256); + return ret; } static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]) @@ -45,10 +54,12 @@ static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]) secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80; } -static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed, +static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, + uint8_t prehashed, uint8_t for_prehash, const uint8_t *context, - size_t context_len) + size_t context_len, + const char *propq) { #ifdef CHARSET_EBCDIC const char dom_s[] = {0x53, 0x69, 0x67, 0x45, @@ -57,6 +68,7 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed, const char dom_s[] = "SigEd448"; #endif uint8_t dom[2]; + EVP_MD *shake256 = NULL; if (context_len > UINT8_MAX) return C448_FAILURE; @@ -65,29 +77,42 @@ static c448_error_t hash_init_with_dom(EVP_MD_CTX *hashctx, uint8_t prehashed, - (for_prehash == 0 ? 1 : 0)); dom[1] = (uint8_t)context_len; - if (!EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) + shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); + if (shake256 == NULL) + return C448_FAILURE; + + if (!EVP_DigestInit_ex(hashctx, shake256, NULL) || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) - || !EVP_DigestUpdate(hashctx, context, context_len)) + || !EVP_DigestUpdate(hashctx, context, context_len)) { + EVP_MD_free(shake256); return C448_FAILURE; + } + EVP_MD_free(shake256); return C448_SUCCESS; } /* In this file because it uses the hash */ -c448_error_t c448_ed448_convert_private_key_to_x448( +c448_error_t +ossl_c448_ed448_convert_private_key_to_x448( + OSSL_LIB_CTX *ctx, uint8_t x[X448_PRIVATE_BYTES], - const uint8_t ed [EDDSA_448_PRIVATE_BYTES]) + const uint8_t ed [EDDSA_448_PRIVATE_BYTES], + const char *propq) { /* 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); + return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed, + EDDSA_448_PRIVATE_BYTES, propq); } -c448_error_t c448_ed448_derive_public_key( +c448_error_t +ossl_c448_ed448_derive_public_key( + OSSL_LIB_CTX *ctx, uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], - const uint8_t privkey[EDDSA_448_PRIVATE_BYTES]) + const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], + const char *propq) { /* only this much used for keygen */ uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]; @@ -95,14 +120,16 @@ c448_error_t c448_ed448_derive_public_key( unsigned int c; curve448_point_t p; - if (!oneshot_hash(secret_scalar_ser, sizeof(secret_scalar_ser), privkey, - EDDSA_448_PRIVATE_BYTES)) + if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser), + privkey, + EDDSA_448_PRIVATE_BYTES, + propq)) return C448_FAILURE; clamp(secret_scalar_ser); - curve448_scalar_decode_long(secret_scalar, secret_scalar_ser, - sizeof(secret_scalar_ser)); + ossl_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 @@ -113,27 +140,29 @@ c448_error_t c448_ed448_derive_public_key( * 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); + ossl_curve448_scalar_halve(secret_scalar, secret_scalar); - curve448_precomputed_scalarmul(p, curve448_precomputed_base, secret_scalar); + ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, + secret_scalar); - curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p); + ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p); /* Cleanup */ - curve448_scalar_destroy(secret_scalar); - curve448_point_destroy(p); + ossl_curve448_scalar_destroy(secret_scalar); + ossl_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) +c448_error_t +ossl_c448_ed448_sign(OSSL_LIB_CTX *ctx, + 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, const char *propq) { curve448_scalar_t secret_scalar; EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); @@ -148,20 +177,21 @@ c448_error_t c448_ed448_sign( { /* - * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialised + * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized * 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)) + if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey, + EDDSA_448_PRIVATE_BYTES, propq)) goto err; clamp(expanded); - curve448_scalar_decode_long(secret_scalar, expanded, - EDDSA_448_PRIVATE_BYTES); + ossl_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) + if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, + context_len, propq) || !EVP_DigestUpdate(hashctx, expanded + EDDSA_448_PRIVATE_BYTES, EDDSA_448_PRIVATE_BYTES) @@ -178,7 +208,7 @@ c448_error_t c448_ed448_sign( if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce))) goto err; - curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce)); + ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce)); OPENSSL_cleanse(nonce, sizeof(nonce)); } @@ -187,44 +217,45 @@ c448_error_t c448_ed448_sign( curve448_scalar_t nonce_scalar_2; curve448_point_t p; - curve448_scalar_halve(nonce_scalar_2, nonce_scalar); + ossl_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); + ossl_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); + ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, + nonce_scalar_2); + ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p); + ossl_curve448_point_destroy(p); + ossl_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) + if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len, + propq) || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point)) || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) || !EVP_DigestUpdate(hashctx, message, message_len) || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) goto err; - curve448_scalar_decode_long(challenge_scalar, challenge, - sizeof(challenge)); + ossl_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); + ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar); + ossl_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); + ossl_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); + ossl_curve448_scalar_destroy(secret_scalar); + ossl_curve448_scalar_destroy(nonce_scalar); + ossl_curve448_scalar_destroy(challenge_scalar); ret = C448_SUCCESS; err: @@ -232,23 +263,27 @@ c448_error_t c448_ed448_sign( return ret; } -c448_error_t c448_ed448_sign_prehash( +c448_error_t +ossl_c448_ed448_sign_prehash( + OSSL_LIB_CTX *ctx, 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) + size_t context_len, const char *propq) { - return c448_ed448_sign(signature, privkey, pubkey, hash, 64, 1, context, - context_len); + return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1, + context, context_len, propq); } -c448_error_t c448_ed448_verify( +c448_error_t +ossl_c448_ed448_verify( + OSSL_LIB_CTX *ctx, 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) + uint8_t context_len, const char *propq) { curve448_point_t pk_point, r_point; c448_error_t error; @@ -280,13 +315,13 @@ c448_error_t c448_ed448_verify( return C448_FAILURE; error = - curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); + ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); if (C448_SUCCESS != error) return error; error = - curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); + ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); if (C448_SUCCESS != error) return error; @@ -296,8 +331,8 @@ c448_error_t c448_ed448_verify( uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; if (hashctx == NULL - || !hash_init_with_dom(hashctx, prehashed, 0, context, - context_len) + || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context, + context_len, propq) || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES) || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) || !EVP_DigestUpdate(hashctx, message, message_len) @@ -307,71 +342,82 @@ c448_error_t c448_ed448_verify( } EVP_MD_CTX_free(hashctx); - curve448_scalar_decode_long(challenge_scalar, challenge, - sizeof(challenge)); + ossl_curve448_scalar_decode_long(challenge_scalar, challenge, + sizeof(challenge)); OPENSSL_cleanse(challenge, sizeof(challenge)); } - curve448_scalar_sub(challenge_scalar, curve448_scalar_zero, - challenge_scalar); + ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero, + challenge_scalar); - curve448_scalar_decode_long(response_scalar, - &signature[EDDSA_448_PUBLIC_BYTES], - EDDSA_448_PRIVATE_BYTES); + ossl_curve448_scalar_decode_long(response_scalar, + &signature[EDDSA_448_PUBLIC_BYTES], + EDDSA_448_PRIVATE_BYTES); /* pk_point = -c(x(P)) + (cx + k)G = kG */ - curve448_base_double_scalarmul_non_secret(pk_point, - response_scalar, - pk_point, challenge_scalar); - return c448_succeed_if(curve448_point_eq(pk_point, r_point)); + ossl_curve448_base_double_scalarmul_non_secret(pk_point, + response_scalar, + pk_point, challenge_scalar); + return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point)); } -c448_error_t c448_ed448_verify_prehash( +c448_error_t +ossl_c448_ed448_verify_prehash( + OSSL_LIB_CTX *ctx, 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) + uint8_t context_len, const char *propq) { - return c448_ed448_verify(signature, pubkey, hash, 64, 1, context, - context_len); + return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context, + context_len, propq); } -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 +ossl_ed448_sign(OSSL_LIB_CTX *ctx, 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, const char *propq) { - return c448_ed448_sign(out_sig, private_key, public_key, message, - message_len, 0, context, context_len) - == C448_SUCCESS; + return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message, + message_len, 0, context, context_len, + propq) == 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) +int +ossl_ed448_verify(OSSL_LIB_CTX *ctx, 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, const char *propq) { - return c448_ed448_verify(signature, public_key, message, message_len, 0, - context, (uint8_t)context_len) == C448_SUCCESS; + return ossl_c448_ed448_verify(ctx, signature, public_key, message, + message_len, 0, context, (uint8_t)context_len, + propq) == 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) +int +ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, 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, const char *propq) { - return c448_ed448_sign_prehash(out_sig, private_key, public_key, hash, - context, context_len) == C448_SUCCESS; - + return ossl_c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, + hash, context, context_len, + propq) == 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) +int +ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], + const uint8_t signature[114], const uint8_t public_key[57], + const uint8_t *context, size_t context_len, + const char *propq) { - return c448_ed448_verify_prehash(signature, public_key, hash, context, - (uint8_t)context_len) == C448_SUCCESS; + return ossl_c448_ed448_verify_prehash(ctx, signature, public_key, hash, + context, (uint8_t)context_len, + propq) == C448_SUCCESS; } -int ED448_public_from_private(uint8_t out_public_key[57], - const uint8_t private_key[57]) +int +ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57], + const uint8_t private_key[57], const char *propq) { - return c448_ed448_derive_public_key(out_public_key, private_key) - == C448_SUCCESS; + return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key, + propq) == C448_SUCCESS; } diff --git a/crypto/ec/curve448/f_generic.c b/crypto/ec/curve448/f_generic.c index 09d08165e250..4c571810d3af 100644 --- a/crypto/ec/curve448/f_generic.c +++ b/crypto/ec/curve448/f_generic.c @@ -1,8 +1,8 @@ /* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -18,7 +18,7 @@ static const gf MODULUS = { }; /* Serialize to wire format. */ -void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit) +void gf_serialize(uint8_t *serial, const gf x, int with_hibit) { unsigned int j = 0, fill = 0; dword_t buffer = 0; diff --git a/crypto/ec/curve448/field.h b/crypto/ec/curve448/field.h index 4e4eda664f78..e1c633378950 100644 --- a/crypto/ec/curve448/field.h +++ b/crypto/ec/curve448/field.h @@ -2,7 +2,7 @@ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -62,14 +62,19 @@ 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[SER_BYTES], const gf x, int with_highbit); +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) +# if (ARCH_WORD_BITS == 32) +# include "arch_32/f_impl.h" /* Bring in the inline implementations */ +# define LIMB_MASK(i) (((1)<<LIMB_PLACE_VALUE(i))-1) +# elif (ARCH_WORD_BITS == 64) +# include "arch_64/f_impl.h" /* Bring in the inline implementations */ +# define LIMB_MASK(i) (((1ULL)<<LIMB_PLACE_VALUE(i))-1) +# endif static const gf ZERO = {{{0}}}, ONE = {{{1}}}; diff --git a/crypto/ec/curve448/point_448.h b/crypto/ec/curve448/point_448.h index 93e715fd9c8d..e67ea68044eb 100644 --- a/crypto/ec/curve448/point_448.h +++ b/crypto/ec/curve448/point_448.h @@ -1,8 +1,8 @@ /* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -69,17 +69,17 @@ typedef struct curve448_scalar_s { } curve448_scalar_t[1]; /* A scalar equal to 1. */ -extern const curve448_scalar_t curve448_scalar_one; +extern const curve448_scalar_t ossl_curve448_scalar_one; /* A scalar equal to 0. */ -extern const curve448_scalar_t curve448_scalar_zero; +extern const curve448_scalar_t ossl_curve448_scalar_zero; /* The identity point on the curve. */ -extern const curve448_point_t curve448_point_identity; +extern const curve448_point_t ossl_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; +extern const struct curve448_precomputed_s *ossl_curve448_precomputed_base; +extern const niels_t *ossl_curve448_wnaf_base; /* * Read a scalar from wire format or from bytes. @@ -92,8 +92,9 @@ extern const niels_t *curve448_wnaf_base; * 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]); +c448_error_t +ossl_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. @@ -102,7 +103,8 @@ c448_error_t curve448_scalar_decode(curve448_scalar_t out, * ser_len (in): Length of serialized form. * out (out): Deserialized form. */ -void curve448_scalar_decode_long(curve448_scalar_t out, +void +ossl_curve448_scalar_decode_long(curve448_scalar_t out, const unsigned char *ser, size_t ser_len); /* @@ -111,7 +113,8 @@ void curve448_scalar_decode_long(curve448_scalar_t out, * ser (out): Serialized form of a scalar. * s (in): Deserialized scalar. */ -void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], +void +ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], const curve448_scalar_t s); /* @@ -121,7 +124,8 @@ void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], * b (in): Another scalar. * out (out): a+b. */ -void curve448_scalar_add(curve448_scalar_t out, +void +ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a, const curve448_scalar_t b); /* @@ -130,7 +134,8 @@ void curve448_scalar_add(curve448_scalar_t out, * b (in): Another scalar. * out (out): a-b. */ -void curve448_scalar_sub(curve448_scalar_t out, +void +ossl_curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a, const curve448_scalar_t b); /* @@ -140,7 +145,8 @@ void curve448_scalar_sub(curve448_scalar_t out, * b (in): Another scalar. * out (out): a*b. */ -void curve448_scalar_mul(curve448_scalar_t out, +void +ossl_curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a, const curve448_scalar_t b); /* @@ -149,7 +155,8 @@ void curve448_scalar_mul(curve448_scalar_t out, * a (in): A scalar. * out (out): a/2. */ -void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a); +void +ossl_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 @@ -188,8 +195,9 @@ static ossl_inline void curve448_point_copy(curve448_point_t a, * 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); +__owur c448_bool_t +ossl_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 @@ -198,7 +206,8 @@ __owur c448_bool_t curve448_point_eq(const curve448_point_t a, * 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); +void +ossl_curve448_point_double(curve448_point_t two_a, const curve448_point_t a); /* * RFC 7748 Diffie-Hellman scalarmul. This function uses a different @@ -213,9 +222,10 @@ void curve448_point_double(curve448_point_t two_a, const curve448_point_t a); * 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]); +__owur c448_error_t +ossl_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. @@ -236,7 +246,8 @@ __owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES], * 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( +void +ossl_curve448_point_mul_by_ratio_and_encode_like_x448( uint8_t out[X448_PUBLIC_BYTES], const curve448_point_t p); @@ -247,7 +258,8 @@ void curve448_point_mul_by_ratio_and_encode_like_x448( * 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], +void +ossl_x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], const uint8_t scalar[X448_PRIVATE_BYTES]); /* @@ -257,7 +269,8 @@ void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], * base (in): The point to be scaled. * scalar (in): The scalar to multiply by. */ -void curve448_precomputed_scalarmul(curve448_point_t scaled, +void +ossl_curve448_precomputed_scalarmul(curve448_point_t scaled, const curve448_precomputed_s * base, const curve448_scalar_t scalar); @@ -276,7 +289,8 @@ void curve448_precomputed_scalarmul(curve448_point_t scaled, * 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, +void +ossl_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); @@ -290,12 +304,13 @@ void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, * 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); +__owur c448_bool_t +ossl_curve448_point_valid(const curve448_point_t to_test); /* Overwrite scalar with zeros. */ -void curve448_scalar_destroy(curve448_scalar_t scalar); +void ossl_curve448_scalar_destroy(curve448_scalar_t scalar); /* Overwrite point with zeros. */ -void curve448_point_destroy(curve448_point_t point); +void ossl_curve448_point_destroy(curve448_point_t point); #endif /* OSSL_CRYPTO_EC_CURVE448_POINT_448_H */ diff --git a/crypto/ec/curve448/scalar.c b/crypto/ec/curve448/scalar.c index 347794bbac38..99c0d83db13b 100644 --- a/crypto/ec/curve448/scalar.c +++ b/crypto/ec/curve448/scalar.c @@ -1,8 +1,8 @@ /* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -38,8 +38,8 @@ static const curve448_scalar_t sc_p = { #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}}}; +const curve448_scalar_t ossl_curve448_scalar_one = {{{1}}}; +const curve448_scalar_t ossl_curve448_scalar_zero = {{{0}}}; /* * {extra,accum} - sub +? p @@ -106,20 +106,22 @@ static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a, 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) +void ossl_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, +void +ossl_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, +void +ossl_curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a, const curve448_scalar_t b) { c448_dword_t chain = 0; @@ -148,9 +150,9 @@ static ossl_inline void scalar_decode_short(curve448_scalar_t s, } } -c448_error_t curve448_scalar_decode( - curve448_scalar_t s, - const unsigned char ser[C448_SCALAR_BYTES]) +c448_error_t +ossl_curve448_scalar_decode(curve448_scalar_t s, + const unsigned char ser[C448_SCALAR_BYTES]) { unsigned int i; c448_dsword_t accum = 0; @@ -160,24 +162,25 @@ c448_error_t curve448_scalar_decode( 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 */ + ossl_curve448_scalar_mul(s, s, ossl_curve448_scalar_one); /* ham-handed reduce */ return c448_succeed_if(~word_is_zero((uint32_t)accum)); } -void curve448_scalar_destroy(curve448_scalar_t scalar) +void ossl_curve448_scalar_destroy(curve448_scalar_t scalar) { OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t)); } -void curve448_scalar_decode_long(curve448_scalar_t s, +void +ossl_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); + curve448_scalar_copy(s, ossl_curve448_scalar_zero); return; } @@ -190,24 +193,25 @@ void curve448_scalar_decode_long(curve448_scalar_t s, 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); + ossl_curve448_scalar_mul(s, t1, ossl_curve448_scalar_one); + ossl_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); + (void)ossl_curve448_scalar_decode(t2, ser + i); + ossl_curve448_scalar_add(t1, t1, t2); } curve448_scalar_copy(s, t1); - curve448_scalar_destroy(t1); - curve448_scalar_destroy(t2); + ossl_curve448_scalar_destroy(t1); + ossl_curve448_scalar_destroy(t2); } -void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], +void +ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], const curve448_scalar_t s) { unsigned int i, j, k = 0; @@ -218,7 +222,8 @@ void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], } } -void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a) +void +ossl_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; diff --git a/crypto/ec/curve448/word.h b/crypto/ec/curve448/word.h index 237cc9b63139..f8292eef88f2 100644 --- a/crypto/ec/curve448/word.h +++ b/crypto/ec/curve448/word.h @@ -1,8 +1,8 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -17,15 +17,20 @@ # include <assert.h> # include <stdlib.h> # include <openssl/e_os2.h> -# include "arch_intrinsics.h" # include "curve448utils.h" +# ifdef INT128_MAX +# include "arch_64/arch_intrinsics.h" +# else +# include "arch_32/arch_intrinsics.h" +# endif + # if (ARCH_WORD_BITS == 64) typedef uint64_t word_t, mask_t; -typedef __uint128_t dword_t; +typedef uint128_t dword_t; typedef int32_t hsword_t; typedef int64_t sword_t; -typedef __int128_t dsword_t; +typedef int128_t dsword_t; # elif (ARCH_WORD_BITS == 32) typedef uint32_t word_t, mask_t; typedef uint64_t dword_t; diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c index 788e6501fbcd..10a4932591d6 100644 --- a/crypto/ec/ec2_oct.c +++ b/crypto/ec/ec2_oct.c @@ -2,12 +2,18 @@ * Copyright 2011-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> #include "ec_local.h" @@ -30,23 +36,22 @@ * the same method, but claim no priority date earlier than July 29, 1994 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art). */ -int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, - EC_POINT *point, - const BIGNUM *x_, int y_bit, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) { - BN_CTX *new_ctx = NULL; BIGNUM *tmp, *x, *y, *z; int ret = 0, z0; - - /* clear error queue */ - ERR_clear_error(); +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } +#endif y_bit = (y_bit != 0) ? 1 : 0; @@ -72,19 +77,24 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, goto err; if (!BN_GF2m_add(tmp, x, tmp)) goto err; + ERR_set_mark(); if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) { +#ifndef FIPS_MODULE unsigned long err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) { - ERR_clear_error(); - ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, - EC_R_INVALID_COMPRESSED_POINT); + ERR_pop_to_mark(); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT); } else - ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, - ERR_R_BN_LIB); +#endif + { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + } goto err; } + ERR_clear_last_mark(); z0 = (BN_is_odd(z)) ? 1 : 0; if (!group->meth->field_mul(group, y, x, z, ctx)) goto err; @@ -101,7 +111,9 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -110,20 +122,23 @@ int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, * length will be returned. If the length len of buf is smaller than required * an error will be returned. */ -size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, - point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx) +size_t ossl_ec_GF2m_simple_point2oct(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) { size_t ret; - BN_CTX *new_ctx = NULL; int used_ctx = 0; BIGNUM *x, *y, *yxi; size_t field_len, i, skip; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); goto err; } @@ -131,7 +146,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, /* encodes to a single 0 octet */ if (buf != NULL) { if (len < 1) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } buf[0] = 0; @@ -148,15 +163,17 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, /* if 'buf' is NULL, just return required length */ if (buf != NULL) { if (len < ret) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); goto err; } +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } +#endif BN_CTX_start(ctx); used_ctx = 1; @@ -181,7 +198,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, skip = field_len - BN_num_bytes(x); if (skip > field_len) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { @@ -191,7 +208,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, skip = BN_bn2bin(x, buf + i); i += skip; if (i != 1 + field_len) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -199,7 +216,7 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, || form == POINT_CONVERSION_HYBRID) { skip = field_len - BN_num_bytes(y); if (skip > field_len) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { @@ -211,20 +228,24 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, } if (i != ret) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } } if (used_ctx) BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; err: if (used_ctx) BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return 0; } @@ -232,19 +253,21 @@ size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, * Converts an octet string representation to an EC_POINT. Note that the * simple implementation only uses affine coordinates. */ -int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, - const unsigned char *buf, size_t len, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, + BN_CTX *ctx) { point_conversion_form_t form; int y_bit, m; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y, *yxi; size_t field_len, enc_len; int ret = 0; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (len == 0) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } @@ -265,18 +288,18 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } /* The point at infinity is represented by a single zero octet. */ if (form == 0) { if (len != 1) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } @@ -290,15 +313,17 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; if (len != enc_len) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } +#endif BN_CTX_start(ctx); x = BN_CTX_get(ctx); @@ -310,7 +335,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!BN_bin2bn(buf + 1, field_len, x)) goto err; if (BN_num_bits(x) > m) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } @@ -321,7 +346,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; if (BN_num_bits(y) > m) { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } if (form == POINT_CONVERSION_HYBRID) { @@ -332,14 +357,14 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, */ if (BN_is_zero(x)) { if (y_bit != 0) { - ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } } else { if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; if (y_bit != BN_is_odd(yxi)) { - ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } } @@ -357,7 +382,9 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } #endif diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index 84e5537a034a..3a59544c8b2f 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -1,13 +1,19 @@ /* - * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> #include "crypto/bn.h" @@ -19,7 +25,7 @@ * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members * are handled by EC_GROUP_new. */ -int ec_GF2m_simple_group_init(EC_GROUP *group) +int ossl_ec_GF2m_simple_group_init(EC_GROUP *group) { group->field = BN_new(); group->a = BN_new(); @@ -38,7 +44,7 @@ int ec_GF2m_simple_group_init(EC_GROUP *group) * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are * handled by EC_GROUP_free. */ -void ec_GF2m_simple_group_finish(EC_GROUP *group) +void ossl_ec_GF2m_simple_group_finish(EC_GROUP *group) { BN_free(group->field); BN_free(group->a); @@ -49,7 +55,7 @@ void ec_GF2m_simple_group_finish(EC_GROUP *group) * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other * members are handled by EC_GROUP_clear_free. */ -void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) +void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *group) { BN_clear_free(group->field); BN_clear_free(group->a); @@ -66,7 +72,7 @@ void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are * handled by EC_GROUP_copy. */ -int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) +int ossl_ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) { if (!BN_copy(dest->field, src->field)) return 0; @@ -92,9 +98,9 @@ int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) } /* Set the curve parameters of an EC_GROUP structure. */ -int ec_GF2m_simple_group_set_curve(EC_GROUP *group, - const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *group, + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { int ret = 0, i; @@ -103,7 +109,7 @@ int ec_GF2m_simple_group_set_curve(EC_GROUP *group, goto err; i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1; if ((i != 5) && (i != 3)) { - ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD); goto err; } @@ -132,8 +138,8 @@ int ec_GF2m_simple_group_set_curve(EC_GROUP *group, * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL * then there values will not be set but the method will return with success. */ -int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, - BIGNUM *a, BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int ret = 0; @@ -162,7 +168,7 @@ int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, * Gets the degree of the field. For a curve over GF(2^m) this is the value * m. */ -int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) +int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *group) { return BN_num_bits(group->field) - 1; } @@ -171,21 +177,22 @@ int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an * elliptic curve <=> b != 0 (mod p) */ -int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, + BN_CTX *ctx) { int ret = 0; BIGNUM *b; +#ifndef FIPS_MODULE BN_CTX *new_ctx = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { - ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, - ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } +#endif BN_CTX_start(ctx); b = BN_CTX_get(ctx); if (b == NULL) @@ -205,12 +212,14 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } /* Initializes an EC_POINT. */ -int ec_GF2m_simple_point_init(EC_POINT *point) +int ossl_ec_GF2m_simple_point_init(EC_POINT *point) { point->X = BN_new(); point->Y = BN_new(); @@ -226,7 +235,7 @@ int ec_GF2m_simple_point_init(EC_POINT *point) } /* Frees an EC_POINT. */ -void ec_GF2m_simple_point_finish(EC_POINT *point) +void ossl_ec_GF2m_simple_point_finish(EC_POINT *point) { BN_free(point->X); BN_free(point->Y); @@ -234,7 +243,7 @@ void ec_GF2m_simple_point_finish(EC_POINT *point) } /* Clears and frees an EC_POINT. */ -void ec_GF2m_simple_point_clear_finish(EC_POINT *point) +void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *point) { BN_clear_free(point->X); BN_clear_free(point->Y); @@ -246,7 +255,7 @@ void ec_GF2m_simple_point_clear_finish(EC_POINT *point) * Copy the contents of one EC_POINT into another. Assumes dest is * initialized. */ -int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) +int ossl_ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { if (!BN_copy(dest->X, src->X)) return 0; @@ -264,8 +273,8 @@ int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) * Set an EC_POINT to the point at infinity. A point at infinity is * represented by having Z=0. */ -int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, - EC_POINT *point) +int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) { point->Z_is_one = 0; BN_zero(point->Z); @@ -276,15 +285,15 @@ int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, * Set the coordinates of an EC_POINT using affine coordinates. Note that * the simple implementation only uses affine coordinates. */ -int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, - EC_POINT *point, - const BIGNUM *x, - const BIGNUM *y, BN_CTX *ctx) +int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + BN_CTX *ctx) { int ret = 0; if (x == NULL || y == NULL) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, - ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -308,22 +317,20 @@ int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, * Gets the affine coordinates of an EC_POINT. Note that the simple * implementation only uses affine coordinates. */ -int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { int ret = 0; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if (BN_cmp(point->Z, BN_value_one())) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (x != NULL) { @@ -346,12 +353,14 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, * Computes a + b and stores the result in r. r could be a or b, a could be * b. Uses algorithm A.10.2 of IEEE P1363. */ -int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, - const EC_POINT *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { - BN_CTX *new_ctx = NULL; BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; int ret = 0; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (EC_POINT_is_at_infinity(group, a)) { if (!EC_POINT_copy(r, b)) @@ -365,11 +374,13 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, return 1; } +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } +#endif BN_CTX_start(ctx); x0 = BN_CTX_get(ctx); @@ -453,7 +464,9 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -461,26 +474,28 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, * Computes 2 * a and stores the result in r. r could be a. Uses algorithm * A.10.2 of IEEE P1363. */ -int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, + const EC_POINT *a, BN_CTX *ctx) { - return ec_GF2m_simple_add(group, r, a, a, ctx); + return ossl_ec_GF2m_simple_add(group, r, a, a, ctx); } -int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) +int ossl_ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) { if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y)) /* point is its own inverse */ return 1; - if (!EC_POINT_make_affine(group, point, ctx)) + if (group->meth->make_affine == NULL + || !group->meth->make_affine(group, point, ctx)) return 0; return BN_GF2m_add(point->Y, point->X, point->Y); } /* Indicates whether the given point is the point at infinity. */ -int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, - const EC_POINT *point) +int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point) { return BN_is_zero(point->Z); } @@ -490,15 +505,17 @@ int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: * y^2 + x*y = x^3 + a*x^2 + b. */ -int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) { int ret = -1; - BN_CTX *new_ctx = NULL; BIGNUM *lh, *y2; int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (EC_POINT_is_at_infinity(group, point)) return 1; @@ -510,11 +527,13 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, if (!point->Z_is_one) return -1; +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return -1; } +#endif BN_CTX_start(ctx); y2 = BN_CTX_get(ctx); @@ -546,7 +565,9 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -557,12 +578,14 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, * 0 equal (in affine coordinates) * 1 not equal */ -int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, - const EC_POINT *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { BIGNUM *aX, *aY, *bX, *bY; - BN_CTX *new_ctx = NULL; int ret = -1; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (EC_POINT_is_at_infinity(group, a)) { return EC_POINT_is_at_infinity(group, b) ? 0 : 1; @@ -575,11 +598,13 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1; } +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return -1; } +#endif BN_CTX_start(ctx); aX = BN_CTX_get(ctx); @@ -597,26 +622,32 @@ int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } /* Forces the given EC_POINT to internally use affine coordinates. */ -int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, - BN_CTX *ctx) +int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) { - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; int ret = 0; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) return 1; +#ifndef FIPS_MODULE if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } +#endif BN_CTX_start(ctx); x = BN_CTX_get(ctx); @@ -638,15 +669,17 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } /* * Forces each of the EC_POINTs in the given array to use affine coordinates. */ -int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, - EC_POINT *points[], BN_CTX *ctx) +int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) { size_t i; @@ -659,22 +692,22 @@ int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, } /* Wrapper to simple binary polynomial field multiplication implementation. */ -int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); } /* Wrapper to simple binary polynomial field squaring implementation. */ -int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, - const BIGNUM *a, BN_CTX *ctx) +int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) { return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); } /* Wrapper to simple binary polynomial field division implementation. */ -int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { return BN_GF2m_mod_div(r, a, b, group->field, ctx); } @@ -696,9 +729,9 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group, /* s blinding: make sure lambda (s->Z here) is not zero */ do { - if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1, - BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) { - ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB); + if (!BN_priv_rand_ex(s->Z, BN_num_bits(group->field) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } while (BN_is_zero(s->Z)); @@ -711,9 +744,9 @@ int ec_GF2m_simple_ladder_pre(const EC_GROUP *group, /* r blinding: make sure lambda (r->Y here for storage) is not zero */ do { - if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1, - BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) { - ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB); + if (!BN_priv_rand_ex(r->Y, BN_num_bits(group->field) - 1, + BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } while (BN_is_zero(r->Y)); @@ -782,7 +815,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group, if (BN_is_zero(s->Z)) { if (!EC_POINT_copy(r, p) || !EC_POINT_invert(group, r, ctx)) { - ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } return 1; @@ -793,7 +826,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group, t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t2 == NULL) { - ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -856,15 +889,15 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, * order or cofactor set to 0. */ if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor)) - return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + return ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); if (scalar != NULL && num == 0) /* Fixed point multiplication */ - return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); + return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); if (scalar == NULL && num == 1) /* Variable point multiplication */ - return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); + return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); /*- * Double point multiplication: @@ -872,12 +905,12 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, */ if ((t = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } - if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx) - || !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx) + if (!ossl_ec_scalar_mul_ladder(group, t, scalar, NULL, ctx) + || !ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx) || !EC_POINT_add(group, r, t, r, ctx)) goto err; @@ -899,7 +932,7 @@ static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r, int ret; if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx))) - ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT); + ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT); return ret; } @@ -908,54 +941,55 @@ const EC_METHOD *EC_GF2m_simple_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_characteristic_two_field, - ec_GF2m_simple_group_init, - ec_GF2m_simple_group_finish, - ec_GF2m_simple_group_clear_finish, - ec_GF2m_simple_group_copy, - ec_GF2m_simple_group_set_curve, - ec_GF2m_simple_group_get_curve, - ec_GF2m_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GF2m_simple_group_check_discriminant, - ec_GF2m_simple_point_init, - ec_GF2m_simple_point_finish, - ec_GF2m_simple_point_clear_finish, - ec_GF2m_simple_point_copy, - ec_GF2m_simple_point_set_to_infinity, - 0, /* set_Jprojective_coordinates_GFp */ - 0, /* get_Jprojective_coordinates_GFp */ - ec_GF2m_simple_point_set_affine_coordinates, - ec_GF2m_simple_point_get_affine_coordinates, + ossl_ec_GF2m_simple_group_init, + ossl_ec_GF2m_simple_group_finish, + ossl_ec_GF2m_simple_group_clear_finish, + ossl_ec_GF2m_simple_group_copy, + ossl_ec_GF2m_simple_group_set_curve, + ossl_ec_GF2m_simple_group_get_curve, + ossl_ec_GF2m_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GF2m_simple_group_check_discriminant, + ossl_ec_GF2m_simple_point_init, + ossl_ec_GF2m_simple_point_finish, + ossl_ec_GF2m_simple_point_clear_finish, + ossl_ec_GF2m_simple_point_copy, + ossl_ec_GF2m_simple_point_set_to_infinity, + ossl_ec_GF2m_simple_point_set_affine_coordinates, + ossl_ec_GF2m_simple_point_get_affine_coordinates, 0, /* point_set_compressed_coordinates */ 0, /* point2oct */ 0, /* oct2point */ - ec_GF2m_simple_add, - ec_GF2m_simple_dbl, - ec_GF2m_simple_invert, - ec_GF2m_simple_is_at_infinity, - ec_GF2m_simple_is_on_curve, - ec_GF2m_simple_cmp, - ec_GF2m_simple_make_affine, - ec_GF2m_simple_points_make_affine, + ossl_ec_GF2m_simple_add, + ossl_ec_GF2m_simple_dbl, + ossl_ec_GF2m_simple_invert, + ossl_ec_GF2m_simple_is_at_infinity, + ossl_ec_GF2m_simple_is_on_curve, + ossl_ec_GF2m_simple_cmp, + ossl_ec_GF2m_simple_make_affine, + ossl_ec_GF2m_simple_points_make_affine, ec_GF2m_simple_points_mul, 0, /* precompute_mult */ 0, /* have_precompute_mult */ - ec_GF2m_simple_field_mul, - ec_GF2m_simple_field_sqr, - ec_GF2m_simple_field_div, + ossl_ec_GF2m_simple_field_mul, + ossl_ec_GF2m_simple_field_sqr, + ossl_ec_GF2m_simple_field_div, ec_GF2m_simple_field_inv, 0, /* field_encode */ 0, /* field_decode */ 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ 0, /* blind_coordinates */ ec_GF2m_simple_ladder_pre, diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 5098bd7a6602..d4348ff244c7 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -1,34 +1,38 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDH and ECDSA low level APIs are deprecated for public use, but still ok + * for internal use. + */ +#include "internal/deprecated.h" + #include <stdio.h> #include "internal/cryptlib.h" #include <openssl/x509.h> #include <openssl/ec.h> #include <openssl/bn.h> -#include <openssl/cms.h> #include <openssl/asn1t.h> #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/x509.h" +#include <openssl/core_names.h> +#include <openssl/param_build.h> #include "ec_local.h" -#ifndef OPENSSL_NO_CMS -static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); -static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); -#endif - static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key) { const EC_GROUP *group; int nid; + if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { - ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); return 0; } if (EC_GROUP_get_asn1_flag(group) @@ -38,8 +42,7 @@ static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key) ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid); if (asn1obj == NULL || OBJ_length(asn1obj) == 0) { - ASN1_OBJECT_free(asn1obj); - ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_OID); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID); return 0; } *ppval = asn1obj; @@ -50,20 +53,10 @@ static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key) pstr = ASN1_STRING_new(); if (pstr == NULL) return 0; - - /* - * The cast in the following line is intentional as the - * `i2d_ECParameters` signature can't be constified (see discussion at - * https://github.com/openssl/openssl/pull/9347 where related and - * required constification backports were rejected). - * - * This cast should be safe anyway, because we can expect - * `i2d_ECParameters()` to treat the first argument as if it was const. - */ - pstr->length = i2d_ECParameters((EC_KEY *)ec_key, &pstr->data); + pstr->length = i2d_ECParameters(ec_key, &pstr->data); if (pstr->length <= 0) { ASN1_STRING_free(pstr); - ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } *ppval = pstr; @@ -81,7 +74,7 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) int penclen; if (!eckey_param2type(&ptype, &pval, ec_key)) { - ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } penclen = i2o_ECPublicKey(ec_key, NULL); @@ -98,80 +91,32 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) ptype, pval, penc, penclen)) return 1; err: - if (ptype == V_ASN1_OBJECT) - ASN1_OBJECT_free(pval); - else + if (ptype == V_ASN1_SEQUENCE) ASN1_STRING_free(pval); OPENSSL_free(penc); return 0; } -static EC_KEY *eckey_type2param(int ptype, const void *pval) -{ - EC_KEY *eckey = NULL; - EC_GROUP *group = NULL; - - if (ptype == V_ASN1_SEQUENCE) { - const ASN1_STRING *pstr = pval; - const unsigned char *pm = pstr->data; - int pmlen = pstr->length; - - if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) { - ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); - goto ecerr; - } - } else if (ptype == V_ASN1_OBJECT) { - const ASN1_OBJECT *poid = pval; - - /* - * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID - */ - if ((eckey = EC_KEY_new()) == NULL) { - ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); - goto ecerr; - } - group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); - if (group == NULL) - goto ecerr; - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); - if (EC_KEY_set_group(eckey, group) == 0) - goto ecerr; - EC_GROUP_free(group); - } else { - ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); - goto ecerr; - } - - return eckey; - - ecerr: - EC_KEY_free(eckey); - EC_GROUP_free(group); - return NULL; -} - -static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) { const unsigned char *p = NULL; - const void *pval; - int ptype, pklen; + int pklen; EC_KEY *eckey = NULL; X509_ALGOR *palg; + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; - if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey) + || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) return 0; - X509_ALGOR_get0(NULL, &ptype, &pval, palg); - - eckey = eckey_type2param(ptype, pval); + eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq); - if (!eckey) { - ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); + if (!eckey) return 0; - } /* We have parameters now set public key */ if (!o2i_ECPublicKey(&eckey, &p, pklen)) { - ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); goto ecerr; } @@ -189,6 +134,7 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), *pb = EC_KEY_get0_public_key(b->pkey.ec); + if (group == NULL || pa == NULL || pb == NULL) return -2; r = EC_POINT_cmp(group, pa, pb, NULL); @@ -199,49 +145,30 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -static int eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8, + OSSL_LIB_CTX *libctx, const char *propq) { - const unsigned char *p = NULL; - const void *pval; - int ptype, pklen; - EC_KEY *eckey = NULL; - const X509_ALGOR *palg; - - if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) - return 0; - X509_ALGOR_get0(NULL, &ptype, &pval, palg); - - eckey = eckey_type2param(ptype, pval); - - if (!eckey) - goto ecliberr; + int ret = 0; + EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq); - /* We have parameters now set private key */ - if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { - ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); - goto ecerr; + if (eckey != NULL) { + ret = 1; + EVP_PKEY_assign_EC_KEY(pkey, eckey); } - EVP_PKEY_assign_EC_KEY(pkey, eckey); - return 1; - - ecliberr: - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - ecerr: - EC_KEY_free(eckey); - return 0; + return ret; } static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { EC_KEY ec_key = *(pkey->pkey.ec); - unsigned char *ep, *p; + unsigned char *ep = NULL; int eplen, ptype; void *pval; unsigned int old_flags; if (!eckey_param2type(&ptype, &pval, &ec_key)) { - ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); return 0; } @@ -254,30 +181,25 @@ static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) old_flags = EC_KEY_get_enc_flags(&ec_key); EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); - eplen = i2d_ECPrivateKey(&ec_key, NULL); - if (!eplen) { - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); - return 0; - } - ep = OPENSSL_malloc(eplen); - if (ep == NULL) { - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); - return 0; - } - p = ep; - if (!i2d_ECPrivateKey(&ec_key, &p)) { - OPENSSL_free(ep); - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); - return 0; + eplen = i2d_ECPrivateKey(&ec_key, &ep); + if (eplen <= 0) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; } if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, ptype, pval, ep, eplen)) { - OPENSSL_free(ep); - return 0; + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); + OPENSSL_clear_free(ep, eplen); + goto err; } return 1; + + err: + if (ptype == V_ASN1_SEQUENCE) + ASN1_STRING_free(pval); + return 0; } static int int_ec_size(const EVP_PKEY *pkey) @@ -293,6 +215,7 @@ static int ec_bits(const EVP_PKEY *pkey) static int ec_security_bits(const EVP_PKEY *pkey) { int ecbits = ec_bits(pkey); + if (ecbits >= 512) return 256; if (ecbits >= 384) @@ -337,6 +260,7 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), *group_b = EC_KEY_get0_group(b->pkey.ec); + if (group_a == NULL || group_b == NULL) return -2; if (EC_GROUP_cmp(group_a, group_b, NULL)) @@ -365,7 +289,7 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) const EC_GROUP *group; if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { - ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -413,7 +337,7 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) ret = 1; err: if (!ret) - ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); OPENSSL_clear_free(priv, privlen); OPENSSL_free(pub); return ret; @@ -424,10 +348,8 @@ static int eckey_param_decode(EVP_PKEY *pkey, { EC_KEY *eckey; - if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) { - ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); + if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) return 0; - } EVP_PKEY_assign_EC_KEY(pkey, eckey); return 1; } @@ -460,10 +382,8 @@ static int old_ec_priv_decode(EVP_PKEY *pkey, { EC_KEY *ec; - if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) { - ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); + if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) return 0; - } EVP_PKEY_assign_EC_KEY(pkey, ec); return 1; } @@ -476,61 +396,20 @@ static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) { switch (op) { - case ASN1_PKEY_CTRL_PKCS7_SIGN: - if (arg1 == 0) { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) - return -1; - X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); - } - return 1; -#ifndef OPENSSL_NO_CMS - case ASN1_PKEY_CTRL_CMS_SIGN: - if (arg1 == 0) { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) - return -1; - X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); - } - return 1; - - case ASN1_PKEY_CTRL_CMS_ENVELOPE: - if (arg1 == 1) - return ecdh_cms_decrypt(arg2); - else if (arg1 == 0) - return ecdh_cms_encrypt(arg2); - return -2; - - case ASN1_PKEY_CTRL_CMS_RI_TYPE: - *(int *)arg2 = CMS_RECIPINFO_AGREE; - return 1; -#endif - case ASN1_PKEY_CTRL_DEFAULT_MD_NID: - if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { + if (EVP_PKEY_get_id(pkey) == EVP_PKEY_SM2) { /* For SM2, the only valid digest-alg is SM3 */ *(int *)arg2 = NID_sm3; - } else { - *(int *)arg2 = NID_sha256; + return 2; /* Make it mandatory */ } + *(int *)arg2 = NID_sha256; return 1; case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: - return EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(pkey), arg2, arg1, NULL); + /* We should only be here if we have a legacy key */ + if (!ossl_assert(evp_pkey_is_legacy(pkey))) + return 0; + return EC_KEY_oct2key(evp_pkey_get0_EC_KEY_int(pkey), arg2, arg1, NULL); case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey), @@ -538,9 +417,7 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) default: return -2; - } - } static int ec_pkey_check(const EVP_PKEY *pkey) @@ -549,7 +426,7 @@ static int ec_pkey_check(const EVP_PKEY *pkey) /* stay consistent to what EVP_PKEY_check demands */ if (eckey->priv_key == NULL) { - ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); return 0; } @@ -578,14 +455,200 @@ static int ec_pkey_param_check(const EVP_PKEY *pkey) /* stay consistent to what EVP_PKEY_check demands */ if (eckey->group == NULL) { - ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); return 0; } return EC_GROUP_check(eckey->group, NULL); } -const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { +static +size_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey) +{ + return pkey->pkey.ec->dirty_cnt; +} + +static +int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, + OSSL_FUNC_keymgmt_import_fn *importer, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const EC_KEY *eckey = NULL; + const EC_GROUP *ecg = NULL; + unsigned char *pub_key_buf = NULL, *gen_buf = NULL; + size_t pub_key_buflen; + OSSL_PARAM_BLD *tmpl; + OSSL_PARAM *params = NULL; + const BIGNUM *priv_key = NULL; + const EC_POINT *pub_point = NULL; + int selection = 0; + int rv = 0; + BN_CTX *bnctx = NULL; + + if (from == NULL + || (eckey = from->pkey.ec) == NULL + || (ecg = EC_KEY_get0_group(eckey)) == NULL) + return 0; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + return 0; + + /* + * EC_POINT_point2buf() can generate random numbers in some + * implementations so we need to ensure we use the correct libctx. + */ + bnctx = BN_CTX_new_ex(libctx); + if (bnctx == NULL) + goto err; + BN_CTX_start(bnctx); + + /* export the domain parameters */ + if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; + + priv_key = EC_KEY_get0_private_key(eckey); + pub_point = EC_KEY_get0_public_key(eckey); + + if (pub_point != NULL) { + /* convert pub_point to a octet string according to the SECG standard */ + point_conversion_form_t format = EC_KEY_get_conv_form(eckey); + + if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point, + format, + &pub_key_buf, bnctx)) == 0 + || !OSSL_PARAM_BLD_push_octet_string(tmpl, + OSSL_PKEY_PARAM_PUB_KEY, + pub_key_buf, + pub_key_buflen)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } + + if (priv_key != NULL) { + size_t sz; + int ecbits; + int ecdh_cofactor_mode; + + /* + * Key import/export should never leak the bit length of the secret + * scalar in the key. + * + * For this reason, on export we use padded BIGNUMs with fixed length. + * + * When importing we also should make sure that, even if short lived, + * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as + * soon as possible, so that any processing of this BIGNUM might opt for + * constant time implementations in the backend. + * + * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have + * to preallocate the BIGNUM internal buffer to a fixed public size big + * enough that operations performed during the processing never trigger + * a realloc which would leak the size of the scalar through memory + * accesses. + * + * Fixed Length + * ------------ + * + * The order of the large prime subgroup of the curve is our choice for + * a fixed public size, as that is generally the upper bound for + * generating a private key in EC cryptosystems and should fit all valid + * secret scalars. + * + * For padding on export we just use the bit length of the order + * converted to bytes (rounding up). + * + * For preallocating the BIGNUM storage we look at the number of "words" + * required for the internal representation of the order, and we + * preallocate 2 extra "words" in case any of the subsequent processing + * might temporarily overflow the order length. + */ + ecbits = EC_GROUP_order_bits(ecg); + if (ecbits <= 0) + goto err; + + sz = (ecbits + 7 ) / 8; + if (!OSSL_PARAM_BLD_push_BN_pad(tmpl, + OSSL_PKEY_PARAM_PRIV_KEY, + priv_key, sz)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; + + /* + * The ECDH Cofactor Mode is defined only if the EC_KEY actually + * contains a private key, so we check for the flag and export it only + * in this case. + */ + ecdh_cofactor_mode = + (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0; + + /* Export the ECDH_COFACTOR_MODE parameter */ + if (!OSSL_PARAM_BLD_push_int(tmpl, + OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, + ecdh_cofactor_mode)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; + } + + params = OSSL_PARAM_BLD_to_param(tmpl); + + /* We export, the provider imports */ + rv = importer(to_keydata, selection, params); + + err: + OSSL_PARAM_BLD_free(tmpl); + OSSL_PARAM_free(params); + OPENSSL_free(pub_key_buf); + OPENSSL_free(gen_buf); + BN_CTX_end(bnctx); + BN_CTX_free(bnctx); + return rv; +} + +static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx) +{ + EVP_PKEY_CTX *pctx = vpctx; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery); + + if (ec == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ossl_ec_group_fromdata(ec, params) + || !ossl_ec_key_otherparams_fromdata(ec, params) + || !ossl_ec_key_fromdata(ec, params, 1) + || !EVP_PKEY_assign_EC_KEY(pkey, ec)) { + EC_KEY_free(ec); + return 0; + } + return 1; +} + +static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) +{ + EC_KEY *eckey = from->pkey.ec; + EC_KEY *dupkey = NULL; + int ret; + + if (eckey != NULL) { + dupkey = EC_KEY_dup(eckey); + if (dupkey == NULL) + return 0; + } else { + /* necessary to properly copy empty SM2 keys */ + return EVP_PKEY_set_type(to, from->type); + } + + ret = EVP_PKEY_assign_EC_KEY(to, dupkey); + if (!ret) + EC_KEY_free(dupkey); + return ret; +} + +const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = { EVP_PKEY_EC, EVP_PKEY_EC, 0, @@ -597,7 +660,7 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { eckey_pub_cmp, eckey_pub_print, - eckey_priv_decode, + NULL, eckey_priv_encode, eckey_priv_print, @@ -622,11 +685,22 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { ec_pkey_check, ec_pkey_public_check, - ec_pkey_param_check + ec_pkey_param_check, + + 0, /* set_priv_key */ + 0, /* set_pub_key */ + 0, /* get_priv_key */ + 0, /* get_pub_key */ + + ec_pkey_dirty_cnt, + ec_pkey_export_to, + ec_pkey_import_from, + ec_pkey_copy, + eckey_priv_decode_ex }; #if !defined(OPENSSL_NO_SM2) -const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = { +const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = { EVP_PKEY_SM2, EVP_PKEY_EC, ASN1_PKEY_ALIAS @@ -645,320 +719,3 @@ int ECParameters_print(BIO *bp, const EC_KEY *x) { return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM); } - -#ifndef OPENSSL_NO_CMS - -static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, - X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) -{ - const ASN1_OBJECT *aoid; - int atype; - const void *aval; - int rv = 0; - EVP_PKEY *pkpeer = NULL; - EC_KEY *ecpeer = NULL; - const unsigned char *p; - int plen; - X509_ALGOR_get0(&aoid, &atype, &aval, alg); - if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) - goto err; - /* If absent parameters get group from main key */ - if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { - const EC_GROUP *grp; - EVP_PKEY *pk; - pk = EVP_PKEY_CTX_get0_pkey(pctx); - if (!pk) - goto err; - grp = EC_KEY_get0_group(pk->pkey.ec); - ecpeer = EC_KEY_new(); - if (ecpeer == NULL) - goto err; - if (!EC_KEY_set_group(ecpeer, grp)) - goto err; - } else { - ecpeer = eckey_type2param(atype, aval); - if (!ecpeer) - goto err; - } - /* We have parameters now set public key */ - plen = ASN1_STRING_length(pubkey); - p = ASN1_STRING_get0_data(pubkey); - if (!p || !plen) - goto err; - if (!o2i_ECPublicKey(&ecpeer, &p, plen)) - goto err; - pkpeer = EVP_PKEY_new(); - if (pkpeer == NULL) - goto err; - EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer); - if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) - rv = 1; - err: - EC_KEY_free(ecpeer); - EVP_PKEY_free(pkpeer); - return rv; -} - -/* Set KDF parameters based on KDF NID */ -static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) -{ - int kdf_nid, kdfmd_nid, cofactor; - const EVP_MD *kdf_md; - if (eckdf_nid == NID_undef) - return 0; - - /* Lookup KDF type, cofactor mode and digest */ - if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) - return 0; - - if (kdf_nid == NID_dh_std_kdf) - cofactor = 0; - else if (kdf_nid == NID_dh_cofactor_kdf) - cofactor = 1; - else - return 0; - - if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) - return 0; - - if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) - return 0; - - kdf_md = EVP_get_digestbynid(kdfmd_nid); - if (!kdf_md) - return 0; - - if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) - return 0; - return 1; -} - -static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) -{ - int rv = 0; - - X509_ALGOR *alg, *kekalg = NULL; - ASN1_OCTET_STRING *ukm; - const unsigned char *p; - unsigned char *der = NULL; - int plen, keylen; - const EVP_CIPHER *kekcipher; - EVP_CIPHER_CTX *kekctx; - - if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) - return 0; - - if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { - ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR); - return 0; - } - - if (alg->parameter->type != V_ASN1_SEQUENCE) - return 0; - - p = alg->parameter->value.sequence->data; - plen = alg->parameter->value.sequence->length; - kekalg = d2i_X509_ALGOR(NULL, &p, plen); - if (!kekalg) - goto err; - kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); - if (!kekctx) - goto err; - kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); - if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) - goto err; - if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) - goto err; - if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) - goto err; - - keylen = EVP_CIPHER_CTX_key_length(kekctx); - if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) - goto err; - - plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); - - if (!plen) - goto err; - - if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) - goto err; - der = NULL; - - rv = 1; - err: - X509_ALGOR_free(kekalg); - OPENSSL_free(der); - return rv; -} - -static int ecdh_cms_decrypt(CMS_RecipientInfo *ri) -{ - EVP_PKEY_CTX *pctx; - pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (!pctx) - return 0; - /* See if we need to set peer key */ - if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { - X509_ALGOR *alg; - ASN1_BIT_STRING *pubkey; - if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, - NULL, NULL, NULL)) - return 0; - if (!alg || !pubkey) - return 0; - if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) { - ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR); - return 0; - } - } - /* Set ECDH derivation parameters and initialise unwrap context */ - if (!ecdh_cms_set_shared_info(pctx, ri)) { - ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR); - return 0; - } - return 1; -} - -static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) -{ - EVP_PKEY_CTX *pctx; - EVP_PKEY *pkey; - EVP_CIPHER_CTX *ctx; - int keylen; - X509_ALGOR *talg, *wrap_alg = NULL; - const ASN1_OBJECT *aoid; - ASN1_BIT_STRING *pubkey; - ASN1_STRING *wrap_str; - ASN1_OCTET_STRING *ukm; - unsigned char *penc = NULL; - int penclen; - int rv = 0; - int ecdh_nid, kdf_type, kdf_nid, wrap_nid; - const EVP_MD *kdf_md; - pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (!pctx) - return 0; - /* Get ephemeral key */ - pkey = EVP_PKEY_CTX_get0_pkey(pctx); - if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, - NULL, NULL, NULL)) - goto err; - X509_ALGOR_get0(&aoid, NULL, NULL, talg); - /* Is everything uninitialised? */ - if (aoid == OBJ_nid2obj(NID_undef)) { - - EC_KEY *eckey = pkey->pkey.ec; - /* Set the key */ - unsigned char *p; - - penclen = i2o_ECPublicKey(eckey, NULL); - if (penclen <= 0) - goto err; - penc = OPENSSL_malloc(penclen); - if (penc == NULL) - goto err; - p = penc; - penclen = i2o_ECPublicKey(eckey, &p); - if (penclen <= 0) - goto err; - ASN1_STRING_set0(pubkey, penc, penclen); - pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; - - penc = NULL; - X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), - V_ASN1_UNDEF, NULL); - } - - /* See if custom parameters set */ - kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); - if (kdf_type <= 0) - goto err; - if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) - goto err; - ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); - if (ecdh_nid < 0) - goto err; - else if (ecdh_nid == 0) - ecdh_nid = NID_dh_std_kdf; - else if (ecdh_nid == 1) - ecdh_nid = NID_dh_cofactor_kdf; - - if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { - kdf_type = EVP_PKEY_ECDH_KDF_X9_63; - if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) - goto err; - } else - /* Unknown KDF */ - goto err; - if (kdf_md == NULL) { - /* Fixme later for better MD */ - kdf_md = EVP_sha1(); - if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) - goto err; - } - - if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) - goto err; - - /* Lookup NID for KDF+cofactor+digest */ - - if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) - goto err; - /* Get wrap NID */ - ctx = CMS_RecipientInfo_kari_get0_ctx(ri); - wrap_nid = EVP_CIPHER_CTX_type(ctx); - keylen = EVP_CIPHER_CTX_key_length(ctx); - - /* Package wrap algorithm in an AlgorithmIdentifier */ - - wrap_alg = X509_ALGOR_new(); - if (wrap_alg == NULL) - goto err; - wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); - wrap_alg->parameter = ASN1_TYPE_new(); - if (wrap_alg->parameter == NULL) - goto err; - if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) - goto err; - if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { - ASN1_TYPE_free(wrap_alg->parameter); - wrap_alg->parameter = NULL; - } - - if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) - goto err; - - penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); - - if (!penclen) - goto err; - - if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) - goto err; - penc = NULL; - - /* - * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter - * of another AlgorithmIdentifier. - */ - penclen = i2d_X509_ALGOR(wrap_alg, &penc); - if (!penc || !penclen) - goto err; - wrap_str = ASN1_STRING_new(); - if (wrap_str == NULL) - goto err; - ASN1_STRING_set0(wrap_str, penc, penclen); - penc = NULL; - X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); - - rv = 1; - - err: - OPENSSL_free(penc); - X509_ALGOR_free(wrap_alg); - return rv; -} - -#endif diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index 1acbbde3d37b..c018f392894d 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -1,90 +1,27 @@ /* * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include "ec_local.h" #include <openssl/err.h> #include <openssl/asn1t.h> #include <openssl/objects.h> #include "internal/nelem.h" +#include "crypto/asn1_dsa.h" -int EC_GROUP_get_basis_type(const EC_GROUP *group) -{ - int i; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field) - /* everything else is currently not supported */ - return 0; - - /* Find the last non-zero element of group->poly[] */ - for (i = 0; - i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0; - i++) - continue; - - if (i == 4) - return NID_X9_62_ppBasis; - else if (i == 2) - return NID_X9_62_tpBasis; - else - /* everything else is currently not supported */ - return 0; -} - -#ifndef OPENSSL_NO_EC2M -int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) -{ - if (group == NULL) - return 0; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field - || !((group->poly[0] != 0) && (group->poly[1] != 0) - && (group->poly[2] == 0))) { - ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - - if (k) - *k = group->poly[1]; - - return 1; -} - -int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, - unsigned int *k2, unsigned int *k3) -{ - if (group == NULL) - return 0; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field - || !((group->poly[0] != 0) && (group->poly[1] != 0) - && (group->poly[2] != 0) && (group->poly[3] != 0) - && (group->poly[4] == 0))) { - ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - - if (k1) - *k1 = group->poly[3]; - if (k2) - *k2 = group->poly[2]; - if (k3) - *k3 = group->poly[1]; - - return 1; -} -#endif +#ifndef FIPS_MODULE /* some structures needed for the asn1 encoding */ typedef struct x9_62_pentanomial_st { @@ -223,9 +160,9 @@ ASN1_CHOICE(ECPKPARAMETERS) = { ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) } ASN1_CHOICE_END(ECPKPARAMETERS) -DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) -IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) +DECLARE_ASN1_FUNCTIONS(ECPKPARAMETERS) +DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECPKPARAMETERS, ECPKPARAMETERS) +IMPLEMENT_ASN1_FUNCTIONS(ECPKPARAMETERS) ASN1_SEQUENCE(EC_PRIVATEKEY) = { ASN1_EMBED(EC_PRIVATEKEY, version, INT32), @@ -234,9 +171,9 @@ ASN1_SEQUENCE(EC_PRIVATEKEY) = { ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) } static_ASN1_SEQUENCE_END(EC_PRIVATEKEY) -DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY) -IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) +DECLARE_ASN1_FUNCTIONS(EC_PRIVATEKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_name(EC_PRIVATEKEY, EC_PRIVATEKEY) +IMPLEMENT_ASN1_FUNCTIONS(EC_PRIVATEKEY) /* some declarations of internal function */ @@ -259,33 +196,33 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) ASN1_OBJECT_free(field->fieldType); ASN1_TYPE_free(field->p.other); - nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + nid = EC_GROUP_get_field_type(group); /* set OID for the field */ if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB); goto err; } if (nid == NID_X9_62_prime_field) { if ((tmp = BN_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } /* the parameters are specified by the prime number p */ if (!EC_GROUP_get_curve(group, tmp, NULL, NULL, NULL)) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* set the prime number */ field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL); if (field->p.prime == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } else if (nid == NID_X9_62_characteristic_two_field) #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); goto err; } #else @@ -297,7 +234,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two = field->p.char_two; if (char_two == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -306,12 +243,12 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) field_type = EC_GROUP_get_basis_type(group); if (field_type == 0) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* set base type OID */ if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB); goto err; } @@ -323,11 +260,11 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two->p.tpBasis = ASN1_INTEGER_new(); if (char_two->p.tpBasis == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } else if (field_type == NID_X9_62_ppBasis) { @@ -338,7 +275,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); if (char_two->p.ppBasis == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -351,14 +288,14 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) /* for ONB the parameters are (asn1) NULL */ char_two->p.onBasis = ASN1_NULL_new(); if (char_two->p.onBasis == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } } #endif else { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_UNSUPPORTED_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD); goto err; } @@ -380,13 +317,13 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) return 0; if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } /* get a and b */ if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -398,19 +335,19 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8; if ((a_buf = OPENSSL_malloc(len)) == NULL || (b_buf = OPENSSL_malloc(len)) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (BN_bn2binpad(tmp_1, a_buf, len) < 0 || BN_bn2binpad(tmp_2, b_buf, len) < 0) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* set a and b */ if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len) || !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } @@ -418,14 +355,14 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) if (group->seed) { if (!curve->seed) if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; if (!ASN1_BIT_STRING_set(curve->seed, group->seed, (int)group->seed_len)) { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } else { @@ -444,7 +381,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) } ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, - ECPARAMETERS *params) + ECPARAMETERS *params) { size_t len = 0; ECPARAMETERS *ret = NULL; @@ -456,7 +393,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, if (params == NULL) { if ((ret = ECPARAMETERS_new()) == NULL) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } else @@ -467,19 +404,19 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, /* set the fieldID */ if (!ec_asn1_group2fieldid(group, ret->fieldID)) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* set the curve */ if (!ec_asn1_group2curve(group, ret->curve)) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* set the base point */ if ((point = EC_GROUP_get0_generator(group)) == NULL) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); goto err; } @@ -487,12 +424,12 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, len = EC_POINT_point2buf(group, point, form, &buffer, NULL); if (len == 0) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { OPENSSL_free(buffer); - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } ASN1_STRING_set0(ret->base, buffer, len); @@ -500,13 +437,13 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, /* set the order */ tmp = EC_GROUP_get0_order(group); if (tmp == NULL) { - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } ret->order = BN_to_ASN1_INTEGER(tmp, orig = ret->order); if (ret->order == NULL) { ret->order = orig; - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } @@ -516,7 +453,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, ret->cofactor = BN_to_ASN1_INTEGER(tmp, orig = ret->cofactor); if (ret->cofactor == NULL) { ret->cofactor = orig; - ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } @@ -537,7 +474,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, if (ret == NULL) { if ((ret = ECPKPARAMETERS_new()) == NULL) { - ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } } else { @@ -558,7 +495,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, if (asn1obj == NULL || OBJ_length(asn1obj) == 0) { ASN1_OBJECT_free(asn1obj); - ECerr(EC_F_EC_GROUP_GET_ECPKPARAMETERS, EC_R_MISSING_OID); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID); ok = 0; } else { ret->type = ECPKPARAMETERS_TYPE_NAMED; @@ -592,9 +529,10 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) int curve_name = NID_undef; BN_CTX *ctx = NULL; - if (!params->fieldID || !params->fieldID->fieldType || - !params->fieldID->p.ptr) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + if (params->fieldID == NULL + || params->fieldID->fieldType == NULL + || params->fieldID->p.ptr == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } @@ -604,20 +542,20 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) * encoded them incorrectly, so we must accept any length for backwards * compatibility. */ - if (!params->curve || !params->curve->a || - !params->curve->a->data || !params->curve->b || - !params->curve->b->data) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + if (params->curve == NULL + || params->curve->a == NULL || params->curve->a->data == NULL + || params->curve->b == NULL || params->curve->b->data == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); if (a == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); if (b == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -626,7 +564,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) if (tmp == NID_X9_62_characteristic_two_field) #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_GF2M_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); goto err; } #else @@ -637,12 +575,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) field_bits = char_two->m; if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); + ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); goto err; } if ((p = BN_new()) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -653,15 +591,14 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) long tmp_long; if (!char_two->p.tpBasis) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); if (!(char_two->m > tmp_long && tmp_long > 0)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, - EC_R_INVALID_TRINOMIAL_BASIS); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_TRINOMIAL_BASIS); goto err; } @@ -676,16 +613,15 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) X9_62_PENTANOMIAL *penta; penta = char_two->p.ppBasis; - if (!penta) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + if (penta == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } if (! (char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, - EC_R_INVALID_PENTANOMIAL_BASIS); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PENTANOMIAL_BASIS); goto err; } @@ -701,11 +637,11 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) if (!BN_set_bit(p, 0)) goto err; } else if (tmp == NID_X9_62_onBasis) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_NOT_IMPLEMENTED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_IMPLEMENTED); goto err; } else { /* error */ - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } @@ -716,36 +652,36 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) else if (tmp == NID_X9_62_prime_field) { /* we have a curve over a prime field */ /* extract the prime number */ - if (!params->fieldID->p.prime) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + if (params->fieldID->p.prime == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); if (p == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(p) || BN_is_zero(p)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); goto err; } field_bits = BN_num_bits(p); if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_FIELD_TOO_LARGE); + ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); goto err; } /* create the EC_GROUP structure */ ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); } else { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); goto err; } if (ret == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -758,12 +694,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) * zero length allocation request. */ if (params->curve->seed->length == 0) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } OPENSSL_free(ret->seed); if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } memcpy(ret->seed, params->curve->seed->data, @@ -775,7 +711,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) || params->base == NULL || params->base->data == NULL || params->base->length == 0) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_ASN1_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); goto err; } @@ -789,21 +725,21 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) /* extract the ec point */ if (!EC_POINT_oct2point(ret, point, params->base->data, params->base->length, NULL)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* extract the order */ if (ASN1_INTEGER_to_BN(params->order, a) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(a) || BN_is_zero(a)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); goto err; } if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, EC_R_INVALID_GROUP_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); goto err; } @@ -812,12 +748,12 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) BN_free(b); b = NULL; } else if (ASN1_INTEGER_to_BN(params->cofactor, b) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } /* set the generator, order and cofactor (if present) */ if (!EC_GROUP_set_generator(ret, point, a, b)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -834,16 +770,16 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) * mathematically wrong anyway and should not be used. */ if ((ctx = BN_CTX_new()) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if ((dup = EC_GROUP_dup(ret)) == NULL || EC_GROUP_set_seed(dup, NULL, 0) != 1 || !EC_GROUP_set_generator(dup, point, a, NULL)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } - if ((curve_name = ec_curve_nid_from_params(dup, ctx)) != NID_undef) { + if ((curve_name = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) { /* * The input explicit parameters successfully matched one of the * built-in curves: often for built-in curves we have specialized @@ -865,7 +801,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) #endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */ if ((named_group = EC_GROUP_new_by_curve_name(curve_name)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } EC_GROUP_free(ret); @@ -917,7 +853,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) int tmp = 0; if (params == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_MISSING_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); return NULL; } @@ -925,8 +861,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) /* the curve is given by an OID */ tmp = OBJ_obj2nid(params->value.named_curve); if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, - EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); return NULL; } EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); @@ -934,7 +869,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) /* the parameters are given by an ECPARAMETERS structure */ ret = EC_GROUP_new_from_ecparameters(params->value.parameters); if (!ret) { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return NULL; } EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_EXPLICIT_CURVE); @@ -942,7 +877,7 @@ EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params) /* implicit parameters inherited from CA - unsupported */ return NULL; } else { - ECerr(EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, EC_R_ASN1_ERROR); + ERR_raise(ERR_LIB_EC, EC_R_ASN1_ERROR); return NULL; } @@ -958,13 +893,11 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) const unsigned char *p = *in; if ((params = d2i_ECPKPARAMETERS(NULL, &p, len)) == NULL) { - ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); ECPKPARAMETERS_free(params); return NULL; } if ((group = EC_GROUP_new_from_ecpkparameters(params)) == NULL) { - ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); ECPKPARAMETERS_free(params); return NULL; } @@ -987,11 +920,11 @@ int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) int ret = 0; ECPKPARAMETERS *tmp = EC_GROUP_get_ecpkparameters(a, NULL); if (tmp == NULL) { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_GROUP2PKPARAMETERS_FAILURE); return 0; } if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_I2D_ECPKPARAMETERS_FAILURE); ECPKPARAMETERS_free(tmp); return 0; } @@ -1007,14 +940,12 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) EC_PRIVATEKEY *priv_key = NULL; const unsigned char *p = *in; - if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + if ((priv_key = d2i_EC_PRIVATEKEY(NULL, &p, len)) == NULL) return NULL; - } if (a == NULL || *a == NULL) { if ((ret = EC_KEY_new()) == NULL) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } else @@ -1029,7 +960,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) } if (ret->group == NULL) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1041,14 +972,17 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) ASN1_STRING_length(pkey)) == 0) goto err; } else { - ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); goto err; } + if (EC_GROUP_get_curve_name(ret->group) == NID_sm2) + EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE); + EC_POINT_clear_free(ret->pub_key); ret->pub_key = EC_POINT_new(ret->group); if (ret->pub_key == NULL) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1059,7 +993,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) pub_oct = ASN1_STRING_get0_data(priv_key->publicKey); pub_oct_len = ASN1_STRING_length(priv_key->publicKey); if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } else { @@ -1074,6 +1008,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) *a = ret; EC_PRIVATEKEY_free(priv_key); *in = p; + ret->dirty_cnt++; return ret; err: @@ -1083,7 +1018,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) return NULL; } -int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) +int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out) { int ret = 0, ok = 0; unsigned char *priv= NULL, *pub= NULL; @@ -1093,12 +1028,12 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) if (a == NULL || a->group == NULL || (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); goto err; } if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -1107,7 +1042,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) privlen = EC_KEY_priv2buf(a, &priv); if (privlen == 0) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1118,7 +1053,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) if ((priv_key->parameters = EC_GROUP_get_ecpkparameters(a->group, priv_key->parameters)) == NULL) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } @@ -1126,14 +1061,14 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) { priv_key->publicKey = ASN1_BIT_STRING_new(); if (priv_key->publicKey == NULL) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL); if (publen == 0) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1144,7 +1079,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) } if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } ok = 1; @@ -1155,10 +1090,10 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) return (ok ? ret : 0); } -int i2d_ECParameters(EC_KEY *a, unsigned char **out) +int i2d_ECParameters(const EC_KEY *a, unsigned char **out) { if (a == NULL) { - ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } return i2d_ECPKParameters(a->group, out); @@ -1169,25 +1104,31 @@ EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) EC_KEY *ret; if (in == NULL || *in == NULL) { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (a == NULL || *a == NULL) { if ((ret = EC_KEY_new()) == NULL) { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } } else ret = *a; if (!d2i_ECPKParameters(&ret->group, in, len)) { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); if (a == NULL || *a != ret) EC_KEY_free(ret); + else + ret->dirty_cnt++; return NULL; } + if (EC_GROUP_get_curve_name(ret->group) == NID_sm2) + EC_KEY_set_flags(ret, EC_FLAG_SM2_RANGE); + + ret->dirty_cnt++; + if (a) *a = ret; @@ -1202,12 +1143,13 @@ EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) /* * sorry, but a EC_GROUP-structure is necessary to set the public key */ - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } ret = *a; + /* EC_KEY_opt2key updates dirty_cnt */ if (!EC_KEY_oct2key(ret, *in, len, NULL)) { - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } *in += len; @@ -1219,8 +1161,8 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) size_t buf_len = 0; int new_buffer = 0; - if (a == NULL) { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + if (a == NULL || a->pub_key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -1233,14 +1175,14 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) if (*out == NULL) { if ((*out = OPENSSL_malloc(buf_len)) == NULL) { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } new_buffer = 1; } if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, *out, buf_len, NULL)) { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); if (new_buffer) { OPENSSL_free(*out); *out = NULL; @@ -1252,20 +1194,16 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) return buf_len; } -ASN1_SEQUENCE(ECDSA_SIG) = { - ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM), - ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM) -} static_ASN1_SEQUENCE_END(ECDSA_SIG) +DECLARE_ASN1_FUNCTIONS(ECDSA_SIG) +DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG) -DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG) -DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG) -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG) +#endif /* FIPS_MODULE */ ECDSA_SIG *ECDSA_SIG_new(void) { ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); if (sig == NULL) - ECerr(EC_F_ECDSA_SIG_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return sig; } @@ -1278,6 +1216,75 @@ void ECDSA_SIG_free(ECDSA_SIG *sig) OPENSSL_free(sig); } +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **psig, const unsigned char **ppin, long len) +{ + ECDSA_SIG *sig; + + if (len < 0) + return NULL; + if (psig != NULL && *psig != NULL) { + sig = *psig; + } else { + sig = ECDSA_SIG_new(); + if (sig == NULL) + return NULL; + } + if (sig->r == NULL) + sig->r = BN_new(); + if (sig->s == NULL) + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL + || ossl_decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) { + if (psig == NULL || *psig == NULL) + ECDSA_SIG_free(sig); + return NULL; + } + if (psig != NULL && *psig == NULL) + *psig = sig; + return sig; +} + +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **ppout) +{ + BUF_MEM *buf = NULL; + size_t encoded_len; + WPACKET pkt; + + if (ppout == NULL) { + if (!WPACKET_init_null(&pkt, 0)) + return -1; + } else if (*ppout == NULL) { + if ((buf = BUF_MEM_new()) == NULL + || !WPACKET_init_len(&pkt, buf, 0)) { + BUF_MEM_free(buf); + return -1; + } + } else { + if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0)) + return -1; + } + + if (!ossl_encode_der_dsa_sig(&pkt, sig->r, sig->s) + || !WPACKET_get_total_written(&pkt, &encoded_len) + || !WPACKET_finish(&pkt)) { + BUF_MEM_free(buf); + WPACKET_cleanup(&pkt); + return -1; + } + + if (ppout != NULL) { + if (*ppout == NULL) { + *ppout = (unsigned char *)buf->data; + buf->data = NULL; + BUF_MEM_free(buf); + } else { + *ppout += encoded_len; + } + } + + return (int)encoded_len; +} + void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr != NULL) @@ -1307,32 +1314,27 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) return 1; } -int ECDSA_size(const EC_KEY *r) +int ECDSA_size(const EC_KEY *ec) { - int ret, i; - ASN1_INTEGER bs; - unsigned char buf[4]; + int ret; + ECDSA_SIG sig; const EC_GROUP *group; + const BIGNUM *bn; - if (r == NULL) + if (ec == NULL) return 0; - group = EC_KEY_get0_group(r); + group = EC_KEY_get0_group(ec); if (group == NULL) return 0; - i = EC_GROUP_order_bits(group); - if (i == 0) + bn = EC_GROUP_get0_order(group); + if (bn == NULL) return 0; - bs.length = (i + 7) / 8; - bs.data = buf; - bs.type = V_ASN1_INTEGER; - /* If the top bit is set the asn1 encoding is 1 larger. */ - buf[0] = 0xff; - - i = i2d_ASN1_INTEGER(&bs, NULL); - i += i; /* r and s */ - ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); + + sig.r = sig.s = (BIGNUM *)bn; + ret = i2d_ECDSA_SIG(&sig, NULL); + if (ret < 0) - return 0; + ret = 0; return ret; } diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c new file mode 100644 index 000000000000..cad576fc48a1 --- /dev/null +++ b/crypto/ec/ec_backend.c @@ -0,0 +1,836 @@ +/* + * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +/* + * Low level APIs related to EC_KEY are deprecated for public use, + * but still ok for internal use. + */ +#include "internal/deprecated.h" + +#include <openssl/core_names.h> +#include <openssl/objects.h> +#include <openssl/params.h> +#include <openssl/err.h> +#ifndef FIPS_MODULE +# include <openssl/engine.h> +# include <openssl/x509.h> +#endif +#include "crypto/bn.h" +#include "crypto/ec.h" +#include "ec_local.h" +#include "e_os.h" +#include "internal/param_build_set.h" + +/* Mapping between a flag and a name */ +static const OSSL_ITEM encoding_nameid_map[] = { + { OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT }, + { OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP }, +}; + +static const OSSL_ITEM check_group_type_nameid_map[] = { + { 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT }, + { EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED }, + { EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST }, +}; + +static const OSSL_ITEM format_nameid_map[] = { + { (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED }, + { (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED }, + { (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID }, +}; + +int ossl_ec_encoding_name2id(const char *name) +{ + size_t i, sz; + + /* Return the default value if there is no name */ + if (name == NULL) + return OPENSSL_EC_NAMED_CURVE; + + for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) { + if (OPENSSL_strcasecmp(name, encoding_nameid_map[i].ptr) == 0) + return encoding_nameid_map[i].id; + } + return -1; +} + +static char *ec_param_encoding_id2name(int id) +{ + size_t i, sz; + + for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) { + if (id == (int)encoding_nameid_map[i].id) + return encoding_nameid_map[i].ptr; + } + return NULL; +} + +char *ossl_ec_check_group_type_id2name(int id) +{ + size_t i, sz; + + for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) { + if (id == (int)check_group_type_nameid_map[i].id) + return check_group_type_nameid_map[i].ptr; + } + return NULL; +} + +static int ec_check_group_type_name2id(const char *name) +{ + size_t i, sz; + + /* Return the default value if there is no name */ + if (name == NULL) + return 0; + + for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) { + if (OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0) + return check_group_type_nameid_map[i].id; + } + return -1; +} + +int ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name) +{ + int flags = ec_check_group_type_name2id(name); + + if (flags == -1) + return 0; + EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK); + EC_KEY_set_flags(ec, flags); + return 1; +} + +static int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) + return ossl_ec_set_check_group_type_from_name(ec, name); + return 0; +} + +int ossl_ec_pt_format_name2id(const char *name) +{ + size_t i, sz; + + /* Return the default value if there is no name */ + if (name == NULL) + return (int)POINT_CONVERSION_UNCOMPRESSED; + + for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) { + if (OPENSSL_strcasecmp(name, format_nameid_map[i].ptr) == 0) + return format_nameid_map[i].id; + } + return -1; +} + +char *ossl_ec_pt_format_id2name(int id) +{ + size_t i, sz; + + for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) { + if (id == (int)format_nameid_map[i].id) + return format_nameid_map[i].ptr; + } + return NULL; +} + +static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, + OSSL_PARAM params[], BN_CTX *bnctx, + unsigned char **genbuf) +{ + int ret = 0, fid; + const char *field_type; + const OSSL_PARAM *param = NULL; + const OSSL_PARAM *param_p = NULL; + const OSSL_PARAM *param_a = NULL; + const OSSL_PARAM *param_b = NULL; + + fid = EC_GROUP_get_field_type(group); + + if (fid == NID_X9_62_prime_field) { + field_type = SN_X9_62_prime_field; + } else if (fid == NID_X9_62_characteristic_two_field) { +#ifdef OPENSSL_NO_EC2M + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); + goto err; +#else + field_type = SN_X9_62_characteristic_two_field; +#endif + } else { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); + return 0; + } + + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P); + param_a = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A); + param_b = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B); + if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL) + { + BIGNUM *p = BN_CTX_get(bnctx); + BIGNUM *a = BN_CTX_get(bnctx); + BIGNUM *b = BN_CTX_get(bnctx); + + if (b == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_GROUP_get_curve(group, p, a, b, bnctx)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); + goto err; + } + if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_P, p) + || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_A, a) + || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_B, b)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER); + if (tmpl != NULL || param != NULL) { + const BIGNUM *order = EC_GROUP_get0_order(group); + + if (order == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); + goto err; + } + if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_ORDER, + order)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE); + if (tmpl != NULL || param != NULL) { + if (!ossl_param_build_set_utf8_string(tmpl, params, + OSSL_PKEY_PARAM_EC_FIELD_TYPE, + field_type)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR); + if (tmpl != NULL || param != NULL) { + size_t genbuf_len; + const EC_POINT *genpt = EC_GROUP_get0_generator(group); + point_conversion_form_t genform = EC_GROUP_get_point_conversion_form(group); + + if (genpt == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); + goto err; + } + genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx); + if (genbuf_len == 0) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); + goto err; + } + if (!ossl_param_build_set_octet_string(tmpl, params, + OSSL_PKEY_PARAM_EC_GENERATOR, + *genbuf, genbuf_len)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR); + if (tmpl != NULL || param != NULL) { + const BIGNUM *cofactor = EC_GROUP_get0_cofactor(group); + + if (cofactor != NULL + && !ossl_param_build_set_bn(tmpl, params, + OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED); + if (tmpl != NULL || param != NULL) { + unsigned char *seed = EC_GROUP_get0_seed(group); + size_t seed_len = EC_GROUP_get_seed_len(group); + + if (seed != NULL + && seed_len > 0 + && !ossl_param_build_set_octet_string(tmpl, params, + OSSL_PKEY_PARAM_EC_SEED, + seed, seed_len)) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ret = 1; +err: + return ret; +} + +int ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, + OSSL_PARAM params[], OSSL_LIB_CTX *libctx, + const char *propq, + BN_CTX *bnctx, unsigned char **genbuf) +{ + int ret = 0, curve_nid, encoding_flag; + const char *encoding_name, *pt_form_name; + point_conversion_form_t genform; + + if (group == NULL) { + ERR_raise(ERR_LIB_EC,EC_R_PASSED_NULL_PARAMETER); + return 0; + } + + genform = EC_GROUP_get_point_conversion_form(group); + pt_form_name = ossl_ec_pt_format_id2name(genform); + if (pt_form_name == NULL + || !ossl_param_build_set_utf8_string( + tmpl, params, + OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); + return 0; + } + encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE; + encoding_name = ec_param_encoding_id2name(encoding_flag); + if (encoding_name == NULL + || !ossl_param_build_set_utf8_string(tmpl, params, + OSSL_PKEY_PARAM_EC_ENCODING, + encoding_name)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + return 0; + } + + if (!ossl_param_build_set_int(tmpl, params, + OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, + group->decoded_from_explicit_params)) + return 0; + + curve_nid = EC_GROUP_get_curve_name(group); + + /* + * Get the explicit parameters in these two cases: + * - We do not have a template, i.e. specific parameters are requested + * - The curve is not a named curve + */ + if (tmpl == NULL || curve_nid == NID_undef) + if (!ec_group_explicit_todata(group, tmpl, params, bnctx, genbuf)) + goto err; + + if (curve_nid != NID_undef) { + /* Named curve */ + const char *curve_name = OSSL_EC_curve_nid2name(curve_nid); + + if (curve_name == NULL + || !ossl_param_build_set_utf8_string(tmpl, params, + OSSL_PKEY_PARAM_GROUP_NAME, + curve_name)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); + goto err; + } + } + ret = 1; +err: + return ret; +} + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ +int ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode) +{ + const EC_GROUP *ecg = EC_KEY_get0_group(ec); + const BIGNUM *cofactor; + /* + * mode can be only 0 for disable, or 1 for enable here. + * + * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that + * also supports mode == -1 with the meaning of "reset to the default for + * the associated key". + */ + if (mode < 0 || mode > 1) + return 0; + + if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL ) + return 0; + + /* ECDH cofactor mode has no effect if cofactor is 1 */ + if (BN_is_one(cofactor)) + return 1; + + if (mode == 1) + EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH); + else if (mode == 0) + EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH); + + return 1; +} + +/* + * Callers of ossl_ec_key_fromdata MUST make sure that ec_key_params_fromdata has + * been called before! + * + * This function only gets the bare keypair, domain parameters and other + * parameters are treated separately, and domain parameters are required to + * define a keypair. + */ +int ossl_ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private) +{ + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL; + BN_CTX *ctx = NULL; + BIGNUM *priv_key = NULL; + unsigned char *pub_key = NULL; + size_t pub_key_len; + const EC_GROUP *ecg = NULL; + EC_POINT *pub_point = NULL; + int ok = 0; + + ecg = EC_KEY_get0_group(ec); + if (ecg == NULL) + return 0; + + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (include_private) + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + + ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec)); + if (ctx == NULL) + goto err; + + if (param_pub_key != NULL) + if (!OSSL_PARAM_get_octet_string(param_pub_key, + (void **)&pub_key, 0, &pub_key_len) + || (pub_point = EC_POINT_new(ecg)) == NULL + || !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx)) + goto err; + + if (param_priv_key != NULL && include_private) { + int fixed_words; + const BIGNUM *order; + + /* + * Key import/export should never leak the bit length of the secret + * scalar in the key. + * + * For this reason, on export we use padded BIGNUMs with fixed length. + * + * When importing we also should make sure that, even if short lived, + * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as + * soon as possible, so that any processing of this BIGNUM might opt for + * constant time implementations in the backend. + * + * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have + * to preallocate the BIGNUM internal buffer to a fixed public size big + * enough that operations performed during the processing never trigger + * a realloc which would leak the size of the scalar through memory + * accesses. + * + * Fixed Length + * ------------ + * + * The order of the large prime subgroup of the curve is our choice for + * a fixed public size, as that is generally the upper bound for + * generating a private key in EC cryptosystems and should fit all valid + * secret scalars. + * + * For padding on export we just use the bit length of the order + * converted to bytes (rounding up). + * + * For preallocating the BIGNUM storage we look at the number of "words" + * required for the internal representation of the order, and we + * preallocate 2 extra "words" in case any of the subsequent processing + * might temporarily overflow the order length. + */ + order = EC_GROUP_get0_order(ecg); + if (order == NULL || BN_is_zero(order)) + goto err; + + fixed_words = bn_get_top(order) + 2; + + if ((priv_key = BN_secure_new()) == NULL) + goto err; + if (bn_wexpand(priv_key, fixed_words) == NULL) + goto err; + BN_set_flags(priv_key, BN_FLG_CONSTTIME); + + if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + goto err; + } + + if (priv_key != NULL + && !EC_KEY_set_private_key(ec, priv_key)) + goto err; + + if (pub_point != NULL + && !EC_KEY_set_public_key(ec, pub_point)) + goto err; + + ok = 1; + + err: + BN_CTX_free(ctx); + BN_clear_free(priv_key); + OPENSSL_free(pub_key); + EC_POINT_free(pub_point); + return ok; +} + +int ossl_ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + int ok = 0; + EC_GROUP *group = NULL; + + if (ec == NULL) + return 0; + + group = EC_GROUP_new_from_params(params, ossl_ec_key_get_libctx(ec), + ossl_ec_key_get0_propq(ec)); + + if (!EC_KEY_set_group(ec, group)) + goto err; + ok = 1; +err: + EC_GROUP_free(group); + return ok; +} + +static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + int format = -1; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); + if (p != NULL) { + if (!ossl_ec_pt_format_param2id(p, &format)) { + ECerr(0, EC_R_INVALID_FORM); + return 0; + } + EC_KEY_set_conv_form(ec, format); + } + return 1; +} + +static int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE); + if (p != NULL) + return ec_set_check_group_type_from_param(ec, p); + return 1; +} + +static int ec_set_include_public(EC_KEY *ec, int include) +{ + int flags = EC_KEY_get_enc_flags(ec); + + if (!include) + flags |= EC_PKEY_NO_PUBKEY; + else + flags &= ~EC_PKEY_NO_PUBKEY; + EC_KEY_set_enc_flags(ec, flags); + return 1; +} + +int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + if (ec == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH); + if (p != NULL) { + int mode; + + if (!OSSL_PARAM_get_int(p, &mode) + || !ossl_ec_set_ecdh_cofactor_mode(ec, mode)) + return 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC); + if (p != NULL) { + int include = 1; + + if (!OSSL_PARAM_get_int(p, &include) + || !ec_set_include_public(ec, include)) + return 0; + } + if (!ec_key_point_format_fromdata(ec, params)) + return 0; + if (!ec_key_group_check_fromdata(ec, params)) + return 0; + return 1; +} + +int ossl_ec_key_is_foreign(const EC_KEY *ec) +{ +#ifndef FIPS_MODULE + if (ec->engine != NULL || EC_KEY_get_method(ec) != EC_KEY_OpenSSL()) + return 1; +#endif + return 0; + +} + +EC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection) +{ + EC_KEY *ret; + + if (src == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((ret = ossl_ec_key_new_method_int(src->libctx, src->propq, + src->engine)) == NULL) + return NULL; + + /* copy the parameters */ + if (src->group != NULL + && (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { + ret->group = ossl_ec_group_new_ex(src->libctx, src->propq, + src->group->meth); + if (ret->group == NULL + || !EC_GROUP_copy(ret->group, src->group)) + goto err; + + if (src->meth != NULL) + ret->meth = src->meth; + } + + /* copy the public key */ + if (src->pub_key != NULL + && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + if (ret->group == NULL) + /* no parameter-less keys allowed */ + goto err; + ret->pub_key = EC_POINT_new(ret->group); + if (ret->pub_key == NULL + || !EC_POINT_copy(ret->pub_key, src->pub_key)) + goto err; + } + + /* copy the private key */ + if (src->priv_key != NULL + && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { + if (ret->group == NULL) + /* no parameter-less keys allowed */ + goto err; + ret->priv_key = BN_new(); + if (ret->priv_key == NULL || !BN_copy(ret->priv_key, src->priv_key)) + goto err; + if (ret->group->meth->keycopy + && ret->group->meth->keycopy(ret, src) == 0) + goto err; + } + + /* copy the rest */ + if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) { + ret->enc_flag = src->enc_flag; + ret->conv_form = src->conv_form; + } + + ret->version = src->version; + ret->flags = src->flags; + +#ifndef FIPS_MODULE + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, + &ret->ex_data, &src->ex_data)) + goto err; +#endif + + if (ret->meth != NULL && ret->meth->copy != NULL) { + if ((selection + & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR) + goto err; + if (ret->meth->copy(ret, src) == 0) + goto err; + } + + return ret; + err: + EC_KEY_free(ret); + return NULL; +} + +int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) { + int i = ossl_ec_encoding_name2id(name); + + if (i >= 0) { + *id = i; + return 1; + } + } + return 0; +} + +int ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id) +{ + const char *name = NULL; + int status = 0; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + name = p->data; + status = (name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + status = OSSL_PARAM_get_utf8_ptr(p, &name); + break; + } + if (status) { + int i = ossl_ec_pt_format_name2id(name); + + if (i >= 0) { + *id = i; + return 1; + } + } + return 0; +} + +#ifndef FIPS_MODULE +int ossl_x509_algor_is_sm2(const X509_ALGOR *palg) +{ + int ptype = 0; + const void *pval = NULL; + + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if (ptype == V_ASN1_OBJECT) + return OBJ_obj2nid((ASN1_OBJECT *)pval) == NID_sm2; + + if (ptype == V_ASN1_SEQUENCE) { + const ASN1_STRING *str = pval; + const unsigned char *der = str->data; + int derlen = str->length; + EC_GROUP *group; + int ret; + + if ((group = d2i_ECPKParameters(NULL, &der, derlen)) == NULL) + ret = 0; + else + ret = (EC_GROUP_get_curve_name(group) == NID_sm2); + + EC_GROUP_free(group); + return ret; + } + + return 0; +} + +EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg, + OSSL_LIB_CTX *libctx, const char *propq) +{ + int ptype = 0; + const void *pval = NULL; + EC_KEY *eckey = NULL; + EC_GROUP *group = NULL; + + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto ecerr; + } + + if (ptype == V_ASN1_SEQUENCE) { + const ASN1_STRING *pstr = pval; + const unsigned char *pm = pstr->data; + int pmlen = pstr->length; + + + if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); + goto ecerr; + } + } else if (ptype == V_ASN1_OBJECT) { + const ASN1_OBJECT *poid = pval; + + /* + * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID + */ + + group = EC_GROUP_new_by_curve_name_ex(libctx, propq, OBJ_obj2nid(poid)); + if (group == NULL) + goto ecerr; + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(eckey, group) == 0) + goto ecerr; + EC_GROUP_free(group); + } else { + ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); + goto ecerr; + } + + return eckey; + + ecerr: + EC_KEY_free(eckey); + EC_GROUP_free(group); + return NULL; +} + +EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const unsigned char *p = NULL; + int pklen; + EC_KEY *eckey = NULL; + const X509_ALGOR *palg; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf)) + return 0; + eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq); + if (eckey == NULL) + goto err; + + /* We have parameters now set private key */ + if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { + ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); + goto err; + } + + return eckey; + err: + EC_KEY_free(eckey); + return NULL; +} +#endif diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c index d0706d2857e6..484124915dc6 100644 --- a/crypto/ec/ec_check.c +++ b/crypto/ec/ec_check.c @@ -1,22 +1,67 @@ /* - * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include "ec_local.h" #include <openssl/err.h> +int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only, + BN_CTX *ctx) +{ + int nid; + BN_CTX *new_ctx = NULL; + + if (group == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return NID_undef; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new_ex(NULL); + if (ctx == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return NID_undef; + } + } + + nid = ossl_ec_curve_nid_from_params(group, ctx); + if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL) + nid = NID_undef; + + BN_CTX_free(new_ctx); + return nid; +} + int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) { +#ifdef FIPS_MODULE + /* + * ECC domain parameter validation. + * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b. + */ + return EC_GROUP_check_named_curve(group, 1, ctx) >= 0 ? 1 : 0; +#else int ret = 0; const BIGNUM *order; BN_CTX *new_ctx = NULL; EC_POINT *point = NULL; + if (group == NULL || group->meth == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + /* Custom curves assumed to be correct */ if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0) return 1; @@ -24,24 +69,24 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { - ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } /* check the discriminant */ if (!EC_GROUP_check_discriminant(group, ctx)) { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); + ERR_raise(ERR_LIB_EC, EC_R_DISCRIMINANT_IS_ZERO); goto err; } /* check the generator */ if (group->generator == NULL) { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); goto err; } if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE); + ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE); goto err; } @@ -52,14 +97,14 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) if (order == NULL) goto err; if (BN_is_zero(order)) { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_ORDER); goto err; } if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err; if (!EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); goto err; } @@ -69,4 +114,5 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) BN_CTX_free(new_ctx); EC_POINT_free(point); return ret; +#endif /* FIPS_MODULE */ } diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c index b4c14e91e175..b5b2f3342dfb 100644 --- a/crypto/ec/ec_curve.c +++ b/crypto/ec/ec_curve.c @@ -2,12 +2,18 @@ * Copyright 2002-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include "ec_local.h" #include <openssl/err.h> @@ -194,6 +200,7 @@ static const struct { } }; +# ifndef FIPS_MODULE /* the x9.62 prime curves (minus the nist prime curves) */ static const struct { EC_CURVE_DATA h; @@ -372,6 +379,7 @@ static const struct { 0x43, 0x21, 0x46, 0x52, 0x65, 0x51 } }; +#endif /* FIPS_MODULE */ static const struct { EC_CURVE_DATA h; @@ -411,6 +419,7 @@ static const struct { } }; +#ifndef FIPS_MODULE /* the secg prime curves (minus the nist and x9.62 prime curves) */ static const struct { EC_CURVE_DATA h; @@ -832,10 +841,13 @@ static const struct { 0x5C, 0x5C, 0x2A, 0x3D } }; +#endif /* FIPS_MODULE */ #ifndef OPENSSL_NO_EC2M /* characteristic two curves */ + +# ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[20 + 15 * 6]; @@ -963,6 +975,7 @@ static const struct { 0x33, 0x04, 0x9B, 0xA9, 0x8F } }; +# endif /* FIPS_MODULE */ static const struct { EC_CURVE_DATA h; @@ -994,6 +1007,7 @@ static const struct { } }; +# ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[0 + 21 * 6]; @@ -1022,6 +1036,7 @@ static const struct { 0xAA, 0xB6, 0x89, 0xC2, 0x9C, 0xA7, 0x10, 0x27, 0x9B } }; +# endif /* FIPS_MODULE */ static const struct { EC_CURVE_DATA h; @@ -1052,6 +1067,7 @@ static const struct { } }; +# ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[20 + 25 * 6]; @@ -1127,6 +1143,7 @@ static const struct { 0xD5 } }; +# endif /* FIPS_MODULE */ static const struct { EC_CURVE_DATA h; @@ -1137,6 +1154,7 @@ static const struct { }, { /* no seed */ + /* p */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, @@ -1201,6 +1219,7 @@ static const struct { } }; +#ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[0 + 30 * 6]; @@ -1210,6 +1229,7 @@ static const struct { }, { /* no seed */ + /* p */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, @@ -1235,6 +1255,7 @@ static const struct { 0x1D, 0xA8, 0x00, 0xE4, 0x78, 0xA5 } }; +# endif /* FIPS_MODULE */ static const struct { EC_CURVE_DATA h; @@ -1245,6 +1266,7 @@ static const struct { }, { /* no seed */ + /* p */ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, @@ -1279,7 +1301,7 @@ static const struct { NID_X9_62_characteristic_two_field, 20, 36, 2 }, { - /* no seed */ + /* seed */ 0x77, 0xE2, 0xB0, 0x73, 0x70, 0xEB, 0x0F, 0x83, 0x2A, 0x6D, 0xD5, 0xB6, 0x2D, 0xFC, 0x88, 0xCD, 0x06, 0xBB, 0x84, 0xBE, /* p */ @@ -1517,6 +1539,7 @@ static const struct { } }; +# ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[20 + 21 * 6]; @@ -2201,8 +2224,8 @@ static const struct { 0xED, 0xF9, 0x7C, 0x44, 0xDB, 0x9F, 0x24, 0x20, 0xBA, 0xFC, 0xA7, 0x5E } }; - -#endif +# endif /* FIPS_MODULE */ +#endif /* OPENSSL_NO_EC2M */ /* * These curves were added by Annie Yousar. @@ -2212,6 +2235,7 @@ static const struct { * generation mechanism is different from those defined in ANSI X9.62. */ +#ifndef FIPS_MODULE static const struct { EC_CURVE_DATA h; unsigned char data[0 + 20 * 6]; @@ -2751,8 +2775,9 @@ static const struct { 0x9C, 0xA9, 0x00, 0x69 } }; +#endif /* FIPS_MODULE */ -#ifndef OPENSSL_NO_SM2 +#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE) static const struct { EC_CURVE_DATA h; unsigned char data[0 + 32 * 6]; @@ -2798,6 +2823,79 @@ typedef struct _ec_list_element_st { const char *comment; } ec_list_element; +#ifdef FIPS_MODULE +static const ec_list_element curve_list[] = { + /* prime field curves */ + /* secg curves */ + {NID_secp224r1, &_EC_NIST_PRIME_224.h, +# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp224_method, +# else + 0, +# endif + "NIST/SECG curve over a 224 bit prime field"}, + /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ + {NID_secp384r1, &_EC_NIST_PRIME_384.h, +# if defined(S390X_EC_ASM) + EC_GFp_s390x_nistp384_method, +# else + 0, +# endif + "NIST/SECG curve over a 384 bit prime field"}, + + {NID_secp521r1, &_EC_NIST_PRIME_521.h, +# if defined(S390X_EC_ASM) + EC_GFp_s390x_nistp521_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp521_method, +# else + 0, +# endif + "NIST/SECG curve over a 521 bit prime field"}, + + /* X9.62 curves */ + {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, + "NIST/X9.62/SECG curve over a 192 bit prime field"}, + {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, +# if defined(ECP_NISTZ256_ASM) + EC_GFp_nistz256_method, +# elif defined(S390X_EC_ASM) + EC_GFp_s390x_nistp256_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp256_method, +# else + 0, +# endif + "X9.62/SECG curve over a 256 bit prime field"}, + +# ifndef OPENSSL_NO_EC2M + /* characteristic two field curves */ + /* NIST/SECG curves */ + {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, + "NIST/SECG/WTLS curve over a 163 bit binary field"}, + {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, + "NIST/SECG curve over a 163 bit binary field"}, + {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, + {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, +# endif +}; + +#else + static const ec_list_element curve_list[] = { /* prime field curves */ /* secg curves */ @@ -2820,25 +2918,32 @@ static const ec_list_element curve_list[] = { "SECG curve over a 192 bit prime field"}, {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field"}, -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field"}, -#else +# else {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field"}, -#endif +# endif {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field"}, /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ - {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, + {NID_secp384r1, &_EC_NIST_PRIME_384.h, +# if defined(S390X_EC_ASM) + EC_GFp_s390x_nistp384_method, +# else + 0, +# endif "NIST/SECG curve over a 384 bit prime field"}, -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, - "NIST/SECG curve over a 521 bit prime field"}, -#else - {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, + {NID_secp521r1, &_EC_NIST_PRIME_521.h, +# if defined(S390X_EC_ASM) + EC_GFp_s390x_nistp521_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + EC_GFp_nistp521_method, +# else + 0, +# endif "NIST/SECG curve over a 521 bit prime field"}, -#endif /* X9.62 curves */ {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field"}, @@ -2853,15 +2958,17 @@ static const ec_list_element curve_list[] = { {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field"}, {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, -#if defined(ECP_NISTZ256_ASM) +# if defined(ECP_NISTZ256_ASM) EC_GFp_nistz256_method, -#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) +# elif defined(S390X_EC_ASM) + EC_GFp_s390x_nistp256_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) EC_GFp_nistp256_method, -#else +# else 0, -#endif +# endif "X9.62/SECG curve over a 256 bit prime field"}, -#ifndef OPENSSL_NO_EC2M +# ifndef OPENSSL_NO_EC2M /* characteristic two field curves */ /* NIST/SECG curves */ {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, @@ -2945,7 +3052,7 @@ static const ec_list_element curve_list[] = { "SECG curve over a 113 bit binary field"}, {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field"}, -#endif +# endif {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field"}, {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, @@ -2954,15 +3061,15 @@ static const ec_list_element curve_list[] = { "WTLS curve over a 112 bit prime field"}, {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field"}, -#ifndef OPENSSL_NO_EC2M +# ifndef OPENSSL_NO_EC2M {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field"}, -#endif +# endif {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curve over a 224 bit prime field"}, -#ifndef OPENSSL_NO_EC2M +# ifndef OPENSSL_NO_EC2M /* IPSec curves */ {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" @@ -2970,7 +3077,7 @@ static const ec_list_element curve_list[] = { {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, -#endif +# endif /* brainpool curves */ {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0, "RFC 5639 curve over a 160 bit prime field"}, @@ -3000,15 +3107,32 @@ static const ec_list_element curve_list[] = { "RFC 5639 curve over a 512 bit prime field"}, {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, "RFC 5639 curve over a 512 bit prime field"}, -#ifndef OPENSSL_NO_SM2 +# ifndef OPENSSL_NO_SM2 {NID_sm2, &_EC_sm2p256v1.h, 0, "SM2 curve over a 256 bit prime field"}, -#endif +# endif }; +#endif /* FIPS_MODULE */ #define curve_list_length OSSL_NELEM(curve_list) -static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) +static const ec_list_element *ec_curve_nid2curve(int nid) +{ + size_t i; + + if (nid <= 0) + return NULL; + + for (i = 0; i < curve_list_length; i++) { + if (curve_list[i].nid == nid) + return &curve_list[i]; + } + return NULL; +} + +static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx, + const char *propq, + const ec_list_element curve) { EC_GROUP *group = NULL; EC_POINT *P = NULL; @@ -3023,10 +3147,11 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) /* If no curve data curve method must handle everything */ if (curve.data == NULL) - return EC_GROUP_new(curve.meth != NULL ? curve.meth() : NULL); + return ossl_ec_group_new_ex(libctx, propq, + curve.meth != NULL ? curve.meth() : NULL); - if ((ctx = BN_CTX_new()) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); + if ((ctx = BN_CTX_new_ex(libctx)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -3039,20 +3164,20 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (curve.meth != 0) { meth = curve.meth(); - if (((group = EC_GROUP_new(meth)) == NULL) || + if (((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) || (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } else if (data->field_type == NID_X9_62_prime_field) { if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } @@ -3061,7 +3186,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) * NID_X9_62_characteristic_two_field */ if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } @@ -3070,35 +3195,36 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) EC_GROUP_set_curve_name(group, curve.nid); if ((P = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL || !BN_set_word(x, (BN_ULONG)data->cofactor)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_set_generator(group, P, order, x)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (seed_len) { if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } +#ifndef FIPS_MODULE if (EC_GROUP_get_asn1_flag(group) == OPENSSL_EC_NAMED_CURVE) { /* * Some curves don't have an associated OID: for those we should not @@ -3115,7 +3241,7 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) ASN1_OBJECT *asn1obj = OBJ_nid2obj(curve.nid); if (asn1obj == NULL) { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_OBJ_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_OBJ_LIB); goto err; } if (OBJ_length(asn1obj) == 0) @@ -3123,6 +3249,16 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) ASN1_OBJECT_free(asn1obj); } +#else + /* + * Inside the FIPS module we do not support explicit curves anyway + * so the above check is not necessary. + * + * Skipping it is also necessary because `OBJ_length()` and + * `ASN1_OBJECT_free()` are not available within the FIPS module + * boundaries. + */ +#endif ok = 1; err: @@ -3141,28 +3277,33 @@ static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) return group; } -EC_GROUP *EC_GROUP_new_by_curve_name(int nid) +EC_GROUP *EC_GROUP_new_by_curve_name_ex(OSSL_LIB_CTX *libctx, const char *propq, + int nid) { - size_t i; EC_GROUP *ret = NULL; + const ec_list_element *curve; - if (nid <= 0) - return NULL; - - for (i = 0; i < curve_list_length; i++) - if (curve_list[i].nid == nid) { - ret = ec_group_new_from_data(curve_list[i]); - break; - } - - if (ret == NULL) { - ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP); + if ((curve = ec_curve_nid2curve(nid)) == NULL + || (ret = ec_group_new_from_data(libctx, propq, *curve)) == NULL) { +#ifndef FIPS_MODULE + ERR_raise_data(ERR_LIB_EC, EC_R_UNKNOWN_GROUP, + "name=%s", OBJ_nid2sn(nid)); +#else + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_GROUP); +#endif return NULL; } return ret; } +#ifndef FIPS_MODULE +EC_GROUP *EC_GROUP_new_by_curve_name(int nid) +{ + return EC_GROUP_new_by_curve_name_ex(NULL, NULL, nid); +} +#endif + size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) { size_t i, min; @@ -3180,49 +3321,14 @@ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) return curve_list_length; } -/* Functions to translate between common NIST curve names and NIDs */ - -typedef struct { - const char *name; /* NIST Name of curve */ - int nid; /* Curve NID */ -} EC_NIST_NAME; - -static EC_NIST_NAME nist_curves[] = { - {"B-163", NID_sect163r2}, - {"B-233", NID_sect233r1}, - {"B-283", NID_sect283r1}, - {"B-409", NID_sect409r1}, - {"B-571", NID_sect571r1}, - {"K-163", NID_sect163k1}, - {"K-233", NID_sect233k1}, - {"K-283", NID_sect283k1}, - {"K-409", NID_sect409k1}, - {"K-571", NID_sect571k1}, - {"P-192", NID_X9_62_prime192v1}, - {"P-224", NID_secp224r1}, - {"P-256", NID_X9_62_prime256v1}, - {"P-384", NID_secp384r1}, - {"P-521", NID_secp521r1} -}; - const char *EC_curve_nid2nist(int nid) { - size_t i; - for (i = 0; i < OSSL_NELEM(nist_curves); i++) { - if (nist_curves[i].nid == nid) - return nist_curves[i].name; - } - return NULL; + return ossl_ec_curve_nid2nist_int(nid); } int EC_curve_nist2nid(const char *name) { - size_t i; - for (i = 0; i < OSSL_NELEM(nist_curves); i++) { - if (strcmp(nist_curves[i].name, name) == 0) - return nist_curves[i].nid; - } - return NID_undef; + return ossl_ec_curve_nist2nid_int(name); } #define NUM_BN_FIELDS 6 @@ -3234,7 +3340,7 @@ int EC_curve_nist2nid(const char *name) * Returns: The nid associated with the found named curve, or NID_undef * if not found. If there was an error it returns -1. */ -int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx) { int ret = -1, nid, len, field_type, param_len; size_t i, seed_len; @@ -3242,17 +3348,13 @@ int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx) unsigned char *param_bytes = NULL; const EC_CURVE_DATA *data; const EC_POINT *generator = NULL; - const EC_METHOD *meth; const BIGNUM *cofactor = NULL; /* An array of BIGNUMs for (p, a, b, x, y, order) */ BIGNUM *bn[NUM_BN_FIELDS] = {NULL, NULL, NULL, NULL, NULL, NULL}; - meth = EC_GROUP_method_of(group); - if (meth == NULL) - return -1; /* Use the optional named curve nid as a search field */ nid = EC_GROUP_get_curve_name(group); - field_type = EC_METHOD_get_field_type(meth); + field_type = EC_GROUP_get_field_type(group); seed_len = EC_GROUP_get_seed_len(group); seed = EC_GROUP_get0_seed(group); cofactor = EC_GROUP_get0_cofactor(group); diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c index 944e317d9d14..1145bfb68f90 100644 --- a/crypto/ec/ec_cvt.c +++ b/crypto/ec/ec_cvt.c @@ -1,14 +1,21 @@ /* - * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> +#include "crypto/bn.h" #include "ec_local.h" EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, @@ -47,12 +54,12 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, meth = EC_GFp_mont_method(); #endif - ret = EC_GROUP_new(meth); + ret = ossl_ec_group_new_ex(ossl_bn_get_libctx(ctx), NULL, meth); if (ret == NULL) return NULL; if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) { - EC_GROUP_clear_free(ret); + EC_GROUP_free(ret); return NULL; } @@ -68,12 +75,12 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, meth = EC_GF2m_simple_method(); - ret = EC_GROUP_new(meth); + ret = ossl_ec_group_new_ex(ossl_bn_get_libctx(ctx), NULL, meth); if (ret == NULL) return NULL; if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) { - EC_GROUP_clear_free(ret); + EC_GROUP_free(ret); return NULL; } diff --git a/crypto/ec/ec_deprecated.c b/crypto/ec/ec_deprecated.c new file mode 100644 index 000000000000..765894c32977 --- /dev/null +++ b/crypto/ec/ec_deprecated.c @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +/* + * Suppress deprecation warnings for EC low level implementations that are + * kept until removal. + */ +#define OPENSSL_SUPPRESS_DEPRECATED + +#include <openssl/crypto.h> +#include <openssl/err.h> +#include <openssl/ec.h> + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form, + BIGNUM *ret, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; + + buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx); + + if (buf_len == 0) + return NULL; + + ret = BN_bin2bn(buf, buf_len, ret); + + OPENSSL_free(buf); + + return ret; +} + +EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, + const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; + EC_POINT *ret; + + if ((buf_len = BN_num_bytes(bn)) == 0) + buf_len = 1; + if ((buf = OPENSSL_malloc(buf_len)) == NULL) { + ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (BN_bn2binpad(bn, buf, buf_len) < 0) { + OPENSSL_free(buf); + return NULL; + } + + if (point == NULL) { + if ((ret = EC_POINT_new(group)) == NULL) { + OPENSSL_free(buf); + return NULL; + } + } else + ret = point; + + if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) { + if (ret != point) + EC_POINT_clear_free(ret); + OPENSSL_free(buf); + return NULL; + } + + OPENSSL_free(buf); + return ret; +} +#endif /* OPENSSL_NO_DEPRECATED_3_0 */ diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index bfe74226503e..480376686b9e 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -10,283 +10,11 @@ #include <openssl/err.h> #include <openssl/ecerr.h> +#include "crypto/ecerr.h" -#ifndef OPENSSL_NO_ERR +#ifndef OPENSSL_NO_EC -static const ERR_STRING_DATA EC_str_functs[] = { - {ERR_PACK(ERR_LIB_EC, EC_F_BN_TO_FELEM, 0), "BN_to_felem"}, - {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPARAMETERS, 0), "d2i_ECParameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPKPARAMETERS, 0), "d2i_ECPKParameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_D2I_ECPRIVATEKEY, 0), "d2i_ECPrivateKey"}, - {ERR_PACK(ERR_LIB_EC, EC_F_DO_EC_KEY_PRINT, 0), "do_EC_KEY_print"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_DECRYPT, 0), "ecdh_cms_decrypt"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_CMS_SET_SHARED_INFO, 0), - "ecdh_cms_set_shared_info"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_COMPUTE_KEY, 0), "ECDH_compute_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDH_SIMPLE_COMPUTE_KEY, 0), - "ecdh_simple_compute_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_SIGN_EX, 0), "ECDSA_do_sign_ex"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_DO_VERIFY, 0), "ECDSA_do_verify"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_EX, 0), "ECDSA_sign_ex"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIGN_SETUP, 0), "ECDSA_sign_setup"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIG_NEW, 0), "ECDSA_SIG_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_VERIFY, 0), "ECDSA_verify"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECD_ITEM_VERIFY, 0), "ecd_item_verify"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM2TYPE, 0), "eckey_param2type"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PARAM_DECODE, 0), "eckey_param_decode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_DECODE, 0), "eckey_priv_decode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PRIV_ENCODE, 0), "eckey_priv_encode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_DECODE, 0), "eckey_pub_decode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_PUB_ENCODE, 0), "eckey_pub_encode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECKEY_TYPE2PARAM, 0), "eckey_type2param"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT, 0), "ECParameters_print"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECPARAMETERS_PRINT_FP, 0), - "ECParameters_print_fp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT, 0), - "ECPKParameters_print"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECPKPARAMETERS_PRINT_FP, 0), - "ECPKParameters_print_fp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_GET_AFFINE, 0), - "ecp_nistz256_get_affine"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_INV_MOD_ORD, 0), - "ecp_nistz256_inv_mod_ord"}, - {ERR_PACK(ERR_LIB_EC, EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, 0), - "ecp_nistz256_mult_precompute"}, - {ERR_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_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_FIELD_INV, 0), - "ec_GF2m_simple_field_inv"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0), - "ec_GF2m_simple_group_check_discriminant"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0), - "ec_GF2m_simple_group_set_curve"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_POST, 0), - "ec_GF2m_simple_ladder_post"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_PRE, 0), - "ec_GF2m_simple_ladder_pre"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_OCT2POINT, 0), - "ec_GF2m_simple_oct2point"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT2OCT, 0), - "ec_GF2m_simple_point2oct"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINTS_MUL, 0), - "ec_GF2m_simple_points_mul"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0), - "ec_GF2m_simple_point_get_affine_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0), - "ec_GF2m_simple_point_set_affine_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, 0), - "ec_GF2m_simple_set_compressed_coordinates"}, - {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_INV, 0), - "ec_GFp_mont_field_inv"}, - {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_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_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, 0), - "ec_GFp_nistp224_group_set_curve"}, - {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_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, 0), - "ec_GFp_nistp256_group_set_curve"}, - {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_PACK(ERR_LIB_EC, EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, 0), - "ec_GFp_nistp521_group_set_curve"}, - {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_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_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0), - "ec_GFp_simple_blind_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_FIELD_INV, 0), - "ec_GFp_simple_field_inv"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0), - "ec_GFp_simple_group_check_discriminant"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0), - "ec_GFp_simple_group_set_curve"}, - {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_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0), - "ec_GFp_simple_point_get_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_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, 0), - "ec_GFp_simple_set_compressed_coordinates"}, - {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_PACK(ERR_LIB_EC, EC_F_EC_GROUP_COPY, 0), "EC_GROUP_copy"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE, 0), "EC_GROUP_get_curve"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GF2M, 0), - "EC_GROUP_get_curve_GF2m"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_CURVE_GFP, 0), - "EC_GROUP_get_curve_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_DEGREE, 0), "EC_GROUP_get_degree"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPARAMETERS, 0), - "EC_GROUP_get_ecparameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_ECPKPARAMETERS, 0), - "EC_GROUP_get_ecpkparameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, 0), - "EC_GROUP_get_pentanomial_basis"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, 0), - "EC_GROUP_get_trinomial_basis"}, - {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_PACK(ERR_LIB_EC, EC_F_EC_GROUP_NEW_FROM_ECPKPARAMETERS, 0), - "EC_GROUP_new_from_ecpkparameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE, 0), "EC_GROUP_set_curve"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GF2M, 0), - "EC_GROUP_set_curve_GF2m"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_CURVE_GFP, 0), - "EC_GROUP_set_curve_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_GENERATOR, 0), - "EC_GROUP_set_generator"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_SET_SEED, 0), "EC_GROUP_set_seed"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_CHECK_KEY, 0), "EC_KEY_check_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_COPY, 0), "EC_KEY_copy"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_GENERATE_KEY, 0), "EC_KEY_generate_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW, 0), "EC_KEY_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_NEW_METHOD, 0), "EC_KEY_new_method"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_OCT2PRIV, 0), "EC_KEY_oct2priv"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT, 0), "EC_KEY_print"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRINT_FP, 0), "EC_KEY_print_fp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2BUF, 0), "EC_KEY_priv2buf"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_PRIV2OCT, 0), "EC_KEY_priv2oct"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 0), - "EC_KEY_set_public_key_affine_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_CHECK_KEY, 0), - "ec_key_simple_check_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_OCT2PRIV, 0), - "ec_key_simple_oct2priv"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_PRIV2OCT, 0), - "ec_key_simple_priv2oct"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_CHECK, 0), "ec_pkey_check"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0), - "EC_POINTs_make_affine"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MUL, 0), "EC_POINTs_mul"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_BN2POINT, 0), "EC_POINT_bn2point"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_CMP, 0), "EC_POINT_cmp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_COPY, 0), "EC_POINT_copy"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_DBL, 0), "EC_POINT_dbl"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES, 0), - "EC_POINT_get_affine_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 0), - "EC_POINT_get_affine_coordinates_GF2m"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 0), - "EC_POINT_get_affine_coordinates_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 0), - "EC_POINT_get_Jprojective_coordinates_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_INVERT, 0), "EC_POINT_invert"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_AT_INFINITY, 0), - "EC_POINT_is_at_infinity"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_IS_ON_CURVE, 0), - "EC_POINT_is_on_curve"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_MAKE_AFFINE, 0), - "EC_POINT_make_affine"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_NEW, 0), "EC_POINT_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_OCT2POINT, 0), "EC_POINT_oct2point"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2BUF, 0), "EC_POINT_point2buf"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_POINT2OCT, 0), "EC_POINT_point2oct"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES, 0), - "EC_POINT_set_affine_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 0), - "EC_POINT_set_affine_coordinates_GF2m"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 0), - "EC_POINT_set_affine_coordinates_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, 0), - "EC_POINT_set_compressed_coordinates"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 0), - "EC_POINT_set_compressed_coordinates_GF2m"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 0), - "EC_POINT_set_compressed_coordinates_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 0), - "EC_POINT_set_Jprojective_coordinates_GFp"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_TO_INFINITY, 0), - "EC_POINT_set_to_infinity"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_PRE_COMP_NEW, 0), "ec_pre_comp_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_SCALAR_MUL_LADDER, 0), - "ec_scalar_mul_ladder"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_MUL, 0), "ec_wNAF_mul"}, - {ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_PRECOMPUTE_MULT, 0), - "ec_wNAF_precompute_mult"}, - {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPARAMETERS, 0), "i2d_ECParameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPKPARAMETERS, 0), "i2d_ECPKParameters"}, - {ERR_PACK(ERR_LIB_EC, EC_F_I2D_ECPRIVATEKEY, 0), "i2d_ECPrivateKey"}, - {ERR_PACK(ERR_LIB_EC, EC_F_I2O_ECPUBLICKEY, 0), "i2o_ECPublicKey"}, - {ERR_PACK(ERR_LIB_EC, EC_F_NISTP224_PRE_COMP_NEW, 0), - "nistp224_pre_comp_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_NISTP256_PRE_COMP_NEW, 0), - "nistp256_pre_comp_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_NISTP521_PRE_COMP_NEW, 0), - "nistp521_pre_comp_new"}, - {ERR_PACK(ERR_LIB_EC, EC_F_O2I_ECPUBLICKEY, 0), "o2i_ECPublicKey"}, - {ERR_PACK(ERR_LIB_EC, EC_F_OLD_EC_PRIV_DECODE, 0), "old_ec_priv_decode"}, - {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDH_COMPUTE_KEY, 0), - "ossl_ecdh_compute_key"}, - {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_SIGN_SIG, 0), "ossl_ecdsa_sign_sig"}, - {ERR_PACK(ERR_LIB_EC, EC_F_OSSL_ECDSA_VERIFY_SIG, 0), - "ossl_ecdsa_verify_sig"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_CTRL, 0), "pkey_ecd_ctrl"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN, 0), "pkey_ecd_digestsign"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN25519, 0), - "pkey_ecd_digestsign25519"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECD_DIGESTSIGN448, 0), - "pkey_ecd_digestsign448"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_ECX_DERIVE, 0), "pkey_ecx_derive"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, 0), "pkey_ec_ctrl"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL_STR, 0), "pkey_ec_ctrl_str"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_DERIVE, 0), "pkey_ec_derive"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_INIT, 0), "pkey_ec_init"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KDF_DERIVE, 0), "pkey_ec_kdf_derive"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"}, - {ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"}, - {ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"}, - {0, NULL} -}; +# ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA EC_str_reasons[] = { {ERR_PACK(ERR_LIB_EC, 0, EC_R_ASN1_ERROR), "asn1 error"}, @@ -298,15 +26,19 @@ static const ERR_STRING_DATA EC_str_reasons[] = { "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_ECDSA), + "curve does not support ecdsa"}, {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_EXPLICIT_PARAMS_NOT_SUPPORTED), + "explicit params not supported"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_FAILED_MAKING_PUBLIC_KEY), + "failed making public key"}, {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), @@ -315,7 +47,10 @@ static const ERR_STRING_DATA EC_str_reasons[] = { "i2d ecpkparameters failure"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_A), "invalid a"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_ARGUMENT), "invalid argument"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_B), "invalid b"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_COFACTOR), "invalid cofactor"}, {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), @@ -326,14 +61,20 @@ static const ERR_STRING_DATA EC_str_reasons[] = { {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_GENERATOR), "invalid generator"}, {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_LENGTH), "invalid length"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_NAMED_GROUP_CONVERSION), + "invalid named group conversion"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_OUTPUT_LENGTH), "invalid output length"}, + {ERR_PACK(ERR_LIB_EC, 0, EC_R_INVALID_P), "invalid p"}, {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_SEED), "invalid seed"}, {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"}, @@ -356,8 +97,6 @@ static const ERR_STRING_DATA EC_str_reasons[] = { {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"}, @@ -369,6 +108,7 @@ static const ERR_STRING_DATA EC_str_reasons[] = { "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_TOO_MANY_RETRIES), "too many retries"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"}, {ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"}, @@ -381,15 +121,16 @@ static const ERR_STRING_DATA EC_str_reasons[] = { {0, NULL} }; -#endif +# endif -int ERR_load_EC_strings(void) +int ossl_err_load_EC_strings(void) { -#ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(EC_str_functs[0].error) == NULL) { - ERR_load_strings_const(EC_str_functs); +# ifndef OPENSSL_NO_ERR + if (ERR_reason_error_string(EC_str_reasons[0].error) == NULL) ERR_load_strings_const(EC_str_reasons); - } -#endif +# endif return 1; } +#else +NON_EMPTY_TRANSLATION_UNIT +#endif diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 63799002bc98..729d338b3379 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -2,31 +2,52 @@ * Copyright 2002-2022 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * EC_KEY low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include "internal/cryptlib.h" #include <string.h> #include "ec_local.h" #include "internal/refcount.h" #include <openssl/err.h> -#include <openssl/engine.h> +#ifndef FIPS_MODULE +# include <openssl/engine.h> +#endif +#include <openssl/self_test.h> +#include "prov/providercommon.h" #include "crypto/bn.h" +static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, + void *cbarg); + +#ifndef FIPS_MODULE EC_KEY *EC_KEY_new(void) { - return EC_KEY_new_method(NULL); + return ossl_ec_key_new_method_int(NULL, NULL, NULL); } +#endif -EC_KEY *EC_KEY_new_by_curve_name(int nid) +EC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq) { - EC_KEY *ret = EC_KEY_new(); + return ossl_ec_key_new_method_int(ctx, propq, NULL); +} + +EC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq, + int nid) +{ + EC_KEY *ret = EC_KEY_new_ex(ctx, propq); if (ret == NULL) return NULL; - ret->group = EC_GROUP_new_by_curve_name(nid); + ret->group = EC_GROUP_new_by_curve_name_ex(ctx, propq, nid); if (ret->group == NULL) { EC_KEY_free(ret); return NULL; @@ -39,6 +60,13 @@ EC_KEY *EC_KEY_new_by_curve_name(int nid) return ret; } +#ifndef FIPS_MODULE +EC_KEY *EC_KEY_new_by_curve_name(int nid) +{ + return EC_KEY_new_by_curve_name_ex(NULL, NULL, nid); +} +#endif + void EC_KEY_free(EC_KEY *r) { int i; @@ -55,18 +83,21 @@ void EC_KEY_free(EC_KEY *r) if (r->meth != NULL && r->meth->finish != NULL) r->meth->finish(r); -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) ENGINE_finish(r->engine); #endif if (r->group && r->group->meth->keyfinish) r->group->meth->keyfinish(r); +#ifndef FIPS_MODULE CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); +#endif CRYPTO_THREAD_lock_free(r->lock); EC_GROUP_free(r->group); EC_POINT_free(r->pub_key); BN_clear_free(r->priv_key); + OPENSSL_free(r->propq); OPENSSL_clear_free((void *)r, sizeof(EC_KEY)); } @@ -74,7 +105,7 @@ void EC_KEY_free(EC_KEY *r) EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { if (dest == NULL || src == NULL) { - ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (src->meth != dest->meth) { @@ -82,18 +113,19 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) dest->meth->finish(dest); if (dest->group && dest->group->meth->keyfinish) dest->group->meth->keyfinish(dest); -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) if (ENGINE_finish(dest->engine) == 0) return 0; dest->engine = NULL; #endif } + dest->libctx = src->libctx; /* copy the parameters */ if (src->group != NULL) { - const EC_METHOD *meth = EC_GROUP_method_of(src->group); /* clear the old group */ EC_GROUP_free(dest->group); - dest->group = EC_GROUP_new(meth); + dest->group = ossl_ec_group_new_ex(src->libctx, src->propq, + src->group->meth); if (dest->group == NULL) return NULL; if (!EC_GROUP_copy(dest->group, src->group)) @@ -129,12 +161,14 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) dest->conv_form = src->conv_form; dest->version = src->version; dest->flags = src->flags; +#ifndef FIPS_MODULE if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, &src->ex_data)) return NULL; +#endif if (src->meth != dest->meth) { -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) if (src->engine != NULL && ENGINE_init(src->engine) == 0) return NULL; dest->engine = src->engine; @@ -145,21 +179,14 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) return NULL; + dest->dirty_cnt++; + return dest; } EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) { - EC_KEY *ret = EC_KEY_new_method(ec_key->engine); - - if (ret == NULL) - return NULL; - - if (EC_KEY_copy(ret, ec_key) == NULL) { - EC_KEY_free(ret); - return NULL; - } - return ret; + return ossl_ec_key_dup(ec_key, OSSL_KEYMGMT_SELECT_ALL); } int EC_KEY_up_ref(EC_KEY *r) @@ -182,156 +209,389 @@ ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey) int EC_KEY_generate_key(EC_KEY *eckey) { if (eckey == NULL || eckey->group == NULL) { - ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if (eckey->meth->keygen != NULL) - return eckey->meth->keygen(eckey); - ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED); + if (eckey->meth->keygen != NULL) { + int ret; + + ret = eckey->meth->keygen(eckey); + if (ret == 1) + eckey->dirty_cnt++; + + return ret; + } + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return 0; } int ossl_ec_key_gen(EC_KEY *eckey) { - return eckey->group->meth->keygen(eckey); + int ret; + + ret = eckey->group->meth->keygen(eckey); + + if (ret == 1) + eckey->dirty_cnt++; + return ret; } -int ec_key_simple_generate_key(EC_KEY *eckey) +/* + * ECC Key generation. + * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" + * + * Params: + * libctx A context containing an optional self test callback. + * eckey An EC key object that contains domain params. The generated keypair + * is stored in this object. + * pairwise_test Set to non zero to perform a pairwise test. If the test + * fails then the keypair is not generated, + * Returns 1 if the keypair was generated or 0 otherwise. + */ +static int ec_generate_key(EC_KEY *eckey, int pairwise_test) { int ok = 0; - BN_CTX *ctx = NULL; BIGNUM *priv_key = NULL; - const BIGNUM *order = NULL; + const BIGNUM *tmp = NULL; + BIGNUM *order = NULL; EC_POINT *pub_key = NULL; + const EC_GROUP *group = eckey->group; + BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx); + int sm2 = EC_KEY_get_flags(eckey) & EC_FLAG_SM2_RANGE ? 1 : 0; - if ((ctx = BN_CTX_new()) == NULL) + if (ctx == NULL) goto err; if (eckey->priv_key == NULL) { - priv_key = BN_new(); + priv_key = BN_secure_new(); if (priv_key == NULL) goto err; } else priv_key = eckey->priv_key; - order = EC_GROUP_get0_order(eckey->group); - if (order == NULL) + /* + * Steps (1-2): Check domain parameters and security strength. + * These steps must be done by the user. This would need to be + * stated in the security policy. + */ + + tmp = EC_GROUP_get0_order(group); + if (tmp == NULL) goto err; + /* + * Steps (3-7): priv_key = DRBG_RAND(order_n_bits) (range [1, n-1]). + * Although this is slightly different from the standard, it is effectively + * equivalent as it gives an unbiased result ranging from 1..n-1. It is also + * faster as the standard needs to retry more often. Also doing + * 1 + rand[0..n-2] would effect the way that tests feed dummy entropy into + * rand so the simpler backward compatible method has been used here. + */ + + /* range of SM2 private key is [1, n-1) */ + if (sm2) { + order = BN_new(); + if (order == NULL || !BN_sub(order, tmp, BN_value_one())) + goto err; + } else { + order = BN_dup(tmp); + if (order == NULL) + goto err; + } + do - if (!BN_priv_rand_range(priv_key, order)) + if (!BN_priv_rand_range_ex(priv_key, order, 0, ctx)) goto err; while (BN_is_zero(priv_key)) ; if (eckey->pub_key == NULL) { - pub_key = EC_POINT_new(eckey->group); + pub_key = EC_POINT_new(group); if (pub_key == NULL) goto err; } else pub_key = eckey->pub_key; - if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) + /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */ + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) goto err; eckey->priv_key = priv_key; eckey->pub_key = pub_key; + priv_key = NULL; + pub_key = NULL; + + eckey->dirty_cnt++; + +#ifdef FIPS_MODULE + pairwise_test = 1; +#endif /* FIPS_MODULE */ ok = 1; + if (pairwise_test) { + OSSL_CALLBACK *cb = NULL; + void *cbarg = NULL; - err: - if (eckey->pub_key == NULL) - EC_POINT_free(pub_key); - if (eckey->priv_key != priv_key) - BN_free(priv_key); + OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg); + ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg); + } +err: + /* Step (9): If there is an error return an invalid keypair. */ + if (!ok) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); + BN_clear(eckey->priv_key); + if (eckey->pub_key != NULL) + EC_POINT_set_to_infinity(group, eckey->pub_key); + } + + EC_POINT_free(pub_key); + BN_clear_free(priv_key); BN_CTX_free(ctx); + BN_free(order); return ok; } -int ec_key_simple_generate_public_key(EC_KEY *eckey) +int ossl_ec_key_simple_generate_key(EC_KEY *eckey) { - return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, - NULL, NULL); + return ec_generate_key(eckey, 0); +} + +int ossl_ec_key_simple_generate_public_key(EC_KEY *eckey) +{ + int ret; + BN_CTX *ctx = BN_CTX_new_ex(eckey->libctx); + + if (ctx == NULL) + return 0; + + /* + * See SP800-56AR3 5.6.1.2.2: Step (8) + * pub_key = priv_key * G (where G is a point on the curve) + */ + ret = EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, + NULL, ctx); + + BN_CTX_free(ctx); + if (ret == 1) + eckey->dirty_cnt++; + + return ret; } int EC_KEY_check_key(const EC_KEY *eckey) { if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { - ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (eckey->group->meth->keycheck == NULL) { - ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return eckey->group->meth->keycheck(eckey); } -int ec_key_simple_check_key(const EC_KEY *eckey) +/* + * Check the range of the EC public key. + * See SP800-56A R3 Section 5.6.2.3.3 (Part 2) + * i.e. + * - If q = odd prime p: Verify that xQ and yQ are integers in the + * interval[0, p - 1], OR + * - If q = 2m: Verify that xQ and yQ are bit strings of length m bits. + * Returns 1 if the public key has a valid range, otherwise it returns 0. + */ +static int ec_key_public_range_check(BN_CTX *ctx, const EC_KEY *key) { - int ok = 0; - BN_CTX *ctx = NULL; - const BIGNUM *order = NULL; - EC_POINT *point = NULL; + int ret = 0; + BIGNUM *x, *y; + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates(key->group, key->pub_key, x, y, ctx)) + goto err; + + if (EC_GROUP_get_field_type(key->group) == NID_X9_62_prime_field) { + if (BN_is_negative(x) + || BN_cmp(x, key->group->field) >= 0 + || BN_is_negative(y) + || BN_cmp(y, key->group->field) >= 0) { + goto err; + } + } else { + int m = EC_GROUP_get_degree(key->group); + if (BN_num_bits(x) > m || BN_num_bits(y) > m) { + goto err; + } + } + ret = 1; +err: + BN_CTX_end(ctx); + return ret; +} + +/* + * ECC Partial Public-Key Validation as specified in SP800-56A R3 + * Section 5.6.2.3.4 ECC Partial Public-Key Validation Routine. + */ +int ossl_ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx) +{ if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } + /* 5.6.2.3.3 (Step 1): Q != infinity */ if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); - goto err; + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); + return 0; } - if ((ctx = BN_CTX_new()) == NULL) - goto err; - if ((point = EC_POINT_new(eckey->group)) == NULL) - goto err; + /* 5.6.2.3.3 (Step 2) Test if the public key is in range */ + if (!ec_key_public_range_check(ctx, eckey)) { + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); + return 0; + } - /* testing whether the pub_key is on the elliptic curve */ + /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */ if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); - goto err; + ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE); + return 0; } - /* testing whether pub_key * order is the point at infinity */ + return 1; +} + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.3.3 ECC Full Public-Key Validation Routine. + */ +int ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx) +{ + int ret = 0; + EC_POINT *point = NULL; + const BIGNUM *order = NULL; + + if (!ossl_ec_key_public_check_quick(eckey, ctx)) + return 0; + + point = EC_POINT_new(eckey->group); + if (point == NULL) + return 0; + order = eckey->group->order; if (BN_is_zero(order)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); goto err; } + /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */ if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!EC_POINT_is_at_infinity(eckey->group, point)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_WRONG_ORDER); goto err; } - /* - * in case the priv_key is present : check if generator * priv_key == - * pub_key - */ + ret = 1; +err: + EC_POINT_free(point); + return ret; +} + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity + * The private key is in the range [1, order-1] + */ +int ossl_ec_key_private_check(const EC_KEY *eckey) +{ + if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (BN_cmp(eckey->priv_key, BN_value_one()) < 0 + || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); + return 0; + } + return 1; +} + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b) + * Check if generator * priv_key = pub_key + */ +int ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx) +{ + int ret = 0; + EC_POINT *point = NULL; + + if (eckey == NULL + || eckey->group == NULL + || eckey->pub_key == NULL + || eckey->priv_key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + point = EC_POINT_new(eckey->group); + if (point == NULL) + goto err; + + + if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + ret = 1; +err: + EC_POINT_free(point); + return ret; +} + + +/* + * ECC Key validation as specified in SP800-56A R3. + * Section 5.6.2.3.3 ECC Full Public-Key Validation + * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity + * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency + * NOTES: + * Before calling this method in fips mode, there should be an assurance that + * an approved elliptic-curve group is used. + * Returns 1 if the key is valid, otherwise it returns 0. + */ +int ossl_ec_key_simple_check_key(const EC_KEY *eckey) +{ + int ok = 0; + BN_CTX *ctx = NULL; + + if (eckey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) + return 0; + + if (!ossl_ec_key_public_check(eckey, ctx)) + goto err; + if (eckey->priv_key != NULL) { - if (BN_cmp(eckey->priv_key, order) >= 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); - goto err; - } - if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, - NULL, NULL, ctx)) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); + if (!ossl_ec_key_private_check(eckey) + || !ossl_ec_key_pairwise_check(eckey, ctx)) goto err; - } - if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { - ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); - goto err; - } } ok = 1; - err: +err: BN_CTX_free(ctx); - EC_POINT_free(point); return ok; } @@ -344,11 +604,10 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, int ok = 0; if (key == NULL || key->group == NULL || x == NULL || y == NULL) { - ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, - ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(key->libctx); if (ctx == NULL) return 0; @@ -369,17 +628,15 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, goto err; /* - * Check if retrieved coordinates match originals and are less than field - * order: if not values are out of range. + * Check if retrieved coordinates match originals. The range check is done + * inside EC_KEY_check_key(). */ - if (BN_cmp(x, tx) || BN_cmp(y, ty) - || (BN_cmp(x, key->group->field) >= 0) - || (BN_cmp(y, key->group->field) >= 0)) { - ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, - EC_R_COORDINATES_OUT_OF_RANGE); + if (BN_cmp(x, tx) || BN_cmp(y, ty)) { + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } + /* EC_KEY_set_public_key updates dirty_cnt */ if (!EC_KEY_set_public_key(key, point)) goto err; @@ -396,6 +653,22 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, } +OSSL_LIB_CTX *ossl_ec_key_get_libctx(const EC_KEY *key) +{ + return key->libctx; +} + +const char *ossl_ec_key_get0_propq(const EC_KEY *key) +{ + return key->propq; +} + +void ossl_ec_key_set0_libctx(EC_KEY *key, OSSL_LIB_CTX *libctx) +{ + key->libctx = libctx; + /* Do we need to propagate this to the group? */ +} + const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; @@ -407,6 +680,10 @@ int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) return 0; EC_GROUP_free(key->group); key->group = EC_GROUP_dup(group); + if (key->group != NULL && EC_GROUP_get_curve_name(key->group) == NID_sm2) + EC_KEY_set_flags(key, EC_FLAG_SM2_RANGE); + + key->dirty_cnt++; return (key->group == NULL) ? 0 : 1; } @@ -505,6 +782,7 @@ int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) BN_clear_free(key->priv_key); key->priv_key = tmp_key; + key->dirty_cnt++; return 1; } @@ -521,6 +799,7 @@ int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) return 0; EC_POINT_free(key->pub_key); key->pub_key = EC_POINT_dup(pub_key, key->group); + key->dirty_cnt++; return (key->pub_key == NULL) ? 0 : 1; } @@ -552,12 +831,14 @@ void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) EC_GROUP_set_asn1_flag(key->group, flag); } +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) { if (key->group == NULL) return 0; return EC_GROUP_precompute_mult(key->group, ctx); } +#endif int EC_KEY_get_flags(const EC_KEY *key) { @@ -567,11 +848,13 @@ int EC_KEY_get_flags(const EC_KEY *key) void EC_KEY_set_flags(EC_KEY *key, int flags) { key->flags |= flags; + key->dirty_cnt++; } void EC_KEY_clear_flags(EC_KEY *key, int flags) { key->flags &= ~flags; + key->dirty_cnt++; } int EC_KEY_decoded_from_explicit_params(const EC_KEY *key) @@ -600,6 +883,7 @@ int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, return 0; if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0) return 0; + key->dirty_cnt++; /* * Save the point conversion form. * For non-custom curves the first octet of the buffer (excluding @@ -618,15 +902,15 @@ size_t EC_KEY_priv2oct(const EC_KEY *eckey, if (eckey->group == NULL || eckey->group->meth == NULL) return 0; if (eckey->group->meth->priv2oct == NULL) { - ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return eckey->group->meth->priv2oct(eckey, buf, len); } -size_t ec_key_simple_priv2oct(const EC_KEY *eckey, - unsigned char *buf, size_t len) +size_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey, + unsigned char *buf, size_t len) { size_t buf_len; @@ -641,7 +925,7 @@ size_t ec_key_simple_priv2oct(const EC_KEY *eckey, /* Octetstring may need leading zeros if BN is to short */ if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) { - ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } @@ -650,27 +934,34 @@ size_t ec_key_simple_priv2oct(const EC_KEY *eckey, int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) { + int ret; + if (eckey->group == NULL || eckey->group->meth == NULL) return 0; if (eckey->group->meth->oct2priv == NULL) { - ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } - return eckey->group->meth->oct2priv(eckey, buf, len); + ret = eckey->group->meth->oct2priv(eckey, buf, len); + if (ret == 1) + eckey->dirty_cnt++; + return ret; } -int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) +int ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, + size_t len) { if (eckey->priv_key == NULL) eckey->priv_key = BN_secure_new(); if (eckey->priv_key == NULL) { - ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) { - ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } + eckey->dirty_cnt++; return 1; } @@ -683,7 +974,7 @@ size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) if (len == 0) return 0; if ((buf = OPENSSL_malloc(len)) == NULL) { - ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } len = EC_KEY_priv2oct(eckey, buf, len); @@ -702,3 +993,45 @@ int EC_KEY_can_sign(const EC_KEY *eckey) return 0; return 1; } + +/* + * FIPS 140-2 IG 9.9 AS09.33 + * Perform a sign/verify operation. + * + * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9 + * states that no additional pairwise tests are required (apart from the tests + * specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are + * omitted here. + */ +static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, + void *cbarg) +{ + int ret = 0; + unsigned char dgst[16] = {0}; + int dgst_len = (int)sizeof(dgst); + ECDSA_SIG *sig = NULL; + OSSL_SELF_TEST *st = NULL; + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_PCT_ECDSA); + + sig = ECDSA_do_sign(dgst, dgst_len, eckey); + if (sig == NULL) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, dgst); + + if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1) + goto err; + + ret = 1; +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + ECDSA_SIG_free(sig); + return ret; +} diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c index 53a4a9295201..8c011635cb42 100644 --- a/crypto/ec/ec_kmeth.c +++ b/crypto/ec/ec_kmeth.c @@ -1,15 +1,23 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDH and ECDSA low level APIs are deprecated for public use, but still ok + * for internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include <openssl/ec.h> -#include <openssl/engine.h> +#ifndef FIPS_MODULE +# include <openssl/engine.h> +#endif #include <openssl/err.h> #include "ec_local.h" @@ -59,7 +67,7 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) if (finish != NULL) finish(key); -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) ENGINE_finish(key->engine); key->engine = NULL; #endif @@ -70,28 +78,37 @@ int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) return 1; } -EC_KEY *EC_KEY_new_method(ENGINE *engine) +EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq, + ENGINE *engine) { EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; + if (propq != NULL) { + ret->propq = OPENSSL_strdup(propq); + if (ret->propq == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } + ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE); - OPENSSL_free(ret); - return NULL; + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; } ret->meth = EC_KEY_get_default_method(); -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) if (engine != NULL) { if (!ENGINE_init(engine)) { - ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ENGINE_LIB); goto err; } ret->engine = engine; @@ -100,7 +117,7 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine) if (ret->engine != NULL) { ret->meth = ENGINE_get_EC(ret->engine); if (ret->meth == NULL) { - ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ENGINE_LIB); goto err; } } @@ -109,12 +126,15 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine) ret->version = 1; ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; +/* No ex_data inside the FIPS provider */ +#ifndef FIPS_MODULE if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { goto err; } +#endif if (ret->meth->init != NULL && ret->meth->init(ret) == 0) { - ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL); + ERR_raise(ERR_LIB_EC, ERR_R_INIT_FAIL); goto err; } return ret; @@ -124,6 +144,13 @@ EC_KEY *EC_KEY_new_method(ENGINE *engine) return NULL; } +#ifndef FIPS_MODULE +EC_KEY *EC_KEY_new_method(ENGINE *engine) +{ + return ossl_ec_key_new_method_int(NULL, NULL, engine); +} +#endif + int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *eckey, void *(*KDF) (const void *in, size_t inlen, void *out, @@ -132,11 +159,11 @@ int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, unsigned char *sec = NULL; size_t seclen; if (eckey->meth->compute_key == NULL) { - ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return 0; } if (outlen > INT_MAX) { - ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_OUTPUT_LENGTH); return 0; } if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey)) diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 08db89fceeb5..a082876fb479 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -1,41 +1,59 @@ /* - * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 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 + * Licensed under the Apache License 2.0 (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 */ -#include <string.h> +/* + * EC_GROUP low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" +#include <string.h> +#include <openssl/params.h> +#include <openssl/core_names.h> #include <openssl/err.h> #include <openssl/opensslv.h> - +#include "crypto/ec.h" +#include "crypto/bn.h" +#include "internal/nelem.h" #include "ec_local.h" /* functions for EC_GROUP objects */ -EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) +EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq, + const EC_METHOD *meth) { EC_GROUP *ret; if (meth == NULL) { - ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); + ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL); return NULL; } if (meth->group_init == 0) { - ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return NULL; } ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } + ret->libctx = libctx; + if (propq != NULL) { + ret->propq = OPENSSL_strdup(propq); + if (ret->propq == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + } ret->meth = meth; if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { ret->order = BN_new(); @@ -45,7 +63,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) if (ret->cofactor == NULL) goto err; } - ret->asn1_flag = OPENSSL_EC_NAMED_CURVE; + ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE; ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; if (!meth->group_init(ret)) goto err; @@ -54,10 +72,20 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) err: BN_free(ret->order); BN_free(ret->cofactor); + OPENSSL_free(ret->propq); OPENSSL_free(ret); return NULL; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# ifndef FIPS_MODULE +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) +{ + return ossl_ec_group_new_ex(NULL, NULL, meth); +} +# endif +#endif + void EC_pre_comp_free(EC_GROUP *group) { switch (group->pre_comp_type) { @@ -105,9 +133,11 @@ void EC_GROUP_free(EC_GROUP *group) BN_free(group->order); BN_free(group->cofactor); OPENSSL_free(group->seed); + OPENSSL_free(group->propq); OPENSSL_free(group); } +#ifndef OPENSSL_NO_DEPRECATED_3_0 void EC_GROUP_clear_free(EC_GROUP *group) { if (!group) @@ -126,20 +156,22 @@ void EC_GROUP_clear_free(EC_GROUP *group) OPENSSL_clear_free(group->seed, group->seed_len); OPENSSL_clear_free(group, sizeof(*group)); } +#endif int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) { if (dest->meth->group_copy == 0) { - ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (dest->meth != src->meth) { - ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (dest == src) return 1; + dest->libctx = src->libctx; dest->curve_name = src->curve_name; /* Copy precomputed */ @@ -216,7 +248,7 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) if (src->seed) { OPENSSL_free(dest->seed); if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) { - ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } if (!memcpy(dest->seed, src->seed, src->seed_len)) @@ -239,7 +271,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) if (a == NULL) return NULL; - if ((t = EC_GROUP_new(a->meth)) == NULL) + if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL) return NULL; if (!EC_GROUP_copy(t, a)) goto err; @@ -254,6 +286,7 @@ EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) return t; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) { return group->meth; @@ -263,6 +296,7 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth) { return meth->field_type; } +#endif static int ec_precompute_mont_data(EC_GROUP *); @@ -295,7 +329,7 @@ static int ec_guess_cofactor(EC_GROUP *group) { return 1; } - if ((ctx = BN_CTX_new()) == NULL) + if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL) return 0; BN_CTX_start(ctx); @@ -331,14 +365,14 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) { if (generator == NULL) { - ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } /* require group->field >= 1 */ if (group->field == NULL || BN_is_zero(group->field) || BN_is_negative(group->field)) { - ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); return 0; } @@ -349,7 +383,7 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, */ if (order == NULL || BN_is_zero(order) || BN_is_negative(order) || BN_num_bits(order) > BN_num_bits(group->field) + 1) { - ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); return 0; } @@ -359,7 +393,7 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, * So accept cofactor == NULL or cofactor >= 0. */ if (cofactor != NULL && BN_is_negative(cofactor)) { - ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR); + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR); return 0; } @@ -447,6 +481,10 @@ const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group) void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) { group->curve_name = nid; + group->asn1_flag = + (nid != NID_undef) + ? OPENSSL_EC_NAMED_CURVE + : OPENSSL_EC_EXPLICIT_CURVE; } int EC_GROUP_get_curve_name(const EC_GROUP *group) @@ -454,6 +492,16 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group) return group->curve_name; } +const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group) +{ + return group->field; +} + +int EC_GROUP_get_field_type(const EC_GROUP *group) +{ + return group->meth->field_type; +} + void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) { group->asn1_flag = flag; @@ -486,7 +534,7 @@ size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) return 1; if ((group->seed = OPENSSL_malloc(len)) == NULL) { - ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } memcpy(group->seed, p, len); @@ -509,7 +557,7 @@ int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { if (group->meth->group_set_curve == 0) { - ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return group->meth->group_set_curve(group, p, a, b, ctx); @@ -519,13 +567,13 @@ int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { if (group->meth->group_get_curve == NULL) { - ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return group->meth->group_get_curve(group, p, a, b, ctx); } -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { @@ -556,7 +604,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, int EC_GROUP_get_degree(const EC_GROUP *group) { if (group->meth->group_get_degree == 0) { - ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return group->meth->group_get_degree(group); @@ -565,8 +613,7 @@ int EC_GROUP_get_degree(const EC_GROUP *group) int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) { if (group->meth->group_check_discriminant == 0) { - ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } return group->meth->group_check_discriminant(group, ctx); @@ -576,11 +623,12 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) { int r = 0; BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; +#ifndef FIPS_MODULE BN_CTX *ctx_new = NULL; +#endif /* compare the field types */ - if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != - EC_METHOD_get_field_type(EC_GROUP_method_of(b))) + if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b)) return 1; /* compare the curve name (if present in both) */ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && @@ -589,8 +637,10 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE) return 0; +#ifndef FIPS_MODULE if (ctx == NULL) ctx_new = ctx = BN_CTX_new(); +#endif if (ctx == NULL) return -1; @@ -603,7 +653,9 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) b3 = BN_CTX_get(ctx); if (b3 == NULL) { BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(ctx_new); +#endif return -1; } @@ -615,33 +667,47 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) !b->meth->group_get_curve(b, b1, b2, b3, ctx)) r = 1; - if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) + /* return 1 if the curve parameters are different */ + if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0) r = 1; /* XXX EC_POINT_cmp() assumes that the methods are equal */ + /* return 1 if the generators are different */ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), - EC_GROUP_get0_generator(b), ctx)) + EC_GROUP_get0_generator(b), ctx) != 0) r = 1; if (!r) { const BIGNUM *ao, *bo, *ac, *bc; - /* compare the order and cofactor */ + /* compare the orders */ ao = EC_GROUP_get0_order(a); bo = EC_GROUP_get0_order(b); - ac = EC_GROUP_get0_cofactor(a); - bc = EC_GROUP_get0_cofactor(b); if (ao == NULL || bo == NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx_new); - return -1; + /* return an error if either order is NULL */ + r = -1; + goto end; } - if (BN_cmp(ao, bo) || BN_cmp(ac, bc)) + if (BN_cmp(ao, bo) != 0) { + /* return 1 if orders are different */ r = 1; + goto end; + } + /* + * It gets here if the curve parameters and generator matched. + * Now check the optional cofactors (if both are present). + */ + ac = EC_GROUP_get0_cofactor(a); + bc = EC_GROUP_get0_cofactor(b); + /* Returns 1 (mismatch) if both cofactors are specified and different */ + if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0) + r = 1; + /* Returns 0 if the parameters matched */ } - +end: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(ctx_new); - +#endif return r; } @@ -652,17 +718,17 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group) EC_POINT *ret; if (group == NULL) { - ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (group->meth->point_init == NULL) { - ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return NULL; } ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } @@ -679,7 +745,7 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group) void EC_POINT_free(EC_POINT *point) { - if (!point) + if (point == NULL) return; if (point->meth->point_finish != 0) @@ -689,7 +755,7 @@ void EC_POINT_free(EC_POINT *point) void EC_POINT_clear_free(EC_POINT *point) { - if (!point) + if (point == NULL) return; if (point->meth->point_clear_finish != 0) @@ -702,14 +768,14 @@ void EC_POINT_clear_free(EC_POINT *point) int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { if (dest->meth->point_copy == 0) { - ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (dest->meth != src->meth || (dest->curve_name != src->curve_name - && dest->curve_name != 0 - && src->curve_name != 0)) { - ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); + && dest->curve_name != 0 + && src->curve_name != 0)) { + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (dest == src) @@ -736,42 +802,42 @@ EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) return t; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) { return point->meth; } +#endif int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) { if (group->meth->point_set_to_infinity == 0) { - ECerr(EC_F_EC_POINT_SET_TO_INFINITY, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (group->meth != point->meth) { - ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->point_set_to_infinity(group, point); } +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) { - if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { - ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + if (group->meth->field_type != NID_X9_62_prime_field) { + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, - EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } - return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, - y, z, ctx); + return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, + x, y, z, ctx); } int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, @@ -779,44 +845,42 @@ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) { - if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { - ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + if (group->meth->field_type != NID_X9_62_prime_field) { + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, - EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } - return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, - y, z, ctx); + return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point, + x, y, z, ctx); } +#endif int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { if (group->meth->point_set_affine_coordinates == NULL) { - ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) return 0; if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { - ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE); + ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE); return 0; } return 1; } -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) @@ -839,22 +903,21 @@ int EC_POINT_get_affine_coordinates(const EC_GROUP *group, BN_CTX *ctx) { if (group->meth->point_get_affine_coordinates == NULL) { - ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); } -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) @@ -876,12 +939,12 @@ int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { if (group->meth->add == 0) { - ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) { - ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->add(group, r, a, b, ctx); @@ -891,11 +954,11 @@ int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) { if (group->meth->dbl == 0) { - ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) { - ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->dbl(group, r, a, ctx); @@ -904,11 +967,11 @@ int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { if (group->meth->invert == 0) { - ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(a, group)) { - ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->invert(group, a, ctx); @@ -917,12 +980,11 @@ int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { if (group->meth->is_at_infinity == 0) { - ECerr(EC_F_EC_POINT_IS_AT_INFINITY, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->is_at_infinity(group, point); @@ -939,11 +1001,11 @@ int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) { if (group->meth->is_on_curve == 0) { - ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->is_on_curve(group, point, ctx); @@ -953,24 +1015,25 @@ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { if (group->meth->point_cmp == 0) { - ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) { - ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return -1; } return group->meth->point_cmp(group, a, b, ctx); } +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { if (group->meth->make_affine == 0) { - ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } return group->meth->make_affine(group, point, ctx); @@ -982,17 +1045,18 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, size_t i; if (group->meth->points_make_affine == 0) { - ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } for (i = 0; i < num; i++) { if (!ec_point_is_compat(points[i], group)) { - ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } } return group->meth->points_make_affine(group, num, points, ctx); } +#endif /* * Functions for point multiplication. If group->meth->mul is 0, we use the @@ -1000,16 +1064,19 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, * methods. */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) { int ret = 0; size_t i = 0; +#ifndef FIPS_MODULE BN_CTX *new_ctx = NULL; +#endif if (!ec_point_is_compat(r, group)) { - ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } @@ -1018,13 +1085,17 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, for (i = 0; i < num; i++) { if (!ec_point_is_compat(points[i], group)) { - ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } } - if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) { - ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR); +#ifndef FIPS_MODULE + if (ctx == NULL) + ctx = new_ctx = BN_CTX_secure_new(); +#endif + if (ctx == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); return 0; } @@ -1032,33 +1103,61 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx); else /* use default */ - ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } +#endif int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) { - /* just a convenient interface to EC_POINTs_mul() */ + int ret = 0; + size_t num; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif + + if (!ec_point_is_compat(r, group) + || (point != NULL && !ec_point_is_compat(point, group))) { + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } - const EC_POINT *points[1]; - const BIGNUM *scalars[1]; + if (g_scalar == NULL && p_scalar == NULL) + return EC_POINT_set_to_infinity(group, r); - points[0] = point; - scalars[0] = p_scalar; +#ifndef FIPS_MODULE + if (ctx == NULL) + ctx = new_ctx = BN_CTX_secure_new(); +#endif + if (ctx == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); + return 0; + } + + num = (point != NULL && p_scalar != NULL) ? 1 : 0; + if (group->meth->mul != NULL) + ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx); + else + /* use default */ + ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx); - return EC_POINTs_mul(group, r, g_scalar, - (point != NULL - && p_scalar != NULL), points, scalars, ctx); +#ifndef FIPS_MODULE + BN_CTX_free(new_ctx); +#endif + return ret; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { if (group->meth->mul == 0) /* use default */ - return ec_wNAF_precompute_mult(group, ctx); + return ossl_ec_wNAF_precompute_mult(group, ctx); if (group->meth->precompute_mult != 0) return group->meth->precompute_mult(group, ctx); @@ -1070,7 +1169,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group) { if (group->meth->mul == 0) /* use default */ - return ec_wNAF_have_precompute_mult(group); + return ossl_ec_wNAF_have_precompute_mult(group); if (group->meth->have_precompute_mult != 0) return group->meth->have_precompute_mult(group); @@ -1078,6 +1177,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group) return 0; /* cannot tell whether precomputation has * been performed */ } +#endif /* * ec_precompute_mont_data sets |group->mont_data| from |group->order| and @@ -1085,7 +1185,7 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group) */ static int ec_precompute_mont_data(EC_GROUP *group) { - BN_CTX *ctx = BN_CTX_new(); + BN_CTX *ctx = BN_CTX_new_ex(group->libctx); int ret = 0; BN_MONT_CTX_free(group->mont_data); @@ -1112,6 +1212,7 @@ static int ec_precompute_mont_data(EC_GROUP *group) return ret; } +#ifndef FIPS_MODULE int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg) { return CRYPTO_set_ex_data(&key->ex_data, idx, arg); @@ -1121,8 +1222,9 @@ void *EC_KEY_get_ex_data(const EC_KEY *key, int idx) { return CRYPTO_get_ex_data(&key->ex_data, idx); } +#endif -int ec_group_simple_order_bits(const EC_GROUP *group) +int ossl_ec_group_simple_order_bits(const EC_GROUP *group) { if (group->order == NULL) return 0; @@ -1133,13 +1235,19 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, const BIGNUM *x, BN_CTX *ctx) { BIGNUM *e = NULL; - BN_CTX *new_ctx = NULL; int ret = 0; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif if (group->mont_data == NULL) return 0; - if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) +#ifndef FIPS_MODULE + if (ctx == NULL) + ctx = new_ctx = BN_CTX_secure_new(); +#endif + if (ctx == NULL) return 0; BN_CTX_start(ctx); @@ -1155,17 +1263,19 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, if (!BN_sub(e, group->order, e)) goto err; /*- - * Exponent e is public. - * No need for scatter-gather or BN_FLG_CONSTTIME. + * Although the exponent is public we want the result to be + * fixed top. */ - if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data)) + if (!bn_mod_exp_mont_fixed_top(r, x, e, group->order, ctx, group->mont_data)) goto err; ret = 1; err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1182,8 +1292,8 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, * EC_METHODs must implement their own field_inverse_mod_ord for * other functionality. */ -int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, - const BIGNUM *x, BN_CTX *ctx) +int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, + const BIGNUM *x, BN_CTX *ctx) { if (group->meth->field_inverse_mod_ord != NULL) return group->meth->field_inverse_mod_ord(group, res, x, ctx); @@ -1201,10 +1311,451 @@ int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, * This wrapper returns 1 in case the underlying EC_METHOD does not * support coordinate blinding. */ -int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) +int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx) { if (group->meth->blind_coordinates == NULL) return 1; /* ignore if not implemented */ return group->meth->blind_coordinates(group, p, ctx); } + +int EC_GROUP_get_basis_type(const EC_GROUP *group) +{ + int i; + + if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field) + /* everything else is currently not supported */ + return 0; + + /* Find the last non-zero element of group->poly[] */ + for (i = 0; + i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0; + i++) + continue; + + if (i == 4) + return NID_X9_62_ppBasis; + else if (i == 2) + return NID_X9_62_tpBasis; + else + /* everything else is currently not supported */ + return 0; +} + +#ifndef OPENSSL_NO_EC2M +int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) +{ + if (group == NULL) + return 0; + + if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] == 0))) { + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k) + *k = group->poly[1]; + + return 1; +} + +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, + unsigned int *k2, unsigned int *k3) +{ + if (group == NULL) + return 0; + + if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] != 0) && (group->poly[3] != 0) + && (group->poly[4] == 0))) { + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k1) + *k1 = group->poly[3]; + if (k2) + *k2 = group->poly[2]; + if (k3) + *k3 = group->poly[1]; + + return 1; +} +#endif + +#ifndef FIPS_MODULE +/* + * Check if the explicit parameters group matches any built-in curves. + * + * We create a copy of the group just built, so that we can remove optional + * fields for the lookup: we do this to avoid the possibility that one of + * the optional parameters is used to force the library into using a less + * performant and less secure EC_METHOD instead of the specialized one. + * In any case, `seed` is not really used in any computation, while a + * cofactor different from the one in the built-in table is just + * mathematically wrong anyway and should not be used. + */ +static EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group, + OSSL_LIB_CTX *libctx, + const char *propq, + BN_CTX *ctx) +{ + EC_GROUP *ret_group = NULL, *dup = NULL; + int curve_name_nid; + + const EC_POINT *point = EC_GROUP_get0_generator(group); + const BIGNUM *order = EC_GROUP_get0_order(group); + int no_seed = (EC_GROUP_get0_seed(group) == NULL); + + if ((dup = EC_GROUP_dup(group)) == NULL + || EC_GROUP_set_seed(dup, NULL, 0) != 1 + || !EC_GROUP_set_generator(dup, point, order, NULL)) + goto err; + if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) { + /* + * The input explicit parameters successfully matched one of the + * built-in curves: often for built-in curves we have specialized + * methods with better performance and hardening. + * + * In this case we replace the `EC_GROUP` created through explicit + * parameters with one created from a named group. + */ + +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + /* + * NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for + * the same curve, we prefer the SECP nid when matching explicit + * parameters as that is associated with a specialized EC_METHOD. + */ + if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12) + curve_name_nid = NID_secp224r1; +# endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */ + + ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid); + if (ret_group == NULL) + goto err; + + /* + * Set the flag so that EC_GROUPs created from explicit parameters are + * serialized using explicit parameters by default. + */ + EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE); + + /* + * If the input params do not contain the optional seed field we make + * sure it is not added to the returned group. + * + * The seed field is not really used inside libcrypto anyway, and + * adding it to parsed explicit parameter keys would alter their DER + * encoding output (because of the extra field) which could impact + * applications fingerprinting keys by their DER encoding. + */ + if (no_seed) { + if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1) + goto err; + } + } else { + ret_group = (EC_GROUP *)group; + } + EC_GROUP_free(dup); + return ret_group; +err: + EC_GROUP_free(dup); + EC_GROUP_free(ret_group); + return NULL; +} +#endif /* FIPS_MODULE */ + +static EC_GROUP *group_new_from_name(const OSSL_PARAM *p, + OSSL_LIB_CTX *libctx, const char *propq) +{ + int ok = 0, nid; + const char *curve_name = NULL; + + switch (p->data_type) { + case OSSL_PARAM_UTF8_STRING: + /* The OSSL_PARAM functions have no support for this */ + curve_name = p->data; + ok = (curve_name != NULL); + break; + case OSSL_PARAM_UTF8_PTR: + ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name); + break; + } + + if (ok) { + nid = ossl_ec_curve_name2nid(curve_name); + if (nid == NID_undef) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); + return NULL; + } else { + return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid); + } + } + return NULL; +} + +/* These parameters can be set directly into an EC_GROUP */ +int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]) +{ + int encoding_flag = -1, format = -1; + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); + if (p != NULL) { + if (!ossl_ec_pt_format_param2id(p, &format)) { + ECerr(0, EC_R_INVALID_FORM); + return 0; + } + EC_GROUP_set_point_conversion_form(group, format); + } + + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING); + if (p != NULL) { + if (!ossl_ec_encoding_param2id(p, &encoding_flag)) { + ECerr(0, EC_R_INVALID_FORM); + return 0; + } + EC_GROUP_set_asn1_flag(group, encoding_flag); + } + /* Optional seed */ + p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED); + if (p != NULL) { + /* The seed is allowed to be NULL */ + if (p->data_type != OSSL_PARAM_OCTET_STRING + || !EC_GROUP_set_seed(group, p->data, p->data_size)) { + ECerr(0, EC_R_INVALID_SEED); + return 0; + } + } + return 1; +} + +EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], + OSSL_LIB_CTX *libctx, const char *propq) +{ + const OSSL_PARAM *ptmp; + EC_GROUP *group = NULL; + +#ifndef FIPS_MODULE + const OSSL_PARAM *pa, *pb; + int ok = 0; + EC_GROUP *named_group = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL; + EC_POINT *point = NULL; + int field_bits = 0; + int is_prime_field = 1; + BN_CTX *bnctx = NULL; + const unsigned char *buf = NULL; + int encoding_flag = -1; +#endif + + /* This is the simple named group case */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); + if (ptmp != NULL) { + int decoded = 0; + + if ((group = group_new_from_name(ptmp, libctx, propq)) == NULL) + return NULL; + if (!ossl_ec_group_set_params(group, params)) { + EC_GROUP_free(group); + return NULL; + } + + ptmp = OSSL_PARAM_locate_const(params, + OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS); + if (ptmp != NULL && !OSSL_PARAM_get_int(ptmp, &decoded)) { + ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); + EC_GROUP_free(group); + return NULL; + } + group->decoded_from_explicit_params = decoded > 0; + return group; + } +#ifdef FIPS_MODULE + ERR_raise(ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED); + return NULL; +#else + /* If it gets here then we are trying explicit parameters */ + bnctx = BN_CTX_new_ex(libctx); + if (bnctx == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return 0; + } + BN_CTX_start(bnctx); + + p = BN_CTX_get(bnctx); + a = BN_CTX_get(bnctx); + b = BN_CTX_get(bnctx); + order = BN_CTX_get(bnctx); + if (order == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE); + if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); + goto err; + } + if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) { + is_prime_field = 1; + } else if (OPENSSL_strcasecmp(ptmp->data, + SN_X9_62_characteristic_two_field) == 0) { + is_prime_field = 0; + } else { + /* Invalid field */ + ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD); + goto err; + } + + pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A); + if (!OSSL_PARAM_get_BN(pa, &a)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_A); + goto err; + } + pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B); + if (!OSSL_PARAM_get_BN(pb, &b)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_B); + goto err; + } + + /* extract the prime number or irreducible polynomial */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P); + if (!OSSL_PARAM_get_BN(ptmp, &p)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_P); + goto err; + } + + if (is_prime_field) { + if (BN_is_negative(p) || BN_is_zero(p)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_P); + goto err; + } + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); + goto err; + } + + /* create the EC_GROUP structure */ + group = EC_GROUP_new_curve_GFp(p, a, b, bnctx); + } else { +# ifdef OPENSSL_NO_EC2M + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); + goto err; +# else + /* create the EC_GROUP structure */ + group = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + if (group != NULL) { + field_bits = EC_GROUP_get_degree(group); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); + goto err; + } + } +# endif /* OPENSSL_NO_EC2M */ + } + + if (group == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + + /* Optional seed */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED); + if (ptmp != NULL) { + if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED); + goto err; + } + if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size)) + goto err; + } + + /* generator base point */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR); + if (ptmp == NULL + || ptmp->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); + goto err; + } + buf = (const unsigned char *)(ptmp->data); + if ((point = EC_POINT_new(group)) == NULL) + goto err; + EC_GROUP_set_point_conversion_form(group, + (point_conversion_form_t)buf[0] & ~0x01); + if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); + goto err; + } + + /* order */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER); + if (!OSSL_PARAM_get_BN(ptmp, &order) + || (BN_is_negative(order) || BN_is_zero(order)) + || (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */ + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); + goto err; + } + + /* Optional cofactor */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR); + if (ptmp != NULL) { + cofactor = BN_CTX_get(bnctx); + if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR); + goto err; + } + } + + /* set the generator, order and cofactor (if present) */ + if (!EC_GROUP_set_generator(group, point, order, cofactor)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); + goto err; + } + + named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx); + if (named_group == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION); + goto err; + } + if (named_group == group) { + /* + * If we did not find a named group then the encoding should be explicit + * if it was specified + */ + ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING); + if (ptmp != NULL + && !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + goto err; + } + if (encoding_flag == OPENSSL_EC_NAMED_CURVE) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + goto err; + } + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE); + } else { + EC_GROUP_free(group); + group = named_group; + } + /* We've imported the group from explicit parameters, set it so. */ + group->decoded_from_explicit_params = 1; + ok = 1; + err: + if (!ok) { + EC_GROUP_free(group); + group = NULL; + } + EC_POINT_free(point); + BN_CTX_end(bnctx); + BN_CTX_free(bnctx); + + return group; +#endif /* FIPS_MODULE */ +} diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index 64725a9c92f4..f34e06aea89a 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -1,8 +1,8 @@ /* - * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 @@ -31,6 +31,10 @@ /* Curve does not support signing operations */ #define EC_FLAGS_NO_SIGN 0x4 +#ifdef OPENSSL_NO_DEPRECATED_3_0 +typedef struct ec_method_st EC_METHOD; +#endif + /* * Structure details are not part of the exported interface, so all this may * change in future versions. @@ -76,14 +80,6 @@ struct ec_method_st { * EC_POINT_set_compressed_coordinates: */ int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *); - int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *, - EC_POINT *, const BIGNUM *x, - const BIGNUM *y, - const BIGNUM *z, BN_CTX *); - int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *, - const EC_POINT *, BIGNUM *x, - BIGNUM *y, BIGNUM *z, - BN_CTX *); int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *, const BIGNUM *x, const BIGNUM *y, BN_CTX *); @@ -179,6 +175,14 @@ struct ec_method_st { /* custom ECDH operation */ int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh); + /* custom ECDSA */ + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinvp, + BIGNUM **rp); + ECDSA_SIG *(*ecdsa_sign_sig)(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey); + int (*ecdsa_verify_sig)(const unsigned char *dgst, int dgstlen, + const ECDSA_SIG *sig, EC_KEY *eckey); /* Inverse modulo order */ int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r, const BIGNUM *x, BN_CTX *); @@ -270,6 +274,9 @@ struct ec_group_st { NISTZ256_PRE_COMP *nistz256; EC_PRE_COMP *ec; } pre_comp; + + OSSL_LIB_CTX *libctx; + char *propq; }; #define SETPRECOMP(g, type, pre) \ @@ -288,8 +295,15 @@ struct ec_key_st { point_conversion_form_t conv_form; CRYPTO_REF_COUNT references; int flags; +#ifndef FIPS_MODULE CRYPTO_EX_DATA ex_data; +#endif CRYPTO_RWLOCK *lock; + OSSL_LIB_CTX *libctx; + char *propq; + + /* Provider data */ + size_t dirty_cnt; /* If any key material changes, increment this */ }; struct ec_point_st { @@ -311,13 +325,10 @@ struct ec_point_st { static ossl_inline int ec_point_is_compat(const EC_POINT *point, const EC_GROUP *group) { - if (group->meth != point->meth - || (group->curve_name != 0 - && point->curve_name != 0 - && group->curve_name != point->curve_name)) - return 0; - - return 1; + return group->meth == point->meth + && (group->curve_name == 0 + || point->curve_name == 0 + || group->curve_name == point->curve_name); } NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *); @@ -338,249 +349,264 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *); * method functions in ec_mult.c (ec_lib.c uses these as defaults if * group->method->mul is 0) */ -int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *); -int ec_wNAF_have_precompute_mult(const EC_GROUP *group); +int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *); +int ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *); +int ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group); /* method functions in ecp_smpl.c */ -int ec_GFp_simple_group_init(EC_GROUP *); -void ec_GFp_simple_group_finish(EC_GROUP *); -void ec_GFp_simple_group_clear_finish(EC_GROUP *); -int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, - BIGNUM *b, BN_CTX *); -int ec_GFp_simple_group_get_degree(const EC_GROUP *); -int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); -int ec_GFp_simple_point_init(EC_POINT *); -void ec_GFp_simple_point_finish(EC_POINT *); -void ec_GFp_simple_point_clear_finish(EC_POINT *); -int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); -int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); -int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, - EC_POINT *, const BIGNUM *x, - const BIGNUM *y, - const BIGNUM *z, BN_CTX *); -int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, - const EC_POINT *, BIGNUM *x, - BIGNUM *y, BIGNUM *z, +int ossl_ec_GFp_simple_group_init(EC_GROUP *); +void ossl_ec_GFp_simple_group_finish(EC_GROUP *); +void ossl_ec_GFp_simple_group_clear_finish(EC_GROUP *); +int ossl_ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *); +int ossl_ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +int ossl_ec_GFp_simple_group_get_degree(const EC_GROUP *); +int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); +int ossl_ec_GFp_simple_point_init(EC_POINT *); +void ossl_ec_GFp_simple_point_finish(EC_POINT *); +void ossl_ec_GFp_simple_point_clear_finish(EC_POINT *); +int ossl_ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *); +int ossl_ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, + EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, + BN_CTX *); +int ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, + const EC_POINT *, + BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); +int ossl_ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); +int ossl_ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, BN_CTX *); -int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, - const BIGNUM *y, BN_CTX *); -int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, - const EC_POINT *, BIGNUM *x, - BIGNUM *y, BN_CTX *); -int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, - BN_CTX *); -size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, - point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *); -int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, - const unsigned char *buf, size_t len, BN_CTX *); -int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, - const EC_POINT *b, BN_CTX *); -int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, - BN_CTX *); -int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); -int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); -int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, - BN_CTX *); -int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, - EC_POINT *[], BN_CTX *); -int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, - BN_CTX *ctx); -int ec_GFp_simple_ladder_pre(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx); -int ec_GFp_simple_ladder_step(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx); -int ec_GFp_simple_ladder_post(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx); +size_t ossl_ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int ossl_ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); +int ossl_ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ossl_ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); +int ossl_ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ossl_ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ossl_ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ossl_ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ossl_ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ossl_ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ossl_ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ossl_ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx); +int ossl_ec_GFp_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ossl_ec_GFp_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ossl_ec_GFp_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); /* method functions in ecp_mont.c */ -int ec_GFp_mont_group_init(EC_GROUP *); -int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -void ec_GFp_mont_group_finish(EC_GROUP *); -void ec_GFp_mont_group_clear_finish(EC_GROUP *); -int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); +int ossl_ec_GFp_mont_group_init(EC_GROUP *); +int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +void ossl_ec_GFp_mont_group_finish(EC_GROUP *); +void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *); +int ossl_ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); +int ossl_ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); /* method functions in ecp_nist.c */ -int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); -int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); +int ossl_ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); +int ossl_ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ossl_ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ossl_ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); /* method functions in ec2_smpl.c */ -int ec_GF2m_simple_group_init(EC_GROUP *); -void ec_GF2m_simple_group_finish(EC_GROUP *); -void ec_GF2m_simple_group_clear_finish(EC_GROUP *); -int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, - BN_CTX *); -int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, - BIGNUM *b, BN_CTX *); -int ec_GF2m_simple_group_get_degree(const EC_GROUP *); -int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); -int ec_GF2m_simple_point_init(EC_POINT *); -void ec_GF2m_simple_point_finish(EC_POINT *); -void ec_GF2m_simple_point_clear_finish(EC_POINT *); -int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *); -int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); -int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, - const BIGNUM *y, BN_CTX *); -int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, - const EC_POINT *, BIGNUM *x, - BIGNUM *y, BN_CTX *); -int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, - BN_CTX *); -size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, - point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *); -int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *, - const unsigned char *buf, size_t len, BN_CTX *); -int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, - const EC_POINT *b, BN_CTX *); -int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, - BN_CTX *); -int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); -int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); -int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, - BN_CTX *); -int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, - EC_POINT *[], BN_CTX *); -int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - BN_CTX *); -int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); +int ossl_ec_GF2m_simple_group_init(EC_GROUP *); +void ossl_ec_GF2m_simple_group_finish(EC_GROUP *); +void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *); +int ossl_ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *); +int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *); +int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); +int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *); +int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); +int ossl_ec_GF2m_simple_point_init(EC_POINT *); +void ossl_ec_GF2m_simple_point_finish(EC_POINT *); +void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *); +int ossl_ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *); +int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); +int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, + EC_POINT *, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); +int ossl_ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); +size_t ossl_ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); +int ossl_ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *, + const unsigned char *buf, size_t len, BN_CTX *); +int ossl_ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ossl_ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); +int ossl_ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); +int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); +int ossl_ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); +int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ossl_ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# ifdef B_ENDIAN +# error "Can not enable ec_nistp_64_gcc_128 on big-endian systems" +# endif + /* method functions in ecp_nistp224.c */ -int ec_GFp_nistp224_group_init(EC_GROUP *group); -int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *n, - BN_CTX *); -int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx); -int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx); -int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx); -int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group); +int ossl_ec_GFp_nistp224_group_init(EC_GROUP *group); +int ossl_ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ossl_ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ossl_ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ossl_ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ossl_ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ossl_ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group); /* method functions in ecp_nistp256.c */ -int ec_GFp_nistp256_group_init(EC_GROUP *group); -int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *n, - BN_CTX *); -int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx); -int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx); -int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx); -int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group); +int ossl_ec_GFp_nistp256_group_init(EC_GROUP *group); +int ossl_ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ossl_ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ossl_ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ossl_ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ossl_ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group); /* method functions in ecp_nistp521.c */ -int ec_GFp_nistp521_group_init(EC_GROUP *group); -int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *n, - BN_CTX *); -int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx); -int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx); -int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx); -int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group); +int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group); +int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ossl_ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ossl_ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ossl_ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ossl_ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group); /* utility functions in ecp_nistputil.c */ -void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, - size_t felem_size, - void *tmp_felems, - void (*felem_one) (void *out), - int (*felem_is_zero) (const void - *in), - void (*felem_assign) (void *out, - const void - *in), - void (*felem_square) (void *out, - const void - *in), - void (*felem_mul) (void *out, - const void - *in1, - const void - *in2), - void (*felem_inv) (void *out, - const void - *in), - void (*felem_contract) (void - *out, - const - void - *in)); -void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, - unsigned char *digit, unsigned char in); +void ossl_ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, + size_t felem_size, + void *tmp_felems, + void (*felem_one) (void *out), + int (*felem_is_zero) + (const void *in), + void (*felem_assign) + (void *out, const void *in), + void (*felem_square) + (void *out, const void *in), + void (*felem_mul) + (void *out, + const void *in1, + const void *in2), + void (*felem_inv) + (void *out, const void *in), + void (*felem_contract) + (void *out, const void *in)); +void ossl_ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, + unsigned char in); #endif -int ec_group_simple_order_bits(const EC_GROUP *group); +int ossl_ec_group_simple_order_bits(const EC_GROUP *group); + +/** + * Creates a new EC_GROUP object + * \param libctx The associated library context or NULL for the default + * library context + * \param propq Any property query string + * \param meth EC_METHOD to use + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq, + const EC_METHOD *meth); #ifdef ECP_NISTZ256_ASM /** Returns GFp methods using montgomery multiplication, with x86-64 optimized @@ -589,15 +615,21 @@ int ec_group_simple_order_bits(const EC_GROUP *group); */ const EC_METHOD *EC_GFp_nistz256_method(void); #endif +#ifdef S390X_EC_ASM +const EC_METHOD *EC_GFp_s390x_nistp256_method(void); +const EC_METHOD *EC_GFp_s390x_nistp384_method(void); +const EC_METHOD *EC_GFp_s390x_nistp521_method(void); +#endif -size_t ec_key_simple_priv2oct(const EC_KEY *eckey, - unsigned char *buf, size_t len); -int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len); -int ec_key_simple_generate_key(EC_KEY *eckey); -int ec_key_simple_generate_public_key(EC_KEY *eckey); -int ec_key_simple_check_key(const EC_KEY *eckey); +size_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey, + unsigned char *buf, size_t len); +int ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, + size_t len); +int ossl_ec_key_simple_generate_key(EC_KEY *eckey); +int ossl_ec_key_simple_generate_public_key(EC_KEY *eckey); +int ossl_ec_key_simple_check_key(const EC_KEY *eckey); -int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx); +int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx); /* EC_METHOD definitions */ @@ -630,11 +662,14 @@ struct ec_key_method_st { #define EC_KEY_METHOD_DYNAMIC 1 +EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq, + ENGINE *engine); + int ossl_ec_key_gen(EC_KEY *eckey); int ossl_ecdh_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh); -int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, - const EC_POINT *pub_key, const EC_KEY *ecdh); +int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh); struct ECDSA_SIG_st { BIGNUM *r; @@ -653,18 +688,14 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); +int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey); +int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); -int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, - const uint8_t public_key[32], const uint8_t private_key[32]); -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], const uint8_t public_key[32]); -void ED25519_public_from_private(uint8_t out_public_key[32], - const uint8_t private_key[32]); - -int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], - const uint8_t peer_public_value[32]); -void X25519_public_from_private(uint8_t out_public_value[32], - const uint8_t private_key[32]); /*- * This functions computes a single point multiplication over the EC group, @@ -695,11 +726,12 @@ void X25519_public_from_private(uint8_t out_public_value[32], * * Returns 1 on success, 0 otherwise. */ -int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, const EC_POINT *point, - BN_CTX *ctx); +int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx); -int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx); +int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx); static ossl_inline int ec_point_ladder_pre(const EC_GROUP *group, EC_POINT *r, EC_POINT *s, diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index 9a1e3974ed9e..c6ec2964b7c4 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -1,13 +1,19 @@ /* - * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include <openssl/err.h> @@ -51,7 +57,7 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -62,7 +68,7 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -136,9 +142,9 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre) * * Returns 1 on success, 0 otherwise. */ -int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, const EC_POINT *point, - BN_CTX *ctx) +int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx) { int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; EC_POINT *p = NULL; @@ -153,11 +159,11 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, return EC_POINT_set_to_infinity(group, r); if (BN_is_zero(group->order)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER); return 0; } if (BN_is_zero(group->cofactor)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR); + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR); return 0; } @@ -165,18 +171,18 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, if (((p = EC_POINT_new(group)) == NULL) || ((s = EC_POINT_new(group)) == NULL)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (point == NULL) { if (!EC_POINT_copy(p, group->generator)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } else { if (!EC_POINT_copy(p, point)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } @@ -189,12 +195,12 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, lambda = BN_CTX_get(ctx); k = BN_CTX_get(ctx); if (k == NULL) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -208,12 +214,12 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, group_top = bn_get_top(cardinality); if ((bn_wexpand(k, group_top + 2) == NULL) || (bn_wexpand(lambda, group_top + 2) == NULL)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (!BN_copy(k, scalar)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -225,18 +231,18 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(k, k, cardinality, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } if (!BN_add(lambda, k, cardinality)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } BN_set_flags(lambda, BN_FLG_CONSTTIME); if (!BN_add(k, lambda, cardinality)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* @@ -256,19 +262,20 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, || (bn_wexpand(p->X, group_top) == NULL) || (bn_wexpand(p->Y, group_top) == NULL) || (bn_wexpand(p->Z, group_top) == NULL)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* ensure input point is in affine coords for ladder step efficiency */ - if (!p->Z_is_one && !EC_POINT_make_affine(group, p, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB); + if (!p->Z_is_one && (group->meth->make_affine == NULL + || !group->meth->make_affine(group, p, ctx))) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } /* Initialize the Montgomery ladder */ if (!ec_point_ladder_pre(group, r, s, p, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE); goto err; } @@ -348,7 +355,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, /* Perform a single step of the Montgomery ladder */ if (!ec_point_ladder_step(group, r, s, p, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE); goto err; } /* @@ -363,7 +370,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, /* Finalize ladder (and recover full point coordinates) */ if (!ec_point_ladder_post(group, r, s, p, ctx)) { - ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_LADDER_POST_FAILURE); goto err; } @@ -380,7 +387,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, #undef EC_POINT_BN_set_flags /* - * TODO: table should be optimised for the wNAF-based implementation, + * Table could be optimised for the wNAF-based implementation, * sometimes smaller windows will give better performance (thus the * boundaries should be increased) */ @@ -400,9 +407,9 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, * scalar*generator * in the addition if scalar != NULL */ -int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *ctx) +int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) { const EC_POINT *generator = NULL; EC_POINT *tmp = NULL; @@ -443,7 +450,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * is why we ignore if BN_FLG_CONSTTIME is actually set and we * always call the ladder version. */ - return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); + return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); } if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) { /*- @@ -453,14 +460,15 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is * actually set and we always call the ladder version. */ - return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx); + return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], + ctx); } } if (scalar != NULL) { generator = EC_GROUP_get0_generator(group); if (generator == NULL) { - ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); goto err; } @@ -488,7 +496,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, /* check that pre_comp looks sane */ if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } } else { @@ -513,7 +521,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, wNAF[0] = NULL; /* preliminary pivot */ if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -543,7 +551,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, if (pre_comp == NULL) { if (num_scalar != 1) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } /* we have already generated a wNAF for 'scalar' */ @@ -552,7 +560,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t tmp_len = 0; if (num_scalar != 0) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -595,7 +603,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, */ numblocks = (tmp_len + blocksize - 1) / blocksize; if (numblocks > pre_comp->numblocks) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); OPENSSL_free(tmp_wNAF); goto err; } @@ -610,7 +618,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, if (i < totalnum - 1) { wNAF_len[i] = blocksize; if (tmp_len < blocksize) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); OPENSSL_free(tmp_wNAF); goto err; } @@ -625,7 +633,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, wNAF[i + 1] = NULL; wNAF[i] = OPENSSL_malloc(wNAF_len[i]); if (wNAF[i] == NULL) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(tmp_wNAF); goto err; } @@ -634,7 +642,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, max_len = wNAF_len[i]; if (*tmp_points == NULL) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); OPENSSL_free(tmp_wNAF); goto err; } @@ -654,7 +662,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, */ val = OPENSSL_malloc((num_val + 1) * sizeof(val[0])); if (val == NULL) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } val[num_val] = NULL; /* pivot element */ @@ -671,7 +679,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, } } if (!(v == val + num_val)) { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -705,7 +713,8 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, } } - if (!EC_POINTs_make_affine(group, num_val, val, ctx)) + if (group->meth->points_make_affine == NULL + || !group->meth->points_make_affine(group, num_val, val, ctx)) goto err; r_is_at_infinity = 1; @@ -745,12 +754,12 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * Apply coordinate blinding for EC_POINT. * * The underlying EC_METHOD can optionally implement this function: - * ec_point_blind_coordinates() returns 0 in case of errors or 1 on + * ossl_ec_point_blind_coordinates() returns 0 in case of errors or 1 on * success or if coordinate blinding is not implemented for this * group. */ - if (!ec_point_blind_coordinates(group, r, ctx)) { - ECerr(EC_F_EC_WNAF_MUL, EC_R_POINT_COORDINATES_BLIND_FAILURE); + if (!ossl_ec_point_blind_coordinates(group, r, ctx)) { + ERR_raise(ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE); goto err; } @@ -799,9 +808,9 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, } /*- - * ec_wNAF_precompute_mult() + * ossl_ec_wNAF_precompute_mult() * creates an EC_PRE_COMP object with preprecomputed multiples of the generator - * for use with wNAF splitting as implemented in ec_wNAF_mul(). + * for use with wNAF splitting as implemented in ossl_ec_wNAF_mul(). * * 'pre_comp->points' is an array of multiples of the generator * of the following form: @@ -818,16 +827,19 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator * points[2^(w-1)*numblocks] = NULL */ -int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { const EC_POINT *generator; EC_POINT *tmp_point = NULL, *base = NULL, **var; - BN_CTX *new_ctx = NULL; const BIGNUM *order; size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; EC_POINT **points = NULL; EC_PRE_COMP *pre_comp; int ret = 0; + int used_ctx = 0; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif /* if there is an old EC_PRE_COMP object, throw it away */ EC_pre_comp_free(group); @@ -836,23 +848,25 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) generator = EC_GROUP_get0_generator(group); if (generator == NULL) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); goto err; } - if (ctx == NULL) { +#ifndef FIPS_MODULE + if (ctx == NULL) ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - } +#endif + if (ctx == NULL) + goto err; BN_CTX_start(ctx); + used_ctx = 1; order = EC_GROUP_get0_order(group); if (order == NULL) goto err; if (BN_is_zero(order)) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER); goto err; } @@ -880,7 +894,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) points = OPENSSL_malloc(sizeof(*points) * (num + 1)); if (points == NULL) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -888,14 +902,14 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) var[num] = NULL; /* pivot */ for (i = 0; i < num; i++) { if ((var[i] = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } if ((tmp_point = EC_POINT_new(group)) == NULL || (base = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -927,7 +941,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) size_t k; if (blocksize <= 2) { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -940,7 +954,8 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) } } - if (!EC_POINTs_make_affine(group, num, points, ctx)) + if (group->meth->points_make_affine == NULL + || !group->meth->points_make_affine(group, num, points, ctx)) goto err; pre_comp->group = group; @@ -955,8 +970,11 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) ret = 1; err: - BN_CTX_end(ctx); + if (used_ctx) + BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif EC_ec_pre_comp_free(pre_comp); if (points) { EC_POINT **p; @@ -970,7 +988,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) return ret; } -int ec_wNAF_have_precompute_mult(const EC_GROUP *group) +int ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group) { return HAVEPRECOMP(group, ec); } diff --git a/crypto/ec/ec_oct.c b/crypto/ec/ec_oct.c index 7ddc86b047ca..2b77e9738883 100644 --- a/crypto/ec/ec_oct.c +++ b/crypto/ec/ec_oct.c @@ -1,13 +1,19 @@ /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include <openssl/err.h> @@ -20,36 +26,33 @@ int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, { if (group->meth->point_set_compressed_coordinates == NULL && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, - ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, - EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_set_compressed_coordinates(group, point, x, - y_bit, ctx); + return ossl_ec_GFp_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); else #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES, - EC_R_GF2M_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); return 0; } #else - return ec_GF2m_simple_set_compressed_coordinates(group, point, x, - y_bit, ctx); + return ossl_ec_GF2m_simple_set_compressed_coordinates(group, point, + x, y_bit, ctx); #endif } return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); } -#if OPENSSL_API_COMPAT < 0x10200000L +#ifndef OPENSSL_NO_DEPRECATED_3_0 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, int y_bit, BN_CTX *ctx) @@ -71,27 +74,32 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx) { + if (point == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } if (group->meth->point2oct == 0 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { - ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); + return ossl_ec_GFp_simple_point2oct(group, point, form, buf, len, + ctx); else #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); return 0; } #else - return ec_GF2m_simple_point2oct(group, point, - form, buf, len, ctx); + return ossl_ec_GF2m_simple_point2oct(group, point, + form, buf, len, ctx); #endif } @@ -103,24 +111,24 @@ int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, { if (group->meth->oct2point == 0 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { - ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (!ec_point_is_compat(point, group)) { - ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); + ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_oct2point(group, point, buf, len, ctx); + return ossl_ec_GFp_simple_oct2point(group, point, buf, len, ctx); else #ifdef OPENSSL_NO_EC2M { - ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); return 0; } #else - return ec_GF2m_simple_oct2point(group, point, buf, len, ctx); + return ossl_ec_GF2m_simple_oct2point(group, point, buf, len, ctx); #endif } return group->meth->oct2point(group, point, buf, len, ctx); @@ -137,7 +145,7 @@ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, if (len == 0) return 0; if ((buf = OPENSSL_malloc(len)) == NULL) { - ECerr(EC_F_EC_POINT_POINT2BUF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } len = EC_POINT_point2oct(group, point, form, buf, len, ctx); diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index 64d2cc93a620..19e2f0d0c04d 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -1,12 +1,18 @@ /* - * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDH and ECDSA low level APIs are deprecated for public use, but still ok + * for internal use. + */ +#include "internal/deprecated.h" + #include <stdio.h> #include "internal/cryptlib.h" #include <openssl/asn1t.h> @@ -43,7 +49,7 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) EC_PKEY_CTX *dctx; if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { - ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } @@ -53,7 +59,7 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) return 1; } -static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) +static int pkey_ec_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) { EC_PKEY_CTX *dctx, *sctx; if (!pkey_ec_init(dst)) @@ -103,7 +109,12 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, int ret, type; unsigned int sltmp; EC_PKEY_CTX *dctx = ctx->data; - EC_KEY *ec = ctx->pkey->pkey.ec; + /* + * Discard const. Its marked as const because this may be a cached copy of + * the "real" key. These calls don't make any modifications that need to + * be reflected back in the "original" key. + */ + EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); const int sig_sz = ECDSA_size(ec); /* ensure cast to size_t is safe */ @@ -116,11 +127,11 @@ static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, } if (*siglen < (size_t)sig_sz) { - ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } - type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1; + type = (dctx->md != NULL) ? EVP_MD_get_type(dctx->md) : NID_sha1; ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); @@ -136,10 +147,15 @@ static int pkey_ec_verify(EVP_PKEY_CTX *ctx, { int ret, type; EC_PKEY_CTX *dctx = ctx->data; - EC_KEY *ec = ctx->pkey->pkey.ec; + /* + * Discard const. Its marked as const because this may be a cached copy of + * the "real" key. These calls don't make any modifications that need to + * be reflected back in the "original" key. + */ + EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); if (dctx->md) - type = EVP_MD_type(dctx->md); + type = EVP_MD_get_type(dctx->md); else type = NID_sha1; @@ -155,21 +171,32 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) size_t outlen; const EC_POINT *pubkey = NULL; EC_KEY *eckey; + const EC_KEY *eckeypub; EC_PKEY_CTX *dctx = ctx->data; - if (!ctx->pkey || !ctx->peerkey) { - ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); + + if (ctx->pkey == NULL || ctx->peerkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET); + return 0; + } + eckeypub = EVP_PKEY_get0_EC_KEY(ctx->peerkey); + if (eckeypub == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET); return 0; } - eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; + eckey = dctx->co_key ? dctx->co_key + : (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); if (!key) { const EC_GROUP *group; group = EC_KEY_get0_group(eckey); + + if (group == NULL) + return 0; *keylen = (EC_GROUP_get_degree(group) + 7) / 8; return 1; } - pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); + pubkey = EC_KEY_get0_public_key(eckeypub); /* * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not @@ -203,14 +230,15 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, if (!pkey_ec_derive(ctx, NULL, &ktmplen)) return 0; if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) { - ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) goto err; /* Do KDF stuff */ - if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen, - dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) + if (!ossl_ecdh_kdf_X9_63(key, *keylen, ktmp, ktmplen, + dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md, + ctx->libctx, ctx->propquery)) goto err; rv = 1; @@ -228,7 +256,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: group = EC_GROUP_new_by_curve_name(p1); if (group == NULL) { - ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); return 0; } EC_GROUP_free(dctx->gen_group); @@ -237,7 +265,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) case EVP_PKEY_CTRL_EC_PARAM_ENC: if (!dctx->gen_group) { - ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET); + ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); return 0; } EC_GROUP_set_asn1_flag(dctx->gen_group, p1); @@ -249,14 +277,23 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) if (dctx->cofactor_mode != -1) return dctx->cofactor_mode; else { - EC_KEY *ec_key = ctx->pkey->pkey.ec; + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ctx->pkey); return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0; } } else if (p1 < -1 || p1 > 1) return -2; dctx->cofactor_mode = p1; if (p1 != -1) { - EC_KEY *ec_key = ctx->pkey->pkey.ec; + EC_KEY *ec_key = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); + + /* + * We discarded the "const" above. This will only work if the key is + * a "real" legacy key, and not a cached copy of a provided key + */ + if (evp_pkey_is_provided(ctx->pkey)) { + ERR_raise(ERR_LIB_EC, ERR_R_UNSUPPORTED); + return 0; + } if (!ec_key->group) return -2; /* If cofactor is 1 cofactor mode does nothing */ @@ -318,17 +355,18 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return dctx->kdf_ukmlen; case EVP_PKEY_CTRL_MD: - if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && - EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha512 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) { - ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); + if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha384 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha512 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_224 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_256 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_384 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_512 && + EVP_MD_get_type((const EVP_MD *)p2) != NID_sm3) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE); return 0; } dctx->md = p2; @@ -362,7 +400,7 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, if (nid == NID_undef) nid = OBJ_ln2nid(value); if (nid == NID_undef) { - ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); return 0; } return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); @@ -378,7 +416,7 @@ static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, } else if (strcmp(type, "ecdh_kdf_md") == 0) { const EVP_MD *md; if ((md = EVP_get_digestbyname(value)) == NULL) { - ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST); return 0; } return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); @@ -398,7 +436,7 @@ static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) int ret; if (dctx->gen_group == NULL) { - ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); + ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); return 0; } ec = EC_KEY_new(); @@ -417,7 +455,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) int ret; if (ctx->pkey == NULL && dctx->gen_group == NULL) { - ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); + ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); return 0; } ec = EC_KEY_new(); @@ -436,7 +474,7 @@ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) return ret ? EC_KEY_generate_key(ec) : 0; } -const EVP_PKEY_METHOD ec_pkey_meth = { +static const EVP_PKEY_METHOD ec_pkey_meth = { EVP_PKEY_EC, 0, pkey_ec_init, @@ -474,3 +512,8 @@ const EVP_PKEY_METHOD ec_pkey_meth = { pkey_ec_ctrl, pkey_ec_ctrl_str }; + +const EVP_PKEY_METHOD *ossl_ec_pkey_method(void) +{ + return &ec_pkey_meth; +} diff --git a/crypto/ec/ec_print.c b/crypto/ec/ec_print.c index 660fc400fb75..ffe112052fbd 100644 --- a/crypto/ec/ec_print.c +++ b/crypto/ec/ec_print.c @@ -1,74 +1,16 @@ /* - * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +#include <string.h> /* strlen */ #include <openssl/crypto.h> -#include <openssl/err.h> #include "ec_local.h" -BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, - const EC_POINT *point, - point_conversion_form_t form, - BIGNUM *ret, BN_CTX *ctx) -{ - size_t buf_len = 0; - unsigned char *buf; - - buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx); - - if (buf_len == 0) - return NULL; - - ret = BN_bin2bn(buf, buf_len, ret); - - OPENSSL_free(buf); - - return ret; -} - -EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, - const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) -{ - size_t buf_len = 0; - unsigned char *buf; - EC_POINT *ret; - - if ((buf_len = BN_num_bytes(bn)) == 0) - buf_len = 1; - if ((buf = OPENSSL_malloc(buf_len)) == NULL) { - ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE); - return NULL; - } - - if (!BN_bn2binpad(bn, buf, buf_len)) { - OPENSSL_free(buf); - return NULL; - } - - if (point == NULL) { - if ((ret = EC_POINT_new(group)) == NULL) { - OPENSSL_free(buf); - return NULL; - } - } else - ret = point; - - if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) { - if (ret != point) - EC_POINT_clear_free(ret); - OPENSSL_free(buf); - return NULL; - } - - OPENSSL_free(buf); - return ret; -} - static const char *HEX_DIGITS = "0123456789ABCDEF"; /* the return value must be freed (using OPENSSL_free()) */ @@ -105,17 +47,39 @@ char *EC_POINT_point2hex(const EC_GROUP *group, } EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, - const char *buf, EC_POINT *point, BN_CTX *ctx) + const char *hex, EC_POINT *point, BN_CTX *ctx) { - EC_POINT *ret = NULL; - BIGNUM *tmp_bn = NULL; + int ok = 0; + unsigned char *oct_buf = NULL; + size_t len, oct_buf_len = 0; + EC_POINT *pt = NULL; - if (!BN_hex2bn(&tmp_bn, buf)) + if (group == NULL || hex == NULL) return NULL; - ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); - - BN_clear_free(tmp_bn); + if (point == NULL) { + pt = EC_POINT_new(group); + if (pt == NULL) + goto err; + } else { + pt = point; + } - return ret; + len = strlen(hex) / 2; + oct_buf = OPENSSL_malloc(len); + if (oct_buf == NULL) + goto err; + + if (!OPENSSL_hexstr2buf_ex(oct_buf, len, &oct_buf_len, hex, '\0') + || !EC_POINT_oct2point(group, pt, oct_buf, oct_buf_len, ctx)) + goto err; + ok = 1; +err: + OPENSSL_clear_free(oct_buf, oct_buf_len); + if (!ok) { + if (pt != point) + EC_POINT_clear_free(pt); + pt = NULL; + } + return pt; } diff --git a/crypto/ec/ecdh_kdf.c b/crypto/ec/ecdh_kdf.c index 96efac62f66f..de63bf8500b4 100644 --- a/crypto/ec/ecdh_kdf.c +++ b/crypto/ec/ecdh_kdf.c @@ -1,81 +1,65 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDH low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> +#include <openssl/core_names.h> #include <openssl/ec.h> #include <openssl/evp.h> +#include <openssl/kdf.h> #include "ec_local.h" /* Key derivation function from X9.63/SECG */ -/* Way more than we will ever need */ -#define ECDH_KDF_MAX (1 << 30) - -int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, - const unsigned char *Z, size_t Zlen, - const unsigned char *sinfo, size_t sinfolen, - const EVP_MD *md) +int ossl_ecdh_kdf_X9_63(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md, + OSSL_LIB_CTX *libctx, const char *propq) { - EVP_MD_CTX *mctx = NULL; - int rv = 0; - unsigned int i; - size_t mdlen; - unsigned char ctr[4]; - if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX - || Zlen > ECDH_KDF_MAX) - return 0; - mctx = EVP_MD_CTX_new(); - if (mctx == NULL) - return 0; - mdlen = EVP_MD_size(md); - for (i = 1;; i++) { - unsigned char mtmp[EVP_MAX_MD_SIZE]; - if (!EVP_DigestInit_ex(mctx, md, NULL)) - goto err; - ctr[3] = i & 0xFF; - ctr[2] = (i >> 8) & 0xFF; - ctr[1] = (i >> 16) & 0xFF; - ctr[0] = (i >> 24) & 0xFF; - if (!EVP_DigestUpdate(mctx, Z, Zlen)) - goto err; - if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr))) - goto err; - if (!EVP_DigestUpdate(mctx, sinfo, sinfolen)) - goto err; - if (outlen >= mdlen) { - if (!EVP_DigestFinal(mctx, out, NULL)) - goto err; - outlen -= mdlen; - if (outlen == 0) - break; - out += mdlen; - } else { - if (!EVP_DigestFinal(mctx, mtmp, NULL)) - goto err; - memcpy(out, mtmp, outlen); - OPENSSL_cleanse(mtmp, mdlen); - break; - } + int ret = 0; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM params[4], *p = params; + const char *mdname = EVP_MD_get0_name(md); + EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_X963KDF, propq); + + if ((kctx = EVP_KDF_CTX_new(kdf)) != NULL) { + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + (char *)mdname, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + (void *)Z, Zlen); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, + (void *)sinfo, sinfolen); + *p = OSSL_PARAM_construct_end(); + + ret = EVP_KDF_derive(kctx, out, outlen, params) > 0; + EVP_KDF_CTX_free(kctx); } - rv = 1; - err: - EVP_MD_CTX_free(mctx); - return rv; + EVP_KDF_free(kdf); + return ret; } /*- * The old name for ecdh_KDF_X9_63 * Retained for ABI compatibility */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md) { - return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md); + return ossl_ecdh_kdf_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md, NULL, + NULL); } +#endif diff --git a/crypto/ec/ecdh_ossl.c b/crypto/ec/ecdh_ossl.c index 0be00d43da4e..8016c6d7ad73 100644 --- a/crypto/ec/ecdh_ossl.c +++ b/crypto/ec/ecdh_ossl.c @@ -1,13 +1,19 @@ /* - * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDH low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include <limits.h> @@ -23,7 +29,7 @@ int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen, const EC_POINT *pub_key, const EC_KEY *ecdh) { if (ecdh->group->meth->ecdh_compute_key == NULL) { - ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH); + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH); return 0; } @@ -31,12 +37,17 @@ int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen, } /*- - * This implementation is based on the following primitives in the IEEE 1363 standard: + * This implementation is based on the following primitives in the + * IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH + * + * It also conforms to SP800-56A r3 + * See Section 5.7.1.2 "Elliptic Curve Cryptography Cofactor Diffie-Hellman + * (ECC CDH) Primitive:". The steps listed below refer to SP800-56A. */ -int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, - const EC_POINT *pub_key, const EC_KEY *ecdh) +int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, + const EC_POINT *pub_key, const EC_KEY *ecdh) { BN_CTX *ctx; EC_POINT *tmp = NULL; @@ -47,61 +58,74 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, size_t buflen, len; unsigned char *buf = NULL; - if ((ctx = BN_CTX_new()) == NULL) + if ((ctx = BN_CTX_new_ex(ecdh->libctx)) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); if (x == NULL) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_MISSING_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); goto err; } group = EC_KEY_get0_group(ecdh); + /* + * Step(1) - Compute the point tmp = cofactor * owners_private_key + * * peer_public_key. + */ if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { if (!EC_GROUP_get_cofactor(group, x, NULL) || !BN_mul(x, x, priv_key, ctx)) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } + /* + * Step(2) : If point tmp is at infinity then clear intermediate values and + * exit. Note: getting affine coordinates returns 0 if point is at infinity. + * Step(3a) : Get x-coordinate of point x = tmp.x + */ if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); + ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } + /* + * Step(3b) : convert x to a byte string, using the field-element-to-byte + * string conversion routine defined in Appendix C.2 + */ buflen = (EC_GROUP_get_degree(group) + 7) / 8; len = BN_num_bytes(x); if (len > buflen) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { - ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -112,6 +136,8 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, ret = 1; err: + /* Step(4) : Destroy all intermediate calculations */ + BN_clear(x); EC_POINT_clear_free(tmp); BN_CTX_end(ctx); BN_CTX_free(ctx); diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index 1da87bfb5e39..775b7ec911be 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -1,12 +1,18 @@ /* - * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include <openssl/err.h> #include <openssl/obj_mac.h> @@ -14,18 +20,67 @@ #include "crypto/bn.h" #include "ec_local.h" +#define MIN_ECDSA_SIGN_ORDERBITS 64 +/* + * It is highly unlikely that a retry will happen, + * Multiple retries would indicate that something is wrong + * with the group parameters (which would normally only happen + * with a bad custom group). + */ +#define MAX_ECDSA_SIGN_RETRIES 8 + +int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp) +{ + if (eckey->group->meth->ecdsa_sign_setup == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA); + return 0; + } + + return eckey->group->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp); +} + +ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey) +{ + if (eckey->group->meth->ecdsa_sign_sig == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA); + return NULL; + } + + return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len, + in_kinv, in_r, eckey); +} + +int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) +{ + if (eckey->group->meth->ecdsa_verify_sig == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA); + return 0; + } + + return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey); +} + int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey) { ECDSA_SIG *s; + if (sig == NULL && (kinv == NULL || r == NULL)) { + *siglen = ECDSA_size(eckey); + return 1; + } + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); if (s == NULL) { *siglen = 0; return 0; } - *siglen = i2d_ECDSA_SIG(s, &sig); + *siglen = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL); ECDSA_SIG_free(s); return 1; } @@ -44,42 +99,48 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, const BIGNUM *priv_key; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) { - ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_MISSING_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); return 0; } if (!EC_KEY_can_sign(eckey)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return 0; } if ((ctx = ctx_in) == NULL) { - if ((ctx = BN_CTX_new()) == NULL) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); + if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } } - k = BN_new(); /* this value is later returned in *kinvp */ + k = BN_secure_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ X = BN_new(); if (k == NULL || r == NULL || X == NULL) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + + if ((order = EC_GROUP_get0_order(group)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } - order = EC_GROUP_get0_order(group); /* Preallocate space */ order_bits = BN_num_bits(order); - if (!BN_set_bit(k, order_bits) + /* Check the number of bits here so that an infinite loop is not possible */ + if (order_bits < MIN_ECDSA_SIGN_ORDERBITS + || !BN_set_bit(k, order_bits) || !BN_set_bit(r, order_bits) || !BN_set_bit(X, order_bits)) goto err; @@ -88,41 +149,39 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, /* get random k */ do { if (dgst != NULL) { - if (!BN_generate_dsa_nonce(k, order, priv_key, - dgst, dlen, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, - EC_R_RANDOM_NUMBER_GENERATION_FAILED); + if (!ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key, + dgst, dlen, ctx)) { + ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { - if (!BN_priv_rand_range(k, order)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, - EC_R_RANDOM_NUMBER_GENERATION_FAILED); + if (!ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx)) { + ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } - } while (BN_is_zero(k)); + } while (ossl_bn_is_word_fixed_top(k, 0)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(r, X, order, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* compute the inverse of k */ - if (!ec_group_do_inverse_ord(group, k, k, ctx)) { - ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); + if (!ossl_ec_group_do_inverse_ord(group, k, k, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -145,17 +204,18 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, return ret; } -int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, - BIGNUM **rp) +int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp) { return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0); } -ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, - const BIGNUM *in_kinv, const BIGNUM *in_r, - EC_KEY *eckey) +ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey) { int ok = 0, i; + int retries = 0; BIGNUM *kinv = NULL, *s, *m = NULL; const BIGNUM *order, *ckinv; BN_CTX *ctx = NULL; @@ -167,39 +227,43 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (priv_key == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); return NULL; } if (!EC_KEY_can_sign(eckey)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return NULL; } ret = ECDSA_SIG_new(); if (ret == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } ret->r = BN_new(); ret->s = BN_new(); if (ret->r == NULL || ret->s == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } s = ret->s; - if ((ctx = BN_CTX_new()) == NULL + if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL || (m = BN_new()) == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if ((order = EC_GROUP_get0_order(group)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } - order = EC_GROUP_get0_order(group); i = BN_num_bits(order); /* * Need to truncate digest if it is too long: first truncate whole bytes. @@ -207,25 +271,25 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, if (8 * dgst_len > i) dgst_len = (i + 7) / 8; if (!BN_bin2bn(dgst, dgst_len, m)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* If still too long, truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } do { if (in_kinv == NULL || in_r == NULL) { if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } @@ -239,11 +303,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, */ if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx) || !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (!bn_mod_add_fixed_top(s, s, m, order)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* @@ -252,7 +316,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, */ if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx) || !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -262,7 +326,12 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len, * generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { - ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES); + ERR_raise(ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES); + goto err; + } + /* Avoid infinite loops cause by invalid group parameters */ + if (retries++ > MAX_ECDSA_SIGN_RETRIES) { + ERR_raise(ERR_LIB_EC, EC_R_TOO_MANY_RETRIES); goto err; } } else { @@ -314,8 +383,8 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, return ret; } -int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, - const ECDSA_SIG *sig, EC_KEY *eckey) +int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; @@ -328,18 +397,18 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); return -1; } if (!EC_KEY_can_sign(eckey)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return -1; } - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(eckey->libctx); if (ctx == NULL) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); @@ -348,26 +417,26 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (X == NULL) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } order = EC_GROUP_get0_order(group); if (order == NULL) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE); + ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ - if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + if (!ossl_ec_group_do_inverse_ord(group, u2, sig->s, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* digest -> m */ @@ -378,41 +447,41 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, if (8 * dgst_len > i) dgst_len = (i + 7) / 8; if (!BN_bin2bn(dgst, dgst_len, m)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!BN_nnmod(u1, X, order, ctx)) { - ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ diff --git a/crypto/ec/ecdsa_sign.c b/crypto/ec/ecdsa_sign.c index dc79c8c8e3df..0c0748c84f87 100644 --- a/crypto/ec/ecdsa_sign.c +++ b/crypto/ec/ecdsa_sign.c @@ -1,12 +1,18 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/ec.h> #include "ec_local.h" #include <openssl/err.h> @@ -22,7 +28,7 @@ ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dlen, { if (eckey->meth->sign_sig != NULL) return eckey->meth->sign_sig(dgst, dlen, kinv, rp, eckey); - ECerr(EC_F_ECDSA_DO_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return NULL; } @@ -38,7 +44,7 @@ int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, { if (eckey->meth->sign != NULL) return eckey->meth->sign(type, dgst, dlen, sig, siglen, kinv, r, eckey); - ECerr(EC_F_ECDSA_SIGN_EX, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return 0; } @@ -47,6 +53,6 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, { if (eckey->meth->sign_setup != NULL) return eckey->meth->sign_setup(eckey, ctx_in, kinvp, rp); - ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return 0; } diff --git a/crypto/ec/ecdsa_vrf.c b/crypto/ec/ecdsa_vrf.c index ff597bdc143c..c148ecdb7cf6 100644 --- a/crypto/ec/ecdsa_vrf.c +++ b/crypto/ec/ecdsa_vrf.c @@ -1,12 +1,18 @@ /* * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/ec.h> #include "ec_local.h" #include <openssl/err.h> @@ -22,7 +28,7 @@ int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, { if (eckey->meth->verify_sig != NULL) return eckey->meth->verify_sig(dgst, dgst_len, sig, eckey); - ECerr(EC_F_ECDSA_DO_VERIFY, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return -1; } @@ -38,6 +44,6 @@ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, if (eckey->meth->verify != NULL) return eckey->meth->verify(type, dgst, dgst_len, sigbuf, sig_len, eckey); - ECerr(EC_F_ECDSA_VERIFY, EC_R_OPERATION_NOT_SUPPORTED); + ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); return -1; } diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c index b538fadcb10c..96ced7c8be0d 100644 --- a/crypto/ec/eck_prn.c +++ b/crypto/ec/eck_prn.c @@ -1,27 +1,30 @@ /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 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 + * Licensed under the Apache License 2.0 (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 */ +#include "internal/deprecated.h" + #include <stdio.h> #include "internal/cryptlib.h" #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/bn.h> -#ifndef OPENSSL_NO_STDIO +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# ifndef OPENSSL_NO_STDIO int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off) { BIO *b; int ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BUF_LIB); return 0; } BIO_set_fp(b, fp, BIO_NOCLOSE); @@ -36,7 +39,7 @@ int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off) int ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB); return 0; } BIO_set_fp(b, fp, BIO_NOCLOSE); @@ -51,7 +54,7 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *x) int ret; if ((b = BIO_new(BIO_s_file())) == NULL) { - ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB); return 0; } BIO_set_fp(b, fp, BIO_NOCLOSE); @@ -59,7 +62,7 @@ int ECParameters_print_fp(FILE *fp, const EC_KEY *x) BIO_free(b); return ret; } -#endif +#endif /* OPENSSL_NO_STDIO */ static int print_bin(BIO *fp, const char *str, const unsigned char *num, size_t len, int off); @@ -69,10 +72,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) int ret = 0, reason = ERR_R_BIO_LIB; BN_CTX *ctx = NULL; const EC_POINT *point = NULL; - BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL; + unsigned char *gen_buf = NULL; const BIGNUM *order = NULL, *cofactor = NULL; const unsigned char *seed; - size_t seed_len = 0; + size_t seed_len = 0, gen_buf_len = 0; static const char *gen_compressed = "Generator (compressed):"; static const char *gen_uncompressed = "Generator (uncompressed):"; @@ -112,10 +116,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) goto err; } } else { + const char *form_str; /* explicit parameters */ int is_char_two = 0; point_conversion_form_t form; - int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); + int tmp_nid = EC_GROUP_get_field_type(x); if (tmp_nid == NID_X9_62_characteristic_two_field) is_char_two = 1; @@ -144,7 +149,8 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) form = EC_GROUP_get_point_conversion_form(x); - if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { + gen_buf_len = EC_POINT_point2buf(x, point, form, &gen_buf, ctx); + if (gen_buf_len == 0) { reason = ERR_R_EC_LIB; goto err; } @@ -185,22 +191,18 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) goto err; if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, NULL, off)) goto err; - if (form == POINT_CONVERSION_COMPRESSED) { - if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, - NULL, off)) - goto err; - } else if (form == POINT_CONVERSION_UNCOMPRESSED) { - if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, - NULL, off)) - goto err; - } else { /* form == POINT_CONVERSION_HYBRID */ - if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, - NULL, off)) - goto err; - } - if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, - NULL, off)) + if (form == POINT_CONVERSION_COMPRESSED) + form_str = gen_compressed; + else if (form == POINT_CONVERSION_UNCOMPRESSED) + form_str = gen_uncompressed; + else + form_str = gen_hybrid; + if (gen_buf != NULL + && !print_bin(bp, form_str, gen_buf, gen_buf_len, off)) + goto err; + + if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, NULL, off)) goto err; if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, NULL, off)) @@ -211,11 +213,11 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) ret = 1; err: if (!ret) - ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); + ERR_raise(ERR_LIB_EC, reason); BN_free(p); BN_free(a); BN_free(b); - BN_free(gen); + OPENSSL_clear_free(gen_buf, gen_buf_len); BN_CTX_free(ctx); return ret; } @@ -257,3 +259,4 @@ static int print_bin(BIO *fp, const char *name, const unsigned char *buf, return 1; } +#endif /* OPENSSL_NO_DEPRECATED_3_0 */ diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index bdc39d5efb0e..35b492453f57 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -1,13 +1,19 @@ /* - * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> #include "ec_local.h" @@ -17,98 +23,99 @@ const EC_METHOD *EC_GFp_mont_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_mont_group_init, - ec_GFp_mont_group_finish, - ec_GFp_mont_group_clear_finish, - ec_GFp_mont_group_copy, - ec_GFp_mont_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, + ossl_ec_GFp_mont_group_init, + ossl_ec_GFp_mont_group_finish, + ossl_ec_GFp_mont_group_clear_finish, + ossl_ec_GFp_mont_group_copy, + ossl_ec_GFp_mont_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_simple_point_get_affine_coordinates, 0, 0, 0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, 0 /* mul */ , 0 /* precompute_mult */ , 0 /* have_precompute_mult */ , - ec_GFp_mont_field_mul, - ec_GFp_mont_field_sqr, + ossl_ec_GFp_mont_field_mul, + ossl_ec_GFp_mont_field_sqr, 0 /* field_div */ , - ec_GFp_mont_field_inv, - ec_GFp_mont_field_encode, - ec_GFp_mont_field_decode, - ec_GFp_mont_field_set_to_one, - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_GFp_mont_field_inv, + ossl_ec_GFp_mont_field_encode, + ossl_ec_GFp_mont_field_decode, + ossl_ec_GFp_mont_field_set_to_one, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ - ec_GFp_simple_blind_coordinates, - ec_GFp_simple_ladder_pre, - ec_GFp_simple_ladder_step, - ec_GFp_simple_ladder_post + ossl_ec_GFp_simple_blind_coordinates, + ossl_ec_GFp_simple_ladder_pre, + ossl_ec_GFp_simple_ladder_step, + ossl_ec_GFp_simple_ladder_post }; return &ret; } -int ec_GFp_mont_group_init(EC_GROUP *group) +int ossl_ec_GFp_mont_group_init(EC_GROUP *group) { int ok; - ok = ec_GFp_simple_group_init(group); + ok = ossl_ec_GFp_simple_group_init(group); group->field_data1 = NULL; group->field_data2 = NULL; return ok; } -void ec_GFp_mont_group_finish(EC_GROUP *group) +void ossl_ec_GFp_mont_group_finish(EC_GROUP *group) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; BN_free(group->field_data2); group->field_data2 = NULL; - ec_GFp_simple_group_finish(group); + ossl_ec_GFp_simple_group_finish(group); } -void ec_GFp_mont_group_clear_finish(EC_GROUP *group) +void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *group) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; BN_clear_free(group->field_data2); group->field_data2 = NULL; - ec_GFp_simple_group_clear_finish(group); + ossl_ec_GFp_simple_group_clear_finish(group); } -int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) +int ossl_ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) { BN_MONT_CTX_free(dest->field_data1); dest->field_data1 = NULL; BN_clear_free(dest->field_data2); dest->field_data2 = NULL; - if (!ec_GFp_simple_group_copy(dest, src)) + if (!ossl_ec_GFp_simple_group_copy(dest, src)) return 0; if (src->field_data1 != NULL) { @@ -132,8 +139,9 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) return 0; } -int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BN_MONT_CTX *mont = NULL; @@ -146,7 +154,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, group->field_data2 = NULL; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -155,7 +163,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, p, ctx)) { - ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } one = BN_new(); @@ -169,7 +177,7 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, group->field_data2 = one; one = NULL; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { BN_MONT_CTX_free(group->field_data1); @@ -185,22 +193,22 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, return ret; } -int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { if (group->field_data1 == NULL) { - ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); return 0; } return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); } -int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) +int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { if (group->field_data1 == NULL) { - ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); return 0; } @@ -212,8 +220,8 @@ int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. * We have a Mont structure, so SCA hardening is FLT inversion. */ -int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) +int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { BIGNUM *e = NULL; BN_CTX *new_ctx = NULL; @@ -222,7 +230,8 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, if (group->field_data1 == NULL) return 0; - if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) + if (ctx == NULL + && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL) return 0; BN_CTX_start(ctx); @@ -243,7 +252,7 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, /* throw an error on zero */ if (BN_is_zero(r)) { - ECerr(EC_F_EC_GFP_MONT_FIELD_INV, EC_R_CANNOT_INVERT); + ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT); goto err; } @@ -255,33 +264,33 @@ int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, return ret; } -int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, - const BIGNUM *a, BN_CTX *ctx) +int ossl_ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) { if (group->field_data1 == NULL) { - ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); return 0; } return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); } -int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, - const BIGNUM *a, BN_CTX *ctx) +int ossl_ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) { if (group->field_data1 == NULL) { - ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); return 0; } return BN_from_montgomery(r, a, group->field_data1, ctx); } -int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, - BN_CTX *ctx) +int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, + BN_CTX *ctx) { if (group->field_data2 == NULL) { - ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); return 0; } diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index 9fd01279a891..3efd43e64c75 100644 --- a/crypto/ec/ecp_nist.c +++ b/crypto/ec/ecp_nist.c @@ -1,13 +1,19 @@ /* - * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <limits.h> #include <openssl/err.h> @@ -19,77 +25,79 @@ const EC_METHOD *EC_GFp_nist_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_simple_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nist_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, + ossl_ec_GFp_simple_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_nist_group_copy, + ossl_ec_GFp_nist_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_simple_point_get_affine_coordinates, 0, 0, 0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, 0 /* mul */ , 0 /* precompute_mult */ , 0 /* have_precompute_mult */ , - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, + ossl_ec_GFp_nist_field_mul, + ossl_ec_GFp_nist_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ - ec_GFp_simple_blind_coordinates, - ec_GFp_simple_ladder_pre, - ec_GFp_simple_ladder_step, - ec_GFp_simple_ladder_post + ossl_ec_GFp_simple_blind_coordinates, + ossl_ec_GFp_simple_ladder_pre, + ossl_ec_GFp_simple_ladder_step, + ossl_ec_GFp_simple_ladder_post }; return &ret; } -int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) +int ossl_ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) { dest->field_mod_func = src->field_mod_func; - return ec_GFp_simple_group_copy(dest, src); + return ossl_ec_GFp_simple_group_copy(dest, src); } -int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) + if ((ctx = new_ctx = BN_CTX_new_ex(group->libctx)) == NULL) return 0; BN_CTX_start(ctx); @@ -105,11 +113,11 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) group->field_mod_func = BN_nist_mod_521; else { - ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME); + ERR_raise(ERR_LIB_EC, EC_R_NOT_A_NIST_PRIME); goto err; } - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); @@ -117,18 +125,18 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, return ret; } -int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *ctx_new = NULL; if (!group || !r || !a || !b) { - ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); goto err; } if (!ctx) - if ((ctx_new = ctx = BN_CTX_new()) == NULL) + if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL) goto err; if (!BN_mul(r, a, b, ctx)) @@ -142,18 +150,18 @@ int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, return ret; } -int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) +int ossl_ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { int ret = 0; BN_CTX *ctx_new = NULL; if (!group || !r || !a) { - ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, EC_R_PASSED_NULL_PARAMETER); goto err; } if (!ctx) - if ((ctx_new = ctx = BN_CTX_new()) == NULL) + if ((ctx_new = ctx = BN_CTX_new_ex(group->libctx)) == NULL) goto err; if (!BN_sqr(r, a, ctx)) diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c index 6f7d66c8bea4..5ab0dd7bef4f 100644 --- a/crypto/ec/ecp_nistp224.c +++ b/crypto/ec/ecp_nistp224.c @@ -1,7 +1,7 @@ /* - * Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -24,6 +24,12 @@ */ /* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +/* * A 64-bit implementation of the NIST P-224 elliptic curve point multiplication * * Inspired by Daniel J. Bernstein's public domain nistp224 implementation @@ -31,22 +37,17 @@ */ #include <openssl/opensslconf.h> -#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 -NON_EMPTY_TRANSLATION_UNIT -#else - -# include <stdint.h> -# include <string.h> -# include <openssl/err.h> -# include "ec_local.h" - -# 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 "Your compiler doesn't appear to support 128-bit integer types" -# endif + +#include <stdint.h> +#include <string.h> +#include <openssl/err.h> +#include "ec_local.h" + +#include "internal/numbers.h" + +#ifndef INT128_MAX +# error "Your compiler doesn't appear to support 128-bit integer types" +#endif typedef uint8_t u8; typedef uint64_t u64; @@ -245,54 +246,55 @@ const EC_METHOD *EC_GFp_nistp224_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_nistp224_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp224_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp224_point_get_affine_coordinates, + ossl_ec_GFp_nistp224_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_nist_group_copy, + ossl_ec_GFp_nistp224_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_nistp224_point_get_affine_coordinates, 0 /* point_set_compressed_coordinates */ , 0 /* point2oct */ , 0 /* oct2point */ , - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, - ec_GFp_nistp224_points_mul, - ec_GFp_nistp224_precompute_mult, - ec_GFp_nistp224_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, + ossl_ec_GFp_nistp224_points_mul, + ossl_ec_GFp_nistp224_precompute_mult, + ossl_ec_GFp_nistp224_have_precompute_mult, + ossl_ec_GFp_nist_field_mul, + ossl_ec_GFp_nist_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ 0, /* blind_coordinates */ 0, /* ladder_pre */ @@ -332,12 +334,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn) int num_bytes; if (BN_is_negative(bn)) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out)); if (num_bytes < 0) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } bin28_to_felem(out, b_out); @@ -663,7 +665,9 @@ static void felem_contract(felem out, const felem in) */ static void felem_neg(felem out, const felem in) { - widefelem tmp = {0}; + widefelem tmp; + + memset(tmp, 0, sizeof(tmp)); felem_diff_128_64(tmp, in); felem_reduce(out, tmp); } @@ -1201,7 +1205,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, bits |= get_bit(scalars[num], i + 1) << 2; bits |= get_bit(scalars[num], i) << 1; bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); /* select the point to add or subtract */ select_point(digit, 17, pre_comp[num], tmp); @@ -1235,7 +1239,7 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); if (!ret) { - ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -1243,7 +1247,7 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -1266,7 +1270,7 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p) return; CRYPTO_DOWN_REF(&p->references, &i, p->lock); - REF_PRINT_COUNT("EC_nistp224", x); + REF_PRINT_COUNT("EC_nistp224", p); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1280,25 +1284,29 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p) * OPENSSL EC_METHOD FUNCTIONS */ -int ec_GFp_nistp224_group_init(EC_GROUP *group) +int ossl_ec_GFp_nistp224_group_init(EC_GROUP *group) { int ret; - ret = ec_GFp_simple_group_init(group); + ret = ossl_ec_GFp_simple_group_init(group); group->a_is_minus3 = 1; return ret; } -int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, - BN_CTX *ctx) +int ossl_ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { int ret = 0; - BN_CTX *new_ctx = NULL; BIGNUM *curve_p, *curve_a, *curve_b; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); curve_p = BN_CTX_get(ctx); curve_a = BN_CTX_get(ctx); @@ -1309,15 +1317,16 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a); BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b); if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { - ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); goto err; } group->field_mod_func = BN_nist_mod_224; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1325,17 +1334,16 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = * (X/Z^2, Y/Z^3) */ -int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { felem z1, z2, x_in, y_in, x_out, y_out; widefelem tmp; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || @@ -1349,8 +1357,7 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(x_out, x_in); if (x != NULL) { if (!felem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1361,8 +1368,7 @@ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(y_out, y_in); if (y != NULL) { if (!felem_to_BN(y, y_out)) { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1376,36 +1382,36 @@ static void make_points_affine(size_t num, felem points[ /* num */ ][3], * Runs in constant time, unless an input is the point at infinity (which * normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal(num, - points, - sizeof(felem), - tmp_felems, - (void (*)(void *))felem_one, - felem_is_zero_int, - (void (*)(void *, const void *)) - felem_assign, - (void (*)(void *, const void *)) - felem_square_reduce, (void (*) - (void *, - const void - *, - const void - *)) - felem_mul_reduce, - (void (*)(void *, const void *)) - felem_inv, - (void (*)(void *, const void *)) - felem_contract); + ossl_ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); } /* * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL * values Result is stored in r (r can equal one of the inputs). */ -int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) +int ossl_ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) { int ret = 0; int j; @@ -1449,12 +1455,12 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, if (!felem_to_BN(x, g_pre_comp[0][1][0]) || !felem_to_BN(y, g_pre_comp[0][1][1]) || !felem_to_BN(z, g_pre_comp[0][1][2])) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, - ctx)) + if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, + generator, + x, y, z, ctx)) goto err; if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) /* precomputation matches generator */ @@ -1482,7 +1488,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, OPENSSL_malloc(sizeof(felem) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -1509,7 +1515,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, @@ -1519,7 +1525,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, secrets[i], sizeof(secrets[i])); } if (num_bytes < 0) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* precompute multiples */ @@ -1561,7 +1567,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret)); @@ -1585,10 +1591,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, felem_contract(z_in, z_out); if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || (!felem_to_BN(z, z_in))) { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z, + ctx); err: BN_CTX_end(ctx); @@ -1599,21 +1606,28 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, return ret; } -int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { int ret = 0; NISTP224_PRE_COMP *pre = NULL; int i, j; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; EC_POINT *generator = NULL; felem tmp_felems[32]; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif /* throw away old precomputation */ EC_pre_comp_free(group); + +#ifndef FIPS_MODULE if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); @@ -1721,14 +1735,14 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) err: BN_CTX_end(ctx); EC_POINT_free(generator); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif EC_nistp224_pre_comp_free(pre); return ret; } -int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group) +int ossl_ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group) { return HAVEPRECOMP(group, nistp224); } - -#endif diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c index e23e9d2a0b34..4a55f925c465 100644 --- a/crypto/ec/ecp_nistp256.c +++ b/crypto/ec/ecp_nistp256.c @@ -1,7 +1,7 @@ /* - * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -24,6 +24,12 @@ */ /* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +/* * A 64-bit implementation of the NIST P-256 elliptic curve point multiplication * * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. @@ -32,23 +38,17 @@ */ #include <openssl/opensslconf.h> -#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 -NON_EMPTY_TRANSLATION_UNIT -#else - -# include <stdint.h> -# include <string.h> -# include <openssl/err.h> -# include "ec_local.h" - -# 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 "Your compiler doesn't appear to support 128-bit integer types" -# endif + +#include <stdint.h> +#include <string.h> +#include <openssl/err.h> +#include "ec_local.h" + +#include "internal/numbers.h" + +#ifndef INT128_MAX +# error "Your compiler doesn't appear to support 128-bit integer types" +#endif typedef uint8_t u8; typedef uint32_t u32; @@ -56,7 +56,7 @@ typedef uint64_t u64; /* * The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We - * can serialise an element of this field into 32 bytes. We call this an + * can serialize an element of this field into 32 bytes. We call this an * felem_bytearray. */ @@ -110,7 +110,7 @@ static const felem_bytearray nistp256_curve_params[5] = { * values are used as intermediate values before multiplication. */ -# define NLIMBS 4 +#define NLIMBS 4 typedef uint128_t limb; typedef limb felem[NLIMBS]; @@ -135,7 +135,7 @@ static void bin32_to_felem(felem out, const u8 in[32]) } /* - * smallfelem_to_bin32 takes a smallfelem and serialises into a little + * smallfelem_to_bin32 takes a smallfelem and serializes into a little * endian, 32 byte array. This assumes that the CPU is little-endian. */ static void smallfelem_to_bin32(u8 out[32], const smallfelem in) @@ -153,12 +153,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn) int num_bytes; if (BN_is_negative(bn)) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out)); if (num_bytes < 0) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } bin32_to_felem(out, b_out); @@ -242,9 +242,9 @@ static void longfelem_scalar(longfelem out, const u64 scalar) out[7] *= scalar; } -# define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) -# define two105 (((limb)1) << 105) -# define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) +#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) +#define two105 (((limb)1) << 105) +#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) /* zero105 is 0 mod p */ static const felem zero105 = @@ -287,9 +287,9 @@ static void felem_diff(felem out, const felem in) out[3] -= in[3]; } -# define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) -# define two107 (((limb)1) << 107) -# define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) +#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) +#define two107 (((limb)1) << 107) +#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) /* zero107 is 0 mod p */ static const felem zero107 = @@ -358,10 +358,10 @@ static void longfelem_diff(longfelem out, const longfelem in) out[7] -= in[7]; } -# define two64m0 (((limb)1) << 64) - 1 -# define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 -# define two64m46 (((limb)1) << 64) - (((limb)1) << 46) -# define two64m32 (((limb)1) << 64) - (((limb)1) << 32) +#define two64m0 (((limb)1) << 64) - 1 +#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 +#define two64m46 (((limb)1) << 64) - (((limb)1) << 46) +#define two64m32 (((limb)1) << 64) - (((limb)1) << 32) /* zero110 is 0 mod p */ static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 }; @@ -711,9 +711,9 @@ static void felem_small_mul(longfelem out, const smallfelem small1, smallfelem_mul(out, small1, small2); } -# define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) -# define two100 (((limb)1) << 100) -# define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) +#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) +#define two100 (((limb)1) << 100) +#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) /* zero100 is 0 mod p */ static const felem zero100 = { two100m36m4, two100, two100m36p4, two100m36p4 }; @@ -1740,7 +1740,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, bits |= get_bit(scalars[num], i + 1) << 2; bits |= get_bit(scalars[num], i) << 1; bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); /* * select the point to add or subtract, in constant time @@ -1781,54 +1781,55 @@ const EC_METHOD *EC_GFp_nistp256_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_nistp256_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp256_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp256_point_get_affine_coordinates, + ossl_ec_GFp_nistp256_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_nist_group_copy, + ossl_ec_GFp_nistp256_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_nistp256_point_get_affine_coordinates, 0 /* point_set_compressed_coordinates */ , 0 /* point2oct */ , 0 /* oct2point */ , - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, - ec_GFp_nistp256_points_mul, - ec_GFp_nistp256_precompute_mult, - ec_GFp_nistp256_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, + ossl_ec_GFp_nistp256_points_mul, + ossl_ec_GFp_nistp256_precompute_mult, + ossl_ec_GFp_nistp256_have_precompute_mult, + ossl_ec_GFp_nist_field_mul, + ossl_ec_GFp_nist_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ 0, /* blind_coordinates */ 0, /* ladder_pre */ @@ -1849,7 +1850,7 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void) NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -1857,7 +1858,7 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -1880,7 +1881,7 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre) return; CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_nistp256", x); + REF_PRINT_COUNT("EC_nistp256", pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1894,25 +1895,29 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre) * OPENSSL EC_METHOD FUNCTIONS */ -int ec_GFp_nistp256_group_init(EC_GROUP *group) +int ossl_ec_GFp_nistp256_group_init(EC_GROUP *group) { int ret; - ret = ec_GFp_simple_group_init(group); + ret = ossl_ec_GFp_simple_group_init(group); group->a_is_minus3 = 1; return ret; } -int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, - BN_CTX *ctx) +int ossl_ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { int ret = 0; - BN_CTX *new_ctx = NULL; BIGNUM *curve_p, *curve_a, *curve_b; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); curve_p = BN_CTX_get(ctx); curve_a = BN_CTX_get(ctx); @@ -1923,15 +1928,16 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a); BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b); if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { - ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); goto err; } group->field_mod_func = BN_nist_mod_256; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1939,18 +1945,17 @@ int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = * (X/Z^2, Y/Z^3) */ -int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { felem z1, z2, x_in, y_in; smallfelem x_out, y_out; longfelem tmp; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || @@ -1964,8 +1969,7 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(x_out, x_in); if (x != NULL) { if (!smallfelem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1976,8 +1980,7 @@ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(y_out, y_in); if (y != NULL) { if (!smallfelem_to_BN(y, y_out)) { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1992,35 +1995,35 @@ static void make_points_affine(size_t num, smallfelem points[][3], * Runs in constant time, unless an input is the point at infinity (which * normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal(num, - points, - sizeof(smallfelem), - tmp_smallfelems, - (void (*)(void *))smallfelem_one, - smallfelem_is_zero_int, - (void (*)(void *, const void *)) - smallfelem_assign, - (void (*)(void *, const void *)) - smallfelem_square_contract, - (void (*) - (void *, const void *, - const void *)) - smallfelem_mul_contract, - (void (*)(void *, const void *)) - smallfelem_inv_contract, - /* nothing to contract */ - (void (*)(void *, const void *)) - smallfelem_assign); + ossl_ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(smallfelem), + tmp_smallfelems, + (void (*)(void *))smallfelem_one, + smallfelem_is_zero_int, + (void (*)(void *, const void *)) + smallfelem_assign, + (void (*)(void *, const void *)) + smallfelem_square_contract, + (void (*) + (void *, const void *, + const void *)) + smallfelem_mul_contract, + (void (*)(void *, const void *)) + smallfelem_inv_contract, + /* nothing to contract */ + (void (*)(void *, const void *)) + smallfelem_assign); } /* * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL * values Result is stored in r (r can equal one of the inputs). */ -int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) +int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) { int ret = 0; int j; @@ -2065,12 +2068,12 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) || !smallfelem_to_BN(y, g_pre_comp[0][1][1]) || !smallfelem_to_BN(z, g_pre_comp[0][1][2])) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, - ctx)) + if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, + generator, + x, y, z, ctx)) goto err; if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) /* precomputation matches generator */ @@ -2097,7 +2100,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, OPENSSL_malloc(sizeof(*tmp_smallfelems) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_smallfelems == NULL))) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -2129,7 +2132,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, @@ -2139,7 +2142,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, secrets[i], sizeof(secrets[i])); } if (num_bytes < 0) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* precompute multiples */ @@ -2183,7 +2186,7 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret)); @@ -2207,10 +2210,11 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, felem_contract(z_in, z_out); if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) || (!smallfelem_to_BN(z, z_in))) { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z, + ctx); err: BN_CTX_end(ctx); @@ -2221,22 +2225,29 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, return ret; } -int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { int ret = 0; NISTP256_PRE_COMP *pre = NULL; int i, j; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; EC_POINT *generator = NULL; smallfelem tmp_smallfelems[32]; felem x_tmp, y_tmp, z_tmp; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif /* throw away old precomputation */ EC_pre_comp_free(group); + +#ifndef FIPS_MODULE if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); @@ -2354,13 +2365,14 @@ int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx) err: BN_CTX_end(ctx); EC_POINT_free(generator); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif EC_nistp256_pre_comp_free(pre); return ret; } -int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group) +int ossl_ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group) { return HAVEPRECOMP(group, nistp256); } -#endif diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c index 08b32787293b..31a97d793742 100644 --- a/crypto/ec/ecp_nistp521.c +++ b/crypto/ec/ecp_nistp521.c @@ -1,7 +1,7 @@ /* - * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -24,6 +24,12 @@ */ /* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +/* * A 64-bit implementation of the NIST P-521 elliptic curve point multiplication * * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. @@ -32,27 +38,22 @@ */ #include <openssl/e_os2.h> -#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 -NON_EMPTY_TRANSLATION_UNIT -#else -# include <string.h> -# include <openssl/err.h> -# include "ec_local.h" +#include <string.h> +#include <openssl/err.h> +#include "ec_local.h" -# 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 "Your compiler doesn't appear to support 128-bit integer types" -# endif +#include "internal/numbers.h" + +#ifndef INT128_MAX +# error "Your compiler doesn't appear to support 128-bit integer types" +#endif typedef uint8_t u8; typedef uint64_t u64; /* - * The underlying field. P521 operates over GF(2^521-1). We can serialise an + * The underlying field. P521 operates over GF(2^521-1). We can serialize an * element of this field into 66 bytes where the most significant byte * contains only a single bit. We call this an felem_bytearray. */ @@ -125,7 +126,7 @@ static const felem_bytearray nistp521_curve_params[5] = { * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a * 'largefelem' */ -# define NLIMBS 9 +#define NLIMBS 9 typedef uint64_t limb; typedef limb limb_aX __attribute((__aligned__(1))); @@ -153,7 +154,7 @@ static void bin66_to_felem(felem out, const u8 in[66]) } /* - * felem_to_bin66 takes an felem and serialises into a little endian, 66 byte + * felem_to_bin66 takes an felem and serializes into a little endian, 66 byte * array. This assumes that the CPU is little-endian. */ static void felem_to_bin66(u8 out[66], const felem in) @@ -177,12 +178,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn) int num_bytes; if (BN_is_negative(bn)) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out)); if (num_bytes < 0) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } bin66_to_felem(out, b_out); @@ -400,7 +401,7 @@ static void felem_diff128(largefelem out, const largefelem in) * On exit: * out[i] < 17 * max(in[i]) * max(in[i]) */ -static void felem_square(largefelem out, const felem in) +static void felem_square_ref(largefelem out, const felem in) { felem inx2, inx4; felem_scalar(inx2, in, 2); @@ -484,7 +485,7 @@ static void felem_square(largefelem out, const felem in) * On exit: * out[i] < 17 * max(in1[i]) * max(in2[i]) */ -static void felem_mul(largefelem out, const felem in1, const felem in2) +static void felem_mul_ref(largefelem out, const felem in1, const felem in2) { felem in2x2; felem_scalar(in2x2, in2, 2); @@ -674,6 +675,57 @@ static void felem_reduce(felem out, const largefelem in) */ } +#if defined(ECP_NISTP521_ASM) +void felem_square_wrapper(largefelem out, const felem in); +void felem_mul_wrapper(largefelem out, const felem in1, const felem in2); + +static void (*felem_square_p)(largefelem out, const felem in) = + felem_square_wrapper; +static void (*felem_mul_p)(largefelem out, const felem in1, const felem in2) = + felem_mul_wrapper; + +void p521_felem_square(largefelem out, const felem in); +void p521_felem_mul(largefelem out, const felem in1, const felem in2); + +# if defined(_ARCH_PPC64) +# include "crypto/ppc_arch.h" +# endif + +void felem_select(void) +{ +# if defined(_ARCH_PPC64) + if ((OPENSSL_ppccap_P & PPC_MADD300) && (OPENSSL_ppccap_P & PPC_ALTIVEC)) { + felem_square_p = p521_felem_square; + felem_mul_p = p521_felem_mul; + + return; + } +# endif + + /* Default */ + felem_square_p = felem_square_ref; + felem_mul_p = felem_mul_ref; +} + +void felem_square_wrapper(largefelem out, const felem in) +{ + felem_select(); + felem_square_p(out, in); +} + +void felem_mul_wrapper(largefelem out, const felem in1, const felem in2) +{ + felem_select(); + felem_mul_p(out, in1, in2); +} + +# define felem_square felem_square_p +# define felem_mul felem_mul_p +#else +# define felem_square felem_square_ref +# define felem_mul felem_mul_ref +#endif + static void felem_square_reduce(felem out, const felem in) { largefelem tmp; @@ -1266,8 +1318,8 @@ static void point_add(felem x3, felem y3, felem z3, * 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 + * Since |ossl_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 @@ -1584,7 +1636,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, bits |= get_bit(scalars[num], i + 1) << 2; bits |= get_bit(scalars[num], i) << 1; bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); /* * select the point to add or subtract, in constant time @@ -1622,54 +1674,55 @@ const EC_METHOD *EC_GFp_nistp521_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_nistp521_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp521_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp521_point_get_affine_coordinates, + ossl_ec_GFp_nistp521_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_nist_group_copy, + ossl_ec_GFp_nistp521_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_nistp521_point_get_affine_coordinates, 0 /* point_set_compressed_coordinates */ , 0 /* point2oct */ , 0 /* oct2point */ , - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, - ec_GFp_nistp521_points_mul, - ec_GFp_nistp521_precompute_mult, - ec_GFp_nistp521_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, + ossl_ec_GFp_nistp521_points_mul, + ossl_ec_GFp_nistp521_precompute_mult, + ossl_ec_GFp_nistp521_have_precompute_mult, + ossl_ec_GFp_nist_field_mul, + ossl_ec_GFp_nist_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ 0, /* blind_coordinates */ 0, /* ladder_pre */ @@ -1690,7 +1743,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -1698,7 +1751,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -1721,7 +1774,7 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) return; CRYPTO_DOWN_REF(&p->references, &i, p->lock); - REF_PRINT_COUNT("EC_nistp521", x); + REF_PRINT_COUNT("EC_nistp521", p); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1735,25 +1788,29 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) * OPENSSL EC_METHOD FUNCTIONS */ -int ec_GFp_nistp521_group_init(EC_GROUP *group) +int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group) { int ret; - ret = ec_GFp_simple_group_init(group); + ret = ossl_ec_GFp_simple_group_init(group); group->a_is_minus3 = 1; return ret; } -int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, - BN_CTX *ctx) +int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { int ret = 0; - BN_CTX *new_ctx = NULL; BIGNUM *curve_p, *curve_a, *curve_b; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); curve_p = BN_CTX_get(ctx); curve_a = BN_CTX_get(ctx); @@ -1764,15 +1821,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a); BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b); if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { - ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); goto err; } group->field_mod_func = BN_nist_mod_521; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1780,17 +1838,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = * (X/Z^2, Y/Z^3) */ -int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { felem z1, z2, x_in, y_in, x_out, y_out; largefelem tmp; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || @@ -1804,8 +1861,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(x_out, x_in); if (x != NULL) { if (!felem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1816,8 +1872,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(y_out, y_in); if (y != NULL) { if (!felem_to_BN(y, y_out)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1832,36 +1887,36 @@ static void make_points_affine(size_t num, felem points[][3], * Runs in constant time, unless an input is the point at infinity (which * normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal(num, - points, - sizeof(felem), - tmp_felems, - (void (*)(void *))felem_one, - felem_is_zero_int, - (void (*)(void *, const void *)) - felem_assign, - (void (*)(void *, const void *)) - felem_square_reduce, (void (*) - (void *, - const void - *, - const void - *)) - felem_mul_reduce, - (void (*)(void *, const void *)) - felem_inv, - (void (*)(void *, const void *)) - felem_contract); + ossl_ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); } /* * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL * values Result is stored in r (r can equal one of the inputs). */ -int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) +int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) { int ret = 0; int j; @@ -1905,12 +1960,12 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, if (!felem_to_BN(x, g_pre_comp[1][0]) || !felem_to_BN(y, g_pre_comp[1][1]) || !felem_to_BN(z, g_pre_comp[1][2])) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, - ctx)) + if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, + generator, + x, y, z, ctx)) goto err; if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) /* precomputation matches generator */ @@ -1938,7 +1993,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -1968,7 +2023,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, @@ -1978,7 +2033,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, secrets[i], sizeof(secrets[i])); } if (num_bytes < 0) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* precompute multiples */ @@ -2020,7 +2075,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret)); @@ -2045,10 +2100,11 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, felem_contract(z_in, z_out); if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || (!felem_to_BN(z, z_in))) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z, + ctx); err: BN_CTX_end(ctx); @@ -2059,21 +2115,28 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, return ret; } -int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { int ret = 0; NISTP521_PRE_COMP *pre = NULL; int i, j; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; EC_POINT *generator = NULL; felem tmp_felems[16]; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif /* throw away old precomputation */ EC_pre_comp_free(group); + +#ifndef FIPS_MODULE if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); @@ -2161,14 +2224,14 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) err: BN_CTX_end(ctx); EC_POINT_free(generator); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif EC_nistp521_pre_comp_free(pre); return ret; } -int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) +int ossl_ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) { return HAVEPRECOMP(group, nistp521); } - -#endif diff --git a/crypto/ec/ecp_nistputil.c b/crypto/ec/ecp_nistputil.c index 60e1325c340f..4e8c0e276769 100644 --- a/crypto/ec/ecp_nistputil.c +++ b/crypto/ec/ecp_nistputil.c @@ -1,7 +1,7 @@ /* - * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -23,17 +23,20 @@ * limitations under the License. */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/opensslconf.h> -#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 -NON_EMPTY_TRANSLATION_UNIT -#else /* * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c. */ -# include <stddef.h> -# include "ec_local.h" +#include <stddef.h> +#include "ec_local.h" /* * Convert an array of points into affine coordinates. (If the point at @@ -46,7 +49,8 @@ NON_EMPTY_TRANSLATION_UNIT * of size 'felem_size'. tmp_felems needs to point to a temporary array of * 'num'+1 field elements for storage of intermediate values. */ -void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, +void +ossl_ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, size_t felem_size, void *tmp_felems, void (*felem_one) (void *out), @@ -74,10 +78,10 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, { int i = 0; -# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size]) -# define X(I) (&((char *)point_array)[3*(I) * felem_size]) -# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size]) -# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size]) +#define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size]) +#define X(I) (&((char *)point_array)[3*(I) * felem_size]) +#define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size]) +#define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size]) if (!felem_is_zero(Z(0))) felem_assign(tmp_felem(0), Z(0)); @@ -206,8 +210,8 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, * b_-1, has to be b_4 b_3 b_2 b_1 b_0 0. * */ -void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, - unsigned char *digit, unsigned char in) +void ossl_ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, unsigned char in) { unsigned char s, d; @@ -220,4 +224,3 @@ void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, *sign = s & 1; *digit = d; } -#endif diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index cfad3e15b0bf..d65f6984ded3 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -3,7 +3,7 @@ * Copyright (c) 2014, Intel Corporation. All Rights Reserved. * Copyright (c) 2015, CloudFlare, Inc. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 @@ -18,6 +18,12 @@ * 256 Bit Primes" */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <string.h> #include "internal/cryptlib.h" @@ -631,7 +637,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group, || (p_str = OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL || (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) { - ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -648,7 +654,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group, if ((mod = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_nnmod(mod, scalar[i], group->order, ctx)) { - ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } scalars[i] = mod; @@ -676,8 +682,7 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group, if (!ecp_nistz256_bignum_to_field_elem(temp[0].X, point[i]->X) || !ecp_nistz256_bignum_to_field_elem(temp[0].Y, point[i]->Y) || !ecp_nistz256_bignum_to_field_elem(temp[0].Z, point[i]->Z)) { - ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, - EC_R_COORDINATES_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } @@ -828,7 +833,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) EC_pre_comp_free(group); generator = EC_GROUP_get0_generator(group); if (generator == NULL) { - ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); return 0; } @@ -844,7 +849,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) return 0; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) goto err; } @@ -856,7 +861,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) goto err; if (BN_is_zero(order)) { - ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNKNOWN_ORDER); + ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER); goto err; } @@ -864,7 +869,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) if ((precomp_storage = OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) { - ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -891,12 +896,12 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) * It would be faster to use EC_POINTs_make_affine and * make multiple points affine at the same time. */ - if (!EC_POINT_make_affine(group, P, ctx)) + if (group->meth->make_affine == NULL + || !group->meth->make_affine(group, P, ctx)) goto err; if (!ecp_nistz256_bignum_to_field_elem(temp.X, P->X) || !ecp_nistz256_bignum_to_field_elem(temp.Y, P->Y)) { - ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, - EC_R_COORDINATES_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } ecp_nistz256_scatter_w7(preComputedTable[j], &temp, k); @@ -969,7 +974,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, BIGNUM *tmp_scalar; if ((num + 1) == 0 || (num + 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } @@ -979,7 +984,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, if (scalar) { generator = EC_GROUP_get0_generator(group); if (generator == NULL) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_UNDEFINED_GENERATOR); + ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); goto err; } @@ -1027,7 +1032,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, goto err; if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } scalar = tmp_scalar; @@ -1119,13 +1124,13 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, */ new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *)); if (new_scalars == NULL) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *)); if (new_points == NULL) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -1180,14 +1185,14 @@ __owur static int ecp_nistz256_get_affine(const EC_GROUP *group, BN_ULONG x_ret[P256_LIMBS], y_ret[P256_LIMBS]; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if (!ecp_nistz256_bignum_to_field_elem(point_x, point->X) || !ecp_nistz256_bignum_to_field_elem(point_y, point->Y) || !ecp_nistz256_bignum_to_field_elem(point_z, point->Z)) { - ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_COORDINATES_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); return 0; } @@ -1222,7 +1227,7 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group) ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -1232,7 +1237,7 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -1255,7 +1260,7 @@ void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre) return; CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_nistz256", x); + REF_PRINT_COUNT("EC_nistz256", pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1291,7 +1296,7 @@ void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS], const BN_ULONG b[P256_LIMBS]); void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS], - int rep); + BN_ULONG rep); static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, const BIGNUM *x, BN_CTX *ctx) @@ -1321,7 +1326,7 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, * Catch allocation failure early. */ if (bn_wexpand(r, P256_LIMBS) == NULL) { - ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -1330,14 +1335,14 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, if ((tmp = BN_CTX_get(ctx)) == NULL || !BN_nnmod(tmp, x, group->order, ctx)) { - ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } x = tmp; } if (!ecp_nistz256_bignum_to_field_elem(t, x)) { - ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); goto err; } @@ -1467,52 +1472,53 @@ const EC_METHOD *EC_GFp_nistz256_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_mont_group_init, - ec_GFp_mont_group_finish, - ec_GFp_mont_group_clear_finish, - ec_GFp_mont_group_copy, - ec_GFp_mont_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_mont_group_init, + ossl_ec_GFp_mont_group_finish, + ossl_ec_GFp_mont_group_clear_finish, + ossl_ec_GFp_mont_group_copy, + ossl_ec_GFp_mont_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, ecp_nistz256_get_affine, 0, 0, 0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, ecp_nistz256_points_mul, /* mul */ ecp_nistz256_mult_precompute, /* precompute_mult */ ecp_nistz256_window_have_precompute_mult, /* have_precompute_mult */ - ec_GFp_mont_field_mul, - ec_GFp_mont_field_sqr, + ossl_ec_GFp_mont_field_mul, + ossl_ec_GFp_mont_field_sqr, 0, /* field_div */ - ec_GFp_mont_field_inv, - ec_GFp_mont_field_encode, - ec_GFp_mont_field_decode, - ec_GFp_mont_field_set_to_one, - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_GFp_mont_field_inv, + ossl_ec_GFp_mont_field_encode, + ossl_ec_GFp_mont_field_decode, + ossl_ec_GFp_mont_field_set_to_one, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */ 0, /* blind_coordinates */ 0, /* ladder_pre */ diff --git a/crypto/ec/ecp_nistz256_table.c b/crypto/ec/ecp_nistz256_table.c index 3f5625c6c5eb..71430d4b8142 100644 --- a/crypto/ec/ecp_nistz256_table.c +++ b/crypto/ec/ecp_nistz256_table.c @@ -1,7 +1,7 @@ /* * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 diff --git a/crypto/ec/ecp_oct.c b/crypto/ec/ecp_oct.c index 9460763256fd..68943e521e8a 100644 --- a/crypto/ec/ecp_oct.c +++ b/crypto/ec/ecp_oct.c @@ -1,32 +1,35 @@ /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> #include <openssl/symhacks.h> #include "ec_local.h" -int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, - EC_POINT *point, - const BIGNUM *x_, int y_bit, - BN_CTX *ctx) +int ossl_ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp1, *tmp2, *x, *y; int ret = 0; - /* clear error queue */ - ERR_clear_error(); - if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -98,19 +101,24 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, goto err; } + ERR_set_mark(); if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) { +#ifndef FIPS_MODULE unsigned long err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { - ERR_clear_error(); - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, - EC_R_INVALID_COMPRESSED_POINT); + ERR_pop_to_mark(); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT); } else - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, - ERR_R_BN_LIB); +#endif + { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + } goto err; } + ERR_clear_last_mark(); if (y_bit != BN_is_odd(y)) { if (BN_is_zero(y)) { @@ -121,22 +129,19 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, goto err; if (kron == 1) - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, - EC_R_INVALID_COMPRESSION_BIT); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSION_BIT); else /* * 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); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT); goto err; } if (!BN_usub(y, group->field, y)) goto err; } if (y_bit != BN_is_odd(y)) { - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, - ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -151,9 +156,9 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, return ret; } -size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, - point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx) +size_t ossl_ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) { size_t ret; BN_CTX *new_ctx = NULL; @@ -164,7 +169,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); goto err; } @@ -172,7 +177,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, /* encodes to a single 0 octet */ if (buf != NULL) { if (len < 1) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } buf[0] = 0; @@ -189,12 +194,12 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, /* if 'buf' is NULL, just return required length */ if (buf != NULL) { if (len < ret) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); goto err; } if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -219,7 +224,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, skip = field_len - BN_num_bytes(x); if (skip > field_len) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { @@ -229,7 +234,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, skip = BN_bn2bin(x, buf + i); i += skip; if (i != 1 + field_len) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -237,7 +242,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, || form == POINT_CONVERSION_HYBRID) { skip = field_len - BN_num_bytes(y); if (skip > field_len) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } while (skip > 0) { @@ -249,7 +254,7 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, } if (i != ret) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } } @@ -266,8 +271,9 @@ size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, return 0; } -int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, - const unsigned char *buf, size_t len, BN_CTX *ctx) +int ossl_ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, + const unsigned char *buf, size_t len, + BN_CTX *ctx) { point_conversion_form_t form; int y_bit; @@ -277,7 +283,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, int ret = 0; if (len == 0) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } form = buf[0]; @@ -286,17 +292,17 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED) && (form != POINT_CONVERSION_HYBRID)) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } if (form == 0) { if (len != 1) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } @@ -309,12 +315,12 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; if (len != enc_len) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -328,7 +334,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!BN_bin2bn(buf + 1, field_len, x)) goto err; if (BN_ucmp(x, group->field) >= 0) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } @@ -339,12 +345,12 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; if (BN_ucmp(y, group->field) >= 0) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } if (form == POINT_CONVERSION_HYBRID) { if (y_bit != BN_is_odd(y)) { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); goto err; } } diff --git a/crypto/ec/ecp_ppc.c b/crypto/ec/ecp_ppc.c new file mode 100644 index 000000000000..b2b9f772b87b --- /dev/null +++ b/crypto/ec/ecp_ppc.c @@ -0,0 +1,34 @@ +/* + * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#include "internal/cryptlib.h" +#include "crypto/ppc_arch.h" +#include "ec_local.h" + +void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4], + const unsigned long b[4]); + +void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]); +void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]) +{ + static const unsigned long RR[] = { 0x0000000000000003U, + 0xfffffffbffffffffU, + 0xfffffffffffffffeU, + 0x00000004fffffffdU }; + + ecp_nistz256_mul_mont(res, in, RR); +} + +void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]); +void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]) +{ + static const unsigned long one[] = { 1, 0, 0, 0 }; + + ecp_nistz256_mul_mont(res, in, one); +} diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c new file mode 100644 index 000000000000..0c10196ea34e --- /dev/null +++ b/crypto/ec/ecp_s390x_nistp.c @@ -0,0 +1,400 @@ +/* + * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +/* + * EC_METHOD low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include <stdlib.h> +#include <string.h> +#include <openssl/err.h> +#include <openssl/rand.h> +#include "ec_local.h" +#include "s390x_arch.h" + +/* Size of parameter blocks */ +#define S390X_SIZE_PARAM 4096 + +/* Size of fields in parameter blocks */ +#define S390X_SIZE_P256 32 +#define S390X_SIZE_P384 48 +#define S390X_SIZE_P521 80 + +/* Offsets of fields in PCC parameter blocks */ +#define S390X_OFF_RES_X(n) (0 * n) +#define S390X_OFF_RES_Y(n) (1 * n) +#define S390X_OFF_SRC_X(n) (2 * n) +#define S390X_OFF_SRC_Y(n) (3 * n) +#define S390X_OFF_SCALAR(n) (4 * n) + +/* Offsets of fields in KDSA parameter blocks */ +#define S390X_OFF_R(n) (0 * n) +#define S390X_OFF_S(n) (1 * n) +#define S390X_OFF_H(n) (2 * n) +#define S390X_OFF_K(n) (3 * n) +#define S390X_OFF_X(n) (3 * n) +#define S390X_OFF_RN(n) (4 * n) +#define S390X_OFF_Y(n) (4 * n) + +static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, + size_t num, const EC_POINT *points[], + const BIGNUM *scalars[], + BN_CTX *ctx, unsigned int fc, int len) +{ + unsigned char param[S390X_SIZE_PARAM]; + BIGNUM *x, *y; + const EC_POINT *point_ptr = NULL; + const BIGNUM *scalar_ptr = NULL; + BN_CTX *new_ctx = NULL; + int rc = -1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new_ex(group->libctx); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (x == NULL || y == NULL) { + rc = 0; + goto ret; + } + + /* + * Use PCC for EC keygen and ECDH key derivation: + * scalar * generator and scalar * peer public key, + * scalar in [0,order). + */ + if ((scalar != NULL && num == 0 && BN_is_negative(scalar) == 0) + || (scalar == NULL && num == 1 && BN_is_negative(scalars[0]) == 0)) { + + if (num == 0) { + point_ptr = EC_GROUP_get0_generator(group); + scalar_ptr = scalar; + } else { + point_ptr = points[0]; + scalar_ptr = scalars[0]; + } + + if (EC_POINT_is_at_infinity(group, point_ptr) == 1 + || BN_is_zero(scalar_ptr)) { + rc = EC_POINT_set_to_infinity(group, r); + goto ret; + } + + memset(¶m, 0, sizeof(param)); + + if (group->meth->point_get_affine_coordinates(group, point_ptr, + x, y, ctx) != 1 + || BN_bn2binpad(x, param + S390X_OFF_SRC_X(len), len) == -1 + || BN_bn2binpad(y, param + S390X_OFF_SRC_Y(len), len) == -1 + || BN_bn2binpad(scalar_ptr, + param + S390X_OFF_SCALAR(len), len) == -1 + || s390x_pcc(fc, param) != 0 + || BN_bin2bn(param + S390X_OFF_RES_X(len), len, x) == NULL + || BN_bin2bn(param + S390X_OFF_RES_Y(len), len, y) == NULL + || group->meth->point_set_affine_coordinates(group, r, + x, y, ctx) != 1) + goto ret; + + rc = 1; + } + +ret: + /* Otherwise use default. */ + if (rc == -1) + rc = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + OPENSSL_cleanse(param, sizeof(param)); + BN_CTX_end(ctx); + BN_CTX_free(new_ctx); + return rc; +} + +static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst, + int dgstlen, + const BIGNUM *kinv, + const BIGNUM *r, + EC_KEY *eckey, + unsigned int fc, int len) +{ + unsigned char param[S390X_SIZE_PARAM]; + int ok = 0; + BIGNUM *k; + ECDSA_SIG *sig; + const EC_GROUP *group; + const BIGNUM *privkey; + int off; + + group = EC_KEY_get0_group(eckey); + privkey = EC_KEY_get0_private_key(eckey); + if (group == NULL || privkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); + return NULL; + } + + if (!EC_KEY_can_sign(eckey)) { + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return NULL; + } + + k = BN_secure_new(); + sig = ECDSA_SIG_new(); + if (k == NULL || sig == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto ret; + } + + sig->r = BN_new(); + sig->s = BN_new(); + if (sig->r == NULL || sig->s == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto ret; + } + + memset(param, 0, sizeof(param)); + off = len - (dgstlen > len ? len : dgstlen); + memcpy(param + S390X_OFF_H(len) + off, dgst, len - off); + + if (BN_bn2binpad(privkey, param + S390X_OFF_K(len), len) == -1) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto ret; + } + + if (r == NULL || kinv == NULL) { + if (len < 0) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_LENGTH); + goto ret; + } + /* + * Generate random k and copy to param param block. RAND_priv_bytes_ex + * is used instead of BN_priv_rand_range or BN_generate_dsa_nonce + * because kdsa instruction constructs an in-range, invertible nonce + * internally implementing counter-measures for RNG weakness. + */ + if (RAND_priv_bytes_ex(eckey->libctx, param + S390X_OFF_RN(len), + (size_t)len, 0) != 1) { + ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); + goto ret; + } + } else { + /* Reconstruct k = (k^-1)^-1. */ + if (ossl_ec_group_do_inverse_ord(group, k, kinv, NULL) == 0 + || BN_bn2binpad(k, param + S390X_OFF_RN(len), len) == -1) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto ret; + } + /* Turns KDSA internal nonce-generation off. */ + fc |= S390X_KDSA_D; + } + + if (s390x_kdsa(fc, param, NULL, 0) != 0) { + ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); + goto ret; + } + + if (BN_bin2bn(param + S390X_OFF_R(len), len, sig->r) == NULL + || BN_bin2bn(param + S390X_OFF_S(len), len, sig->s) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto ret; + } + + ok = 1; +ret: + OPENSSL_cleanse(param, sizeof(param)); + if (ok != 1) { + ECDSA_SIG_free(sig); + sig = NULL; + } + BN_clear_free(k); + return sig; +} + +static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen, + const ECDSA_SIG *sig, EC_KEY *eckey, + unsigned int fc, int len) +{ + unsigned char param[S390X_SIZE_PARAM]; + int rc = -1; + BN_CTX *ctx; + BIGNUM *x, *y; + const EC_GROUP *group; + const EC_POINT *pubkey; + int off; + + group = EC_KEY_get0_group(eckey); + pubkey = EC_KEY_get0_public_key(eckey); + if (eckey == NULL || group == NULL || pubkey == NULL || sig == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); + return -1; + } + + if (!EC_KEY_can_sign(eckey)) { + ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return -1; + } + + ctx = BN_CTX_new_ex(group->libctx); + if (ctx == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return -1; + } + + BN_CTX_start(ctx); + + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (x == NULL || y == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto ret; + } + + memset(param, 0, sizeof(param)); + off = len - (dgstlen > len ? len : dgstlen); + memcpy(param + S390X_OFF_H(len) + off, dgst, len - off); + + if (group->meth->point_get_affine_coordinates(group, pubkey, + x, y, ctx) != 1 + || BN_bn2binpad(sig->r, param + S390X_OFF_R(len), len) == -1 + || BN_bn2binpad(sig->s, param + S390X_OFF_S(len), len) == -1 + || BN_bn2binpad(x, param + S390X_OFF_X(len), len) == -1 + || BN_bn2binpad(y, param + S390X_OFF_Y(len), len) == -1) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto ret; + } + + rc = s390x_kdsa(fc, param, NULL, 0) == 0 ? 1 : 0; +ret: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return rc; +} + +#define EC_GFP_S390X_NISTP_METHOD(bits) \ + \ +static int ec_GFp_s390x_nistp##bits##_mul(const EC_GROUP *group, \ + EC_POINT *r, \ + const BIGNUM *scalar, \ + size_t num, \ + const EC_POINT *points[], \ + const BIGNUM *scalars[], \ + BN_CTX *ctx) \ +{ \ + return ec_GFp_s390x_nistp_mul(group, r, scalar, num, points, \ + scalars, ctx, \ + S390X_SCALAR_MULTIPLY_P##bits, \ + S390X_SIZE_P##bits); \ +} \ + \ +static ECDSA_SIG *ecdsa_s390x_nistp##bits##_sign_sig(const unsigned \ + char *dgst, \ + int dgstlen, \ + const BIGNUM *kinv,\ + const BIGNUM *r, \ + EC_KEY *eckey) \ +{ \ + return ecdsa_s390x_nistp_sign_sig(dgst, dgstlen, kinv, r, eckey, \ + S390X_ECDSA_SIGN_P##bits, \ + S390X_SIZE_P##bits); \ +} \ + \ +static int ecdsa_s390x_nistp##bits##_verify_sig(const \ + unsigned char *dgst, \ + int dgstlen, \ + const ECDSA_SIG *sig, \ + EC_KEY *eckey) \ +{ \ + return ecdsa_s390x_nistp_verify_sig(dgst, dgstlen, sig, eckey, \ + S390X_ECDSA_VERIFY_P##bits, \ + S390X_SIZE_P##bits); \ +} \ + \ +const EC_METHOD *EC_GFp_s390x_nistp##bits##_method(void) \ +{ \ + static const EC_METHOD EC_GFp_s390x_nistp##bits##_meth = { \ + EC_FLAGS_DEFAULT_OCT, \ + NID_X9_62_prime_field, \ + ossl_ec_GFp_simple_group_init, \ + ossl_ec_GFp_simple_group_finish, \ + ossl_ec_GFp_simple_group_clear_finish, \ + ossl_ec_GFp_simple_group_copy, \ + ossl_ec_GFp_simple_group_set_curve, \ + ossl_ec_GFp_simple_group_get_curve, \ + ossl_ec_GFp_simple_group_get_degree, \ + ossl_ec_group_simple_order_bits, \ + ossl_ec_GFp_simple_group_check_discriminant, \ + ossl_ec_GFp_simple_point_init, \ + ossl_ec_GFp_simple_point_finish, \ + ossl_ec_GFp_simple_point_clear_finish, \ + ossl_ec_GFp_simple_point_copy, \ + ossl_ec_GFp_simple_point_set_to_infinity, \ + ossl_ec_GFp_simple_point_set_affine_coordinates, \ + ossl_ec_GFp_simple_point_get_affine_coordinates, \ + NULL, /* point_set_compressed_coordinates */ \ + NULL, /* point2oct */ \ + NULL, /* oct2point */ \ + ossl_ec_GFp_simple_add, \ + ossl_ec_GFp_simple_dbl, \ + ossl_ec_GFp_simple_invert, \ + ossl_ec_GFp_simple_is_at_infinity, \ + ossl_ec_GFp_simple_is_on_curve, \ + ossl_ec_GFp_simple_cmp, \ + ossl_ec_GFp_simple_make_affine, \ + ossl_ec_GFp_simple_points_make_affine, \ + ec_GFp_s390x_nistp##bits##_mul, \ + NULL, /* precompute_mult */ \ + NULL, /* have_precompute_mult */ \ + ossl_ec_GFp_simple_field_mul, \ + ossl_ec_GFp_simple_field_sqr, \ + NULL, /* field_div */ \ + ossl_ec_GFp_simple_field_inv, \ + NULL, /* field_encode */ \ + NULL, /* field_decode */ \ + NULL, /* field_set_to_one */ \ + ossl_ec_key_simple_priv2oct, \ + ossl_ec_key_simple_oct2priv, \ + NULL, /* set_private */ \ + ossl_ec_key_simple_generate_key, \ + ossl_ec_key_simple_check_key, \ + ossl_ec_key_simple_generate_public_key, \ + NULL, /* keycopy */ \ + NULL, /* keyfinish */ \ + ossl_ecdh_simple_compute_key, \ + ossl_ecdsa_simple_sign_setup, \ + ecdsa_s390x_nistp##bits##_sign_sig, \ + ecdsa_s390x_nistp##bits##_verify_sig, \ + NULL, /* field_inverse_mod_ord */ \ + ossl_ec_GFp_simple_blind_coordinates, \ + ossl_ec_GFp_simple_ladder_pre, \ + ossl_ec_GFp_simple_ladder_step, \ + ossl_ec_GFp_simple_ladder_post \ + }; \ + static const EC_METHOD *ret; \ + \ + if ((OPENSSL_s390xcap_P.pcc[1] \ + & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P##bits)) \ + && (OPENSSL_s390xcap_P.kdsa[0] \ + & S390X_CAPBIT(S390X_ECDSA_VERIFY_P##bits)) \ + && (OPENSSL_s390xcap_P.kdsa[0] \ + & S390X_CAPBIT(S390X_ECDSA_SIGN_P##bits))) \ + ret = &EC_GFp_s390x_nistp##bits##_meth; \ + else \ + ret = EC_GFp_mont_method(); \ + \ + return ret; \ +} + +EC_GFP_S390X_NISTP_METHOD(256) +EC_GFP_S390X_NISTP_METHOD(384) +EC_GFP_S390X_NISTP_METHOD(521) diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index b3110ec89dbe..bde8cad34641 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -1,13 +1,19 @@ /* - * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2021 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 + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <openssl/err.h> #include <openssl/symhacks.h> @@ -18,57 +24,58 @@ const EC_METHOD *EC_GFp_simple_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_simple_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_simple_group_copy, - ec_GFp_simple_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_group_simple_order_bits, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, + ossl_ec_GFp_simple_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_simple_group_copy, + ossl_ec_GFp_simple_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_simple_point_get_affine_coordinates, 0, 0, 0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, 0 /* mul */ , 0 /* precompute_mult */ , 0 /* have_precompute_mult */ , - ec_GFp_simple_field_mul, - ec_GFp_simple_field_sqr, + ossl_ec_GFp_simple_field_mul, + ossl_ec_GFp_simple_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ - ec_GFp_simple_blind_coordinates, - ec_GFp_simple_ladder_pre, - ec_GFp_simple_ladder_step, - ec_GFp_simple_ladder_post + ossl_ec_GFp_simple_blind_coordinates, + ossl_ec_GFp_simple_ladder_pre, + ossl_ec_GFp_simple_ladder_step, + ossl_ec_GFp_simple_ladder_post }; return &ret; @@ -88,7 +95,7 @@ const EC_METHOD *EC_GFp_simple_method(void) * representation (i.e. 'encoding' means multiplying by some factor R). */ -int ec_GFp_simple_group_init(EC_GROUP *group) +int ossl_ec_GFp_simple_group_init(EC_GROUP *group) { group->field = BN_new(); group->a = BN_new(); @@ -103,21 +110,21 @@ int ec_GFp_simple_group_init(EC_GROUP *group) return 1; } -void ec_GFp_simple_group_finish(EC_GROUP *group) +void ossl_ec_GFp_simple_group_finish(EC_GROUP *group) { BN_free(group->field); BN_free(group->a); BN_free(group->b); } -void ec_GFp_simple_group_clear_finish(EC_GROUP *group) +void ossl_ec_GFp_simple_group_clear_finish(EC_GROUP *group) { BN_clear_free(group->field); BN_clear_free(group->a); BN_clear_free(group->b); } -int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) +int ossl_ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) { if (!BN_copy(dest->field, src->field)) return 0; @@ -131,9 +138,9 @@ int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) return 1; } -int ec_GFp_simple_group_set_curve(EC_GROUP *group, - const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *group, + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; @@ -141,12 +148,12 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, /* p must be a prime > 3 */ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { - ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -190,8 +197,8 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group, return ret; } -int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, - BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; @@ -204,7 +211,7 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, if (a != NULL || b != NULL) { if (group->meth->field_decode) { if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -235,12 +242,13 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, return ret; } -int ec_GFp_simple_group_get_degree(const EC_GROUP *group) +int ossl_ec_GFp_simple_group_get_degree(const EC_GROUP *group) { return BN_num_bits(group->field); } -int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, + BN_CTX *ctx) { int ret = 0; BIGNUM *a, *b, *order, *tmp_1, *tmp_2; @@ -248,10 +256,9 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) BN_CTX *new_ctx = NULL; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) { - ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, - ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } } @@ -312,7 +319,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) return ret; } -int ec_GFp_simple_point_init(EC_POINT *point) +int ossl_ec_GFp_simple_point_init(EC_POINT *point) { point->X = BN_new(); point->Y = BN_new(); @@ -328,14 +335,14 @@ int ec_GFp_simple_point_init(EC_POINT *point) return 1; } -void ec_GFp_simple_point_finish(EC_POINT *point) +void ossl_ec_GFp_simple_point_finish(EC_POINT *point) { BN_free(point->X); BN_free(point->Y); BN_free(point->Z); } -void ec_GFp_simple_point_clear_finish(EC_POINT *point) +void ossl_ec_GFp_simple_point_clear_finish(EC_POINT *point) { BN_clear_free(point->X); BN_clear_free(point->Y); @@ -343,7 +350,7 @@ void ec_GFp_simple_point_clear_finish(EC_POINT *point) point->Z_is_one = 0; } -int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) +int ossl_ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { if (!BN_copy(dest->X, src->X)) return 0; @@ -357,26 +364,26 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) return 1; } -int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, - EC_POINT *point) +int ossl_ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) { point->Z_is_one = 0; BN_zero(point->Z); return 1; } -int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, - EC_POINT *point, - const BIGNUM *x, - const BIGNUM *y, - const BIGNUM *z, - BN_CTX *ctx) +int ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, + BN_CTX *ctx) { BN_CTX *new_ctx = NULL; int ret = 0; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -425,17 +432,17 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, return ret; } -int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BIGNUM *z, BN_CTX *ctx) +int ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BIGNUM *z, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; int ret = 0; if (group->meth->field_decode != 0) { if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -474,17 +481,16 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, return ret; } -int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, - EC_POINT *point, - const BIGNUM *x, - const BIGNUM *y, BN_CTX *ctx) +int ossl_ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) { if (x == NULL || y == NULL) { /* * unlike for projective coordinates, we do not tolerate this */ - ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, - ERR_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -492,10 +498,10 @@ int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, BN_value_one(), ctx); } -int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *Z, *Z_1, *Z_2, *Z_3; @@ -503,13 +509,12 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, int ret = 0; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -554,8 +559,7 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, } } else { if (!group->meth->field_inv(group, Z_1, Z_, ctx)) { - ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -606,8 +610,8 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, return ret; } -int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, - const EC_POINT *b, BN_CTX *ctx) +int ossl_ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); @@ -629,7 +633,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, p = group->field; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -791,8 +795,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, return ret; } -int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, - BN_CTX *ctx) +int ossl_ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) { int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); @@ -813,7 +817,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, p = group->field; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -933,7 +937,8 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, return ret; } -int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) +int ossl_ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) { if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y)) /* point is its own inverse */ @@ -942,13 +947,14 @@ int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) return BN_usub(point->Y, group->field, point->Y); } -int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) +int ossl_ec_GFp_simple_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point) { return BN_is_zero(point->Z); } -int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, - BN_CTX *ctx) +int ossl_ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) { int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); @@ -966,7 +972,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, p = group->field; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return -1; } @@ -1050,8 +1056,8 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, return ret; } -int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, - const EC_POINT *b, BN_CTX *ctx) +int ossl_ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) { /*- * return values: @@ -1083,7 +1089,7 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, field_sqr = group->meth->field_sqr; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return -1; } @@ -1158,8 +1164,8 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, return ret; } -int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, - BN_CTX *ctx) +int ossl_ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *x, *y; @@ -1169,7 +1175,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, return 1; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -1185,7 +1191,7 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) goto err; if (!point->Z_is_one) { - ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } @@ -1197,8 +1203,8 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, return ret; } -int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, - EC_POINT *points[], BN_CTX *ctx) +int ossl_ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *tmp, *tmp_Z; @@ -1210,7 +1216,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, return 1; if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); + ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) return 0; } @@ -1266,7 +1272,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, */ if (!group->meth->field_inv(group, tmp, prod_Z[num - 1], ctx)) { - ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if (group->meth->field_encode != 0) { @@ -1356,14 +1362,14 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, return ret; } -int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) +int ossl_ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { return BN_mod_mul(r, a, b, group->field, ctx); } -int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) +int ossl_ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) { return BN_mod_sqr(r, a, group->field, ctx); } @@ -1374,14 +1380,15 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, * Since we don't have a Mont structure here, SCA hardening is with blinding. * NB: "a" must be in _decoded_ form. (i.e. field_decode must precede.) */ -int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) +int ossl_ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) { BIGNUM *e = NULL; BN_CTX *new_ctx = NULL; int ret = 0; - if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) + if (ctx == NULL + && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL) return 0; BN_CTX_start(ctx); @@ -1389,7 +1396,7 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, goto err; do { - if (!BN_priv_rand_range(e, group->field)) + if (!BN_priv_rand_range_ex(e, group->field, 0, ctx)) goto err; } while (BN_is_zero(e)); @@ -1398,7 +1405,7 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, goto err; /* r := 1/(a * e) */ if (!BN_mod_inverse(r, r, group->field, ctx)) { - ECerr(EC_F_EC_GFP_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT); + ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT); goto err; } /* r := e/(a * e) = 1/a */ @@ -1420,8 +1427,8 @@ int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, * lambda = [1,group->field) * */ -int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, - BN_CTX *ctx) +int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx) { int ret = 0; BIGNUM *lambda = NULL; @@ -1431,7 +1438,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, lambda = BN_CTX_get(ctx); temp = BN_CTX_get(ctx); if (temp == NULL) { - ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto end; } @@ -1442,7 +1449,7 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, */ do { ERR_set_mark(); - ret = BN_priv_rand_range(lambda, group->field); + ret = BN_priv_rand_range_ex(lambda, group->field, 0, ctx); ERR_pop_to_mark(); if (ret == 0) { ret = 1; @@ -1483,9 +1490,9 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, * Blinding uses the equivalence relation (\lambda X, \lambda Y, \lambda Z) * for any non-zero \lambda that holds for projective (homogeneous) coords. */ -int ec_GFp_simple_ladder_pre(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx) +int ossl_ec_GFp_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) { BIGNUM *t1, *t2, *t3, *t4, *t5 = NULL; @@ -1512,13 +1519,13 @@ int ec_GFp_simple_ladder_pre(const EC_GROUP *group, /* make sure lambda (r->Y here for storage) is not zero */ do { - if (!BN_priv_rand_range(r->Y, group->field)) + if (!BN_priv_rand_range_ex(r->Y, group->field, 0, ctx)) return 0; } while (BN_is_zero(r->Y)); /* make sure lambda (s->Z here for storage) is not zero */ do { - if (!BN_priv_rand_range(s->Z, group->field)) + if (!BN_priv_rand_range_ex(s->Z, group->field, 0, ctx)) return 0; } while (BN_is_zero(s->Z)); @@ -1553,9 +1560,9 @@ int ec_GFp_simple_ladder_pre(const EC_GROUP *group, * attacks", as described at * https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-mladd-2002-it-4 */ -int ec_GFp_simple_ladder_step(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx) +int ossl_ec_GFp_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) { int ret = 0; BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL; @@ -1641,9 +1648,9 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group, * - Y1==0 implies p has order 2, so either r or s are infinity and handled by * one of the BN_is_zero(...) branches. */ -int ec_GFp_simple_ladder_post(const EC_GROUP *group, - EC_POINT *r, EC_POINT *s, - EC_POINT *p, BN_CTX *ctx) +int ossl_ec_GFp_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) { int ret = 0; BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL; diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c new file mode 100644 index 000000000000..e42767d6bf0f --- /dev/null +++ b/crypto/ec/ecx_backend.c @@ -0,0 +1,263 @@ +/* + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#include <string.h> +#include <openssl/core_names.h> +#include <openssl/params.h> +#include <openssl/ec.h> +#include <openssl/rand.h> +#include <openssl/err.h> +#ifndef FIPS_MODULE +# include <openssl/x509.h> +#endif +#include "crypto/ecx.h" +#include "ecx_backend.h" + +/* + * The intention with the "backend" source file is to offer backend support + * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider + * implementations alike. + */ + +int ossl_ecx_public_from_private(ECX_KEY *key) +{ + switch (key->type) { + case ECX_KEY_TYPE_X25519: + ossl_x25519_public_from_private(key->pubkey, key->privkey); + break; + case ECX_KEY_TYPE_ED25519: + if (!ossl_ed25519_public_from_private(key->libctx, key->pubkey, + key->privkey, key->propq)) { + ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); + return 0; + } + break; + case ECX_KEY_TYPE_X448: + ossl_x448_public_from_private(key->pubkey, key->privkey); + break; + case ECX_KEY_TYPE_ED448: + if (!ossl_ed448_public_from_private(key->libctx, key->pubkey, + key->privkey, key->propq)) { + ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); + return 0; + } + break; + } + return 1; +} + +int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[], + int include_private) +{ + size_t privkeylen = 0, pubkeylen = 0; + const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; + unsigned char *pubkey; + + if (ecx == NULL) + return 0; + + param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (include_private) + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); + + if (param_pub_key == NULL && param_priv_key == NULL) + return 0; + + if (param_priv_key != NULL) { + if (!OSSL_PARAM_get_octet_string(param_priv_key, + (void **)&ecx->privkey, ecx->keylen, + &privkeylen)) + return 0; + if (privkeylen != ecx->keylen) { + /* + * Invalid key length. We will clear what we've received now. We + * can't leave it to ossl_ecx_key_free() because that will call + * OPENSSL_secure_clear_free() and assume the correct key length + */ + OPENSSL_secure_clear_free(ecx->privkey, privkeylen); + ecx->privkey = NULL; + return 0; + } + } + + + pubkey = ecx->pubkey; + if (param_pub_key != NULL + && !OSSL_PARAM_get_octet_string(param_pub_key, + (void **)&pubkey, + sizeof(ecx->pubkey), &pubkeylen)) + return 0; + + if ((param_pub_key != NULL && pubkeylen != ecx->keylen)) + return 0; + + if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx)) + return 0; + + ecx->haspubkey = 1; + + return 1; +} + +ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) +{ + ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + OPENSSL_free(ret); + return NULL; + } + + ret->libctx = key->libctx; + ret->haspubkey = 0; + ret->keylen = key->keylen; + ret->type = key->type; + ret->references = 1; + + if (key->propq != NULL) { + ret->propq = OPENSSL_strdup(key->propq); + if (ret->propq == NULL) + goto err; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 + && key->haspubkey == 1) { + memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); + ret->haspubkey = 1; + } + + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 + && key->privkey != NULL) { + if (ossl_ecx_key_allocate_privkey(ret) == NULL) + goto err; + memcpy(ret->privkey, key->privkey, ret->keylen); + } + + return ret; + +err: + ossl_ecx_key_free(ret); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return NULL; +} + +#ifndef FIPS_MODULE +ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, + const unsigned char *p, int plen, + int id, ecx_key_op_t op, + OSSL_LIB_CTX *libctx, const char *propq) +{ + ECX_KEY *key = NULL; + unsigned char *privkey, *pubkey; + + if (op != KEY_OP_KEYGEN) { + if (palg != NULL) { + int ptype; + + /* Algorithm parameters must be absent */ + X509_ALGOR_get0(NULL, &ptype, NULL, palg); + if (ptype != V_ASN1_UNDEF) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + return 0; + } + if (id == EVP_PKEY_NONE) + id = OBJ_obj2nid(palg->algorithm); + else if (id != OBJ_obj2nid(palg->algorithm)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + return 0; + } + } + + if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); + return 0; + } + } + + key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); + if (key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return 0; + } + pubkey = key->pubkey; + + if (op == KEY_OP_PUBLIC) { + memcpy(pubkey, p, plen); + } else { + privkey = ossl_ecx_key_allocate_privkey(key); + if (privkey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + if (op == KEY_OP_KEYGEN) { + if (id != EVP_PKEY_NONE) { + if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0) + goto err; + if (id == EVP_PKEY_X25519) { + privkey[0] &= 248; + privkey[X25519_KEYLEN - 1] &= 127; + privkey[X25519_KEYLEN - 1] |= 64; + } else if (id == EVP_PKEY_X448) { + privkey[0] &= 252; + privkey[X448_KEYLEN - 1] |= 128; + } + } + } else { + memcpy(privkey, p, KEYLENID(id)); + } + if (!ossl_ecx_public_from_private(key)) { + ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); + goto err; + } + } + + return key; + err: + ossl_ecx_key_free(key); + return NULL; +} + +ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, + OSSL_LIB_CTX *libctx, const char *propq) +{ + ECX_KEY *ecx = NULL; + const unsigned char *p; + int plen; + ASN1_OCTET_STRING *oct = NULL; + const X509_ALGOR *palg; + + if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) + return 0; + + oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); + if (oct == NULL) { + p = NULL; + plen = 0; + } else { + p = ASN1_STRING_get0_data(oct); + plen = ASN1_STRING_length(oct); + } + + /* + * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type + * on its own. + */ + ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, + libctx, propq); + ASN1_OCTET_STRING_free(oct); + return ecx; +} +#endif diff --git a/crypto/ec/ecx_backend.h b/crypto/ec/ecx_backend.h new file mode 100644 index 000000000000..2c01294789b3 --- /dev/null +++ b/crypto/ec/ecx_backend.h @@ -0,0 +1,20 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#define ISX448(id) ((id) == EVP_PKEY_X448) +#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519) +#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \ + : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \ + : ED448_KEYLEN)) +#define KEYNID2TYPE(id) \ + (IS25519(id) ? ((id) == EVP_PKEY_X25519 ? ECX_KEY_TYPE_X25519 \ + : ECX_KEY_TYPE_ED25519) \ + : ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \ + : ECX_KEY_TYPE_ED448)) +#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id) diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c new file mode 100644 index 000000000000..dcec26c2e9b3 --- /dev/null +++ b/crypto/ec/ecx_key.c @@ -0,0 +1,98 @@ +/* + * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#include <string.h> +#include <openssl/err.h> +#include "crypto/ecx.h" + +ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey, + const char *propq) +{ + ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) + return NULL; + + ret->libctx = libctx; + ret->haspubkey = haspubkey; + switch (type) { + case ECX_KEY_TYPE_X25519: + ret->keylen = X25519_KEYLEN; + break; + case ECX_KEY_TYPE_X448: + ret->keylen = X448_KEYLEN; + break; + case ECX_KEY_TYPE_ED25519: + ret->keylen = ED25519_KEYLEN; + break; + case ECX_KEY_TYPE_ED448: + ret->keylen = ED448_KEYLEN; + break; + } + ret->type = type; + ret->references = 1; + + if (propq != NULL) { + ret->propq = OPENSSL_strdup(propq); + if (ret->propq == NULL) + goto err; + } + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) + goto err; + return ret; +err: + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; +} + +void ossl_ecx_key_free(ECX_KEY *key) +{ + int i; + + if (key == NULL) + return; + + CRYPTO_DOWN_REF(&key->references, &i, key->lock); + REF_PRINT_COUNT("ECX_KEY", key); + if (i > 0) + return; + REF_ASSERT_ISNT(i < 0); + + OPENSSL_free(key->propq); + OPENSSL_secure_clear_free(key->privkey, key->keylen); + CRYPTO_THREAD_lock_free(key->lock); + OPENSSL_free(key); +} + +void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx) +{ + key->libctx = libctx; +} + +int ossl_ecx_key_up_ref(ECX_KEY *key) +{ + int i; + + if (CRYPTO_UP_REF(&key->references, &i, key->lock) <= 0) + return 0; + + REF_PRINT_COUNT("ECX_KEY", key); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + +unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key) +{ + key->privkey = OPENSSL_secure_zalloc(key->keylen); + + return key->privkey; +} diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index 9dc5259e4afc..c97dc472ac57 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -1,126 +1,32 @@ /* - * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (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 */ +/* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include <stdio.h> -#include "internal/cryptlib.h" #include <openssl/x509.h> #include <openssl/ec.h> +#include <openssl/core_names.h> +#include <openssl/param_build.h> #include <openssl/rand.h> +#include "internal/cryptlib.h" +#include "internal/provider.h" #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/ecx.h" #include "ec_local.h" #include "curve448/curve448_local.h" - -#define X25519_BITS 253 -#define X25519_SECURITY_BITS 128 - -#define ED25519_SIGSIZE 64 - -#define X448_BITS 448 -#define ED448_BITS 456 -#define X448_SECURITY_BITS 224 - -#define ED448_SIGSIZE 114 - -#define ISX448(id) ((id) == EVP_PKEY_X448) -#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519) -#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \ - : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \ - : ED448_KEYLEN)) -#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id) - - -typedef enum { - KEY_OP_PUBLIC, - KEY_OP_PRIVATE, - KEY_OP_KEYGEN -} ecx_key_op_t; - -/* Setup EVP_PKEY using public, private or generation */ -static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg, - const unsigned char *p, int plen, ecx_key_op_t op) -{ - ECX_KEY *key = NULL; - unsigned char *privkey, *pubkey; - - if (op != KEY_OP_KEYGEN) { - if (palg != NULL) { - int ptype; - - /* Algorithm parameters must be absent */ - X509_ALGOR_get0(NULL, &ptype, NULL, palg); - if (ptype != V_ASN1_UNDEF) { - ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); - return 0; - } - } - - if (p == NULL || plen != KEYLENID(id)) { - ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING); - return 0; - } - } - - key = OPENSSL_zalloc(sizeof(*key)); - if (key == NULL) { - ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); - return 0; - } - pubkey = key->pubkey; - - if (op == KEY_OP_PUBLIC) { - memcpy(pubkey, p, plen); - } else { - privkey = key->privkey = OPENSSL_secure_malloc(KEYLENID(id)); - if (privkey == NULL) { - ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE); - goto err; - } - if (op == KEY_OP_KEYGEN) { - if (RAND_priv_bytes(privkey, KEYLENID(id)) <= 0) { - OPENSSL_secure_free(privkey); - key->privkey = NULL; - goto err; - } - if (id == EVP_PKEY_X25519) { - privkey[0] &= 248; - privkey[X25519_KEYLEN - 1] &= 127; - privkey[X25519_KEYLEN - 1] |= 64; - } else if (id == EVP_PKEY_X448) { - privkey[0] &= 252; - privkey[X448_KEYLEN - 1] |= 128; - } - } else { - memcpy(privkey, p, KEYLENID(id)); - } - switch (id) { - case EVP_PKEY_X25519: - X25519_public_from_private(pubkey, privkey); - break; - case EVP_PKEY_ED25519: - ED25519_public_from_private(pubkey, privkey); - break; - case EVP_PKEY_X448: - X448_public_from_private(pubkey, privkey); - break; - case EVP_PKEY_ED448: - ED448_public_from_private(pubkey, privkey); - break; - } - } - - EVP_PKEY_assign(pkey, id, key); - return 1; - err: - OPENSSL_free(key); - return 0; -} +#include "ecx_backend.h" static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { @@ -128,35 +34,42 @@ static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) unsigned char *penc; if (ecxkey == NULL) { - ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); return 0; } penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey)); if (penc == NULL) { - ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id), V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) { OPENSSL_free(penc); - ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } return 1; } -static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) { const unsigned char *p; int pklen; X509_ALGOR *palg; + ECX_KEY *ecx; + int ret = 0; if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) return 0; - return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen, - KEY_OP_PUBLIC); + ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id, + KEY_OP_PUBLIC, NULL, NULL); + if (ecx != NULL) { + ret = 1; + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx); + } + return ret; } static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) @@ -170,29 +83,18 @@ static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0; } -static int ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) +static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8, + OSSL_LIB_CTX *libctx, const char *propq) { - const unsigned char *p; - int plen; - ASN1_OCTET_STRING *oct = NULL; - const X509_ALGOR *palg; - int rv; + int ret = 0; + ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq); - if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8)) - return 0; - - oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); - if (oct == NULL) { - p = NULL; - plen = 0; - } else { - p = ASN1_STRING_get0_data(oct); - plen = ASN1_STRING_length(oct); + if (ecx != NULL) { + ret = 1; + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx); } - rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE); - ASN1_STRING_clear_free(oct); - return rv; + return ret; } static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) @@ -203,7 +105,7 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) int penclen; if (ecxkey == NULL || ecxkey->privkey == NULL) { - ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); return 0; } @@ -213,14 +115,14 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) penclen = i2d_ASN1_OCTET_STRING(&oct, &penc); if (penclen < 0) { - ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 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); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return 0; } @@ -254,9 +156,7 @@ static int ecx_security_bits(const EVP_PKEY *pkey) static void ecx_free(EVP_PKEY *pkey) { - if (pkey->pkey.ecx != NULL) - OPENSSL_secure_clear_free(pkey->pkey.ecx->privkey, KEYLEN(pkey)); - OPENSSL_free(pkey->pkey.ecx); + ossl_ecx_key_free(pkey->pkey.ecx); } /* "parameters" are always equal */ @@ -318,10 +218,16 @@ 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, pkey->ameth->pkey_id, NULL, arg2, arg1, - KEY_OP_PUBLIC); + case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: { + ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id, + KEY_OP_PUBLIC, NULL, NULL); + if (ecx != NULL) { + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx); + return 1; + } + return 0; + } case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: if (pkey->pkey.ecx != NULL) { unsigned char **ppt = arg2; @@ -355,14 +261,38 @@ static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, size_t len) { - return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len, - KEY_OP_PRIVATE); + OSSL_LIB_CTX *libctx = NULL; + ECX_KEY *ecx = NULL; + + if (pkey->keymgmt != NULL) + libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt)); + + ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id, + KEY_OP_PRIVATE, libctx, NULL); + + if (ecx != NULL) { + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx); + return 1; + } + return 0; } static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len) { - return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len, - KEY_OP_PUBLIC); + OSSL_LIB_CTX *libctx = NULL; + ECX_KEY *ecx = NULL; + + if (pkey->keymgmt != NULL) + libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt)); + + ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id, + KEY_OP_PUBLIC, libctx, NULL); + + if (ecx != NULL) { + EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx); + return 1; + } + return 0; } static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, @@ -406,7 +336,97 @@ static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub, return 1; } -const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { +static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey) +{ + /* + * We provide no mechanism to "update" an ECX key once it has been set, + * therefore we do not have to maintain a dirty count. + */ + return 1; +} + +static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata, + OSSL_FUNC_keymgmt_import_fn *importer, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const ECX_KEY *key = from->pkey.ecx; + OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new(); + OSSL_PARAM *params = NULL; + int selection = 0; + int rv = 0; + + if (tmpl == NULL) + return 0; + + /* A key must at least have a public part */ + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY, + key->pubkey, key->keylen)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + + if (key->privkey != NULL) { + if (!OSSL_PARAM_BLD_push_octet_string(tmpl, + OSSL_PKEY_PARAM_PRIV_KEY, + key->privkey, key->keylen)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; + } + + params = OSSL_PARAM_BLD_to_param(tmpl); + + /* We export, the provider imports */ + rv = importer(to_keydata, selection, params); + + err: + OSSL_PARAM_BLD_free(tmpl); + OSSL_PARAM_free(params); + return rv; +} + +static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx, + int keytype) +{ + EVP_PKEY_CTX *pctx = vpctx; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0, + pctx->propquery); + + if (ecx == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!ossl_ecx_key_fromdata(ecx, params, 1) + || !EVP_PKEY_assign(pkey, keytype, ecx)) { + ossl_ecx_key_free(ecx); + return 0; + } + return 1; +} + +static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) +{ + ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL; + int ret; + + if (ecx != NULL) { + dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL); + if (dupkey == NULL) + return 0; + } + + ret = EVP_PKEY_assign(to, from->type, dupkey); + if (!ret) + ossl_ecx_key_free(dupkey); + return ret; +} + +static int x25519_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519); +} + +const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = { EVP_PKEY_X25519, EVP_PKEY_X25519, 0, @@ -418,7 +438,7 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { ecx_pub_cmp, ecx_pub_print, - ecx_priv_decode, + NULL, ecx_priv_encode, ecx_priv_print, @@ -447,9 +467,20 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + x25519_import_from, + ecx_pkey_copy, + + ecx_priv_decode_ex }; -const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { +static int x448_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448); +} + +const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = { EVP_PKEY_X448, EVP_PKEY_X448, 0, @@ -461,7 +492,7 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { ecx_pub_cmp, ecx_pub_print, - ecx_priv_decode, + NULL, ecx_priv_encode, ecx_priv_print, @@ -490,6 +521,12 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + x448_import_from, + ecx_pkey_copy, + + ecx_priv_decode_ex }; static int ecd_size25519(const EVP_PKEY *pkey) @@ -502,9 +539,9 @@ static int ecd_size448(const EVP_PKEY *pkey) return ED448_SIGSIZE; } -static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, - X509_ALGOR *sigalg, ASN1_BIT_STRING *str, - EVP_PKEY *pkey) +static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, + const void *asn, const X509_ALGOR *sigalg, + const ASN1_BIT_STRING *str, EVP_PKEY *pkey) { const ASN1_OBJECT *obj; int ptype; @@ -514,7 +551,7 @@ static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR_get0(&obj, &ptype, NULL, sigalg); nid = OBJ_obj2nid(obj); if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) { - ECerr(EC_F_ECD_ITEM_VERIFY, EC_R_INVALID_ENCODING); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); return 0; } @@ -524,7 +561,8 @@ static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, return 2; } -static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, +static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it, + const void *asn, X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *str) { @@ -544,7 +582,8 @@ static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg, return 1; } -static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, +static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, + const void *asn, X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *str) { @@ -564,8 +603,12 @@ static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg, return 1; } +static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519); +} -const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { +const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = { EVP_PKEY_ED25519, EVP_PKEY_ED25519, 0, @@ -577,7 +620,7 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { ecx_pub_cmp, ecx_pub_print, - ecx_priv_decode, + NULL, ecx_priv_encode, ecx_priv_print, @@ -605,9 +648,20 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + ed25519_import_from, + ecx_pkey_copy, + + ecx_priv_decode_ex }; -const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { +static int ed448_import_from(const OSSL_PARAM params[], void *vpctx) +{ + return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448); +} + +const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = { EVP_PKEY_ED448, EVP_PKEY_ED448, 0, @@ -619,7 +673,7 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { ecx_pub_cmp, ecx_pub_print, - ecx_priv_decode, + NULL, ecx_priv_encode, ecx_priv_print, @@ -647,11 +701,24 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to, + ed448_import_from, + ecx_pkey_copy, + + ecx_priv_decode_ex }; static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { - return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN); + ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id, + KEY_OP_KEYGEN, NULL, NULL); + + if (ecx != NULL) { + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx); + return 1; + } + return 0; } static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key, @@ -662,17 +729,17 @@ static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key, const ECX_KEY *ecxkey, *peerkey; if (ctx->pkey == NULL || ctx->peerkey == NULL) { - ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_KEYS_NOT_SET); + ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET); return 0; } - ecxkey = ctx->pkey->pkey.ecx; - peerkey = ctx->peerkey->pkey.ecx; + ecxkey = evp_pkey_get_legacy(ctx->pkey); + peerkey = evp_pkey_get_legacy(ctx->peerkey); if (ecxkey == NULL || ecxkey->privkey == NULL) { - ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); return 0; } if (peerkey == NULL) { - ECerr(EC_F_VALIDATE_ECX_DERIVE, EC_R_INVALID_PEER_KEY); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY); return 0; } *privkey = ecxkey->privkey; @@ -688,7 +755,7 @@ static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key, if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) || (key != NULL - && X25519(key, privkey, pubkey) == 0)) + && ossl_x25519(key, privkey, pubkey) == 0)) return 0; *keylen = X25519_KEYLEN; return 1; @@ -701,7 +768,7 @@ static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key, if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) || (key != NULL - && X448(key, privkey, pubkey) == 0)) + && ossl_x448(key, privkey, pubkey) == 0)) return 0; *keylen = X448_KEYLEN; return 1; @@ -715,7 +782,7 @@ static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return -2; } -const EVP_PKEY_METHOD ecx25519_pkey_meth = { +static const EVP_PKEY_METHOD ecx25519_pkey_meth = { EVP_PKEY_X25519, 0, 0, 0, 0, 0, 0, 0, pkey_ecx_keygen, @@ -725,7 +792,7 @@ const EVP_PKEY_METHOD ecx25519_pkey_meth = { 0 }; -const EVP_PKEY_METHOD ecx448_pkey_meth = { +static const EVP_PKEY_METHOD ecx448_pkey_meth = { EVP_PKEY_X448, 0, 0, 0, 0, 0, 0, 0, pkey_ecx_keygen, @@ -739,18 +806,24 @@ static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } if (sig == NULL) { *siglen = ED25519_SIGSIZE; return 1; } if (*siglen < ED25519_SIGSIZE) { - ECerr(EC_F_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } - if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0) + if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL, + NULL) == 0) return 0; *siglen = ED25519_SIGSIZE; return 1; @@ -760,19 +833,24 @@ static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } if (sig == NULL) { *siglen = ED448_SIGSIZE; return 1; } if (*siglen < ED448_SIGSIZE) { - ECerr(EC_F_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL); + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); return 0; } - if (ED448_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL, - 0) == 0) + if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey, + edkey->privkey, NULL, 0, edkey->propq) == 0) return 0; *siglen = ED448_SIGSIZE; return 1; @@ -782,24 +860,36 @@ static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { - const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } if (siglen != ED25519_SIGSIZE) return 0; - return ED25519_verify(tbs, tbslen, sig, edkey->pubkey); + return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey, + edkey->libctx, edkey->propq); } static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { - const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } if (siglen != ED448_SIGSIZE) return 0; - return ED448_verify(tbs, tbslen, sig, edkey->pubkey, NULL, 0); + return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey, + NULL, 0, edkey->propq); } static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) @@ -809,7 +899,7 @@ static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) /* Only NULL allowed as digest */ if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null()) return 1; - ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE); return 0; case EVP_PKEY_CTRL_DIGESTINIT: @@ -818,7 +908,7 @@ static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return -2; } -const EVP_PKEY_METHOD ed25519_pkey_meth = { +static const EVP_PKEY_METHOD ed25519_pkey_meth = { EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM, 0, 0, 0, 0, 0, 0, pkey_ecx_keygen, @@ -829,7 +919,7 @@ const EVP_PKEY_METHOD ed25519_pkey_meth = { pkey_ecd_digestverify25519 }; -const EVP_PKEY_METHOD ed448_pkey_meth = { +static const EVP_PKEY_METHOD ed448_pkey_meth = { EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM, 0, 0, 0, 0, 0, 0, pkey_ecx_keygen, @@ -839,3 +929,496 @@ const EVP_PKEY_METHOD ed448_pkey_meth = { pkey_ecd_digestsign448, pkey_ecd_digestverify448 }; + +#ifdef S390X_EC_ASM +# include "s390x_arch.h" + +static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + static const unsigned char generator[] = { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1, + ctx->propquery); + unsigned char *privkey = NULL, *pubkey; + + if (key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + pubkey = key->pubkey; + + privkey = ossl_ecx_key_allocate_privkey(key); + if (privkey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0) + goto err; + + privkey[0] &= 248; + privkey[31] &= 127; + privkey[31] |= 64; + + if (s390x_x25519_mul(pubkey, generator, privkey) != 1) + goto err; + + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key); + return 1; + err: + ossl_ecx_key_free(key); + return 0; +} + +static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + static const unsigned char generator[] = { + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1, + ctx->propquery); + unsigned char *privkey = NULL, *pubkey; + + if (key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + pubkey = key->pubkey; + + privkey = ossl_ecx_key_allocate_privkey(key); + if (privkey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0) + goto err; + + privkey[0] &= 252; + privkey[55] |= 128; + + if (s390x_x448_mul(pubkey, generator, privkey) != 1) + goto err; + + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key); + return 1; + err: + ossl_ecx_key_free(key); + return 0; +} + +static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + static const unsigned char generator_x[] = { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, + 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 + }; + static const unsigned char generator_y[] = { + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + }; + unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH]; + ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1, + ctx->propquery); + unsigned char *privkey = NULL, *pubkey; + unsigned int sz; + EVP_MD *md = NULL; + int rv; + + if (key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + pubkey = key->pubkey; + + privkey = ossl_ecx_key_allocate_privkey(key); + if (privkey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0) + goto err; + + md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery); + if (md == NULL) + goto err; + + rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL); + EVP_MD_free(md); + if (!rv) + goto err; + + buff[0] &= 248; + buff[31] &= 63; + buff[31] |= 64; + + if (s390x_ed25519_mul(x_dst, pubkey, + generator_x, generator_y, buff) != 1) + goto err; + + pubkey[31] |= ((x_dst[0] & 0x01) << 7); + + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key); + return 1; + err: + ossl_ecx_key_free(key); + return 0; +} + +static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) +{ + static const unsigned char generator_x[] = { + 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b, + 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, + 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47, + 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, + 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00 + }; + static const unsigned char generator_y[] = { + 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e, + 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, + 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c, + 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, + 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00 + }; + unsigned char x_dst[57], buff[114]; + ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1, + ctx->propquery); + unsigned char *privkey = NULL, *pubkey; + EVP_MD_CTX *hashctx = NULL; + EVP_MD *md = NULL; + int rv; + + if (key == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + pubkey = key->pubkey; + + privkey = ossl_ecx_key_allocate_privkey(key); + if (privkey == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0) + goto err; + + hashctx = EVP_MD_CTX_new(); + if (hashctx == NULL) + goto err; + + md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery); + if (md == NULL) + goto err; + + rv = EVP_DigestInit_ex(hashctx, md, NULL); + EVP_MD_free(md); + if (rv != 1) + goto err; + + if (EVP_DigestUpdate(hashctx, privkey, 57) != 1) + goto err; + if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1) + goto err; + + buff[0] &= -4; + buff[55] |= 0x80; + buff[56] = 0; + + if (s390x_ed448_mul(x_dst, pubkey, + generator_x, generator_y, buff) != 1) + goto err; + + pubkey[56] |= ((x_dst[0] & 0x01) << 7); + + EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key); + EVP_MD_CTX_free(hashctx); + return 1; + err: + ossl_ecx_key_free(key); + EVP_MD_CTX_free(hashctx); + return 0; +} + +static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + const unsigned char *privkey, *pubkey; + + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && s390x_x25519_mul(key, privkey, pubkey) == 0)) + return 0; + *keylen = X25519_KEYLEN; + return 1; +} + +static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + const unsigned char *privkey, *pubkey; + + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && s390x_x448_mul(key, pubkey, privkey) == 0)) + return 0; + *keylen = X448_KEYLEN; + return 1; +} + +static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen) +{ + union { + struct { + unsigned char sig[64]; + unsigned char priv[32]; + } ed25519; + unsigned long long buff[512]; + } param; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + int rc; + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } + + if (sig == NULL) { + *siglen = ED25519_SIGSIZE; + return 1; + } + + if (*siglen < ED25519_SIGSIZE) { + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + memset(¶m, 0, sizeof(param)); + memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv)); + + rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen); + OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv)); + if (rc != 0) + return 0; + + s390x_flip_endian32(sig, param.ed25519.sig); + s390x_flip_endian32(sig + 32, param.ed25519.sig + 32); + + *siglen = ED25519_SIGSIZE; + return 1; +} + +static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen) +{ + union { + struct { + unsigned char sig[128]; + unsigned char priv[64]; + } ed448; + unsigned long long buff[512]; + } param; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + int rc; + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } + + if (sig == NULL) { + *siglen = ED448_SIGSIZE; + return 1; + } + + if (*siglen < ED448_SIGSIZE) { + ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + memset(¶m, 0, sizeof(param)); + memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57); + + rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen); + OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv)); + if (rc != 0) + return 0; + + s390x_flip_endian64(param.ed448.sig, param.ed448.sig); + s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64); + memcpy(sig, param.ed448.sig, 57); + memcpy(sig + 57, param.ed448.sig + 64, 57); + + *siglen = ED448_SIGSIZE; + return 1; +} + +static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen) +{ + union { + struct { + unsigned char sig[64]; + unsigned char pub[32]; + } ed25519; + unsigned long long buff[512]; + } param; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } + + if (siglen != ED25519_SIGSIZE) + return 0; + + memset(¶m, 0, sizeof(param)); + s390x_flip_endian32(param.ed25519.sig, sig); + s390x_flip_endian32(param.ed25519.sig + 32, sig + 32); + s390x_flip_endian32(param.ed25519.pub, edkey->pubkey); + + return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519, + ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0; +} + +static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen) +{ + union { + struct { + unsigned char sig[128]; + unsigned char pub[64]; + } ed448; + unsigned long long buff[512]; + } param; + const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey); + + if (edkey == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY); + return 0; + } + + if (siglen != ED448_SIGSIZE) + return 0; + + memset(¶m, 0, sizeof(param)); + memcpy(param.ed448.sig, sig, 57); + s390x_flip_endian64(param.ed448.sig, param.ed448.sig); + memcpy(param.ed448.sig + 64, sig + 57, 57); + s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64); + memcpy(param.ed448.pub, edkey->pubkey, 57); + s390x_flip_endian64(param.ed448.pub, param.ed448.pub); + + return s390x_kdsa(S390X_EDDSA_VERIFY_ED448, + ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0; +} + +static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = { + EVP_PKEY_X25519, + 0, 0, 0, 0, 0, 0, 0, + s390x_pkey_ecx_keygen25519, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + s390x_pkey_ecx_derive25519, + pkey_ecx_ctrl, + 0 +}; + +static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = { + EVP_PKEY_X448, + 0, 0, 0, 0, 0, 0, 0, + s390x_pkey_ecx_keygen448, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + s390x_pkey_ecx_derive448, + pkey_ecx_ctrl, + 0 +}; +static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = { + EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM, + 0, 0, 0, 0, 0, 0, + s390x_pkey_ecd_keygen25519, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecd_ctrl, + 0, + s390x_pkey_ecd_digestsign25519, + s390x_pkey_ecd_digestverify25519 +}; + +static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = { + EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM, + 0, 0, 0, 0, 0, 0, + s390x_pkey_ecd_keygen448, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + pkey_ecd_ctrl, + 0, + s390x_pkey_ecd_digestsign448, + s390x_pkey_ecd_digestverify448 +}; +#endif + +const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void) +{ +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) + return &ecx25519_s390x_pkey_meth; +#endif + return &ecx25519_pkey_meth; +} + +const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void) +{ +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) + return &ecx448_s390x_pkey_meth; +#endif + return &ecx448_pkey_meth; +} + +const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void) +{ +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519) + && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519) + && OPENSSL_s390xcap_P.kdsa[0] + & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) + return &ed25519_s390x_pkey_meth; +#endif + return &ed25519_pkey_meth; +} + +const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void) +{ +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448) + && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448) + && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) + return &ed448_s390x_pkey_meth; +#endif + return &ed448_pkey_meth; +} diff --git a/crypto/ec/ecx_s390x.c b/crypto/ec/ecx_s390x.c new file mode 100644 index 000000000000..d424d6252dcf --- /dev/null +++ b/crypto/ec/ecx_s390x.c @@ -0,0 +1,217 @@ +/* + * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/ec.h> +#include <openssl/rand.h> +#include "crypto/ecx.h" +#include "ec_local.h" +#include "curve448/curve448_local.h" +#include "ecx_backend.h" +#include "s390x_arch.h" +#include "internal/constant_time.h" + +static void s390x_x25519_mod_p(unsigned char u[32]) +{ + unsigned char u_red[32]; + unsigned int c = 0; + int i; + + memcpy(u_red, u, sizeof(u_red)); + + c += (unsigned int)u_red[31] + 19; + u_red[31] = (unsigned char)c; + c >>= 8; + + for (i = 30; i >= 0; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + c = (u_red[0] & 0x80) >> 7; + u_red[0] &= 0x7f; + constant_time_cond_swap_buff(0 - (unsigned char)c, + u, u_red, sizeof(u_red)); +} + +static void s390x_x448_mod_p(unsigned char u[56]) +{ + unsigned char u_red[56]; + unsigned int c = 0; + int i; + + memcpy(u_red, u, sizeof(u_red)); + + c += (unsigned int)u_red[55] + 1; + u_red[55] = (unsigned char)c; + c >>= 8; + + for (i = 54; i >= 28; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + c += (unsigned int)u_red[27] + 1; + u_red[27] = (unsigned char)c; + c >>= 8; + + for (i = 26; i >= 0; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + constant_time_cond_swap_buff(0 - (unsigned char)c, + u, u_red, sizeof(u_red)); +} + +int s390x_x25519_mul(unsigned char u_dst[32], + const unsigned char u_src[32], + const unsigned char d_src[32]) +{ + union { + struct { + unsigned char u_dst[32]; + unsigned char u_src[32]; + unsigned char d_src[32]; + } x25519; + unsigned long long buff[512]; + } param; + int rc; + + memset(¶m, 0, sizeof(param)); + + s390x_flip_endian32(param.x25519.u_src, u_src); + param.x25519.u_src[0] &= 0x7f; + s390x_x25519_mod_p(param.x25519.u_src); + + s390x_flip_endian32(param.x25519.d_src, d_src); + param.x25519.d_src[31] &= 248; + param.x25519.d_src[0] &= 127; + param.x25519.d_src[0] |= 64; + + rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, ¶m.x25519) ? 0 : 1; + if (rc == 1) + s390x_flip_endian32(u_dst, param.x25519.u_dst); + + OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src)); + return rc; +} + +int s390x_x448_mul(unsigned char u_dst[56], + const unsigned char u_src[56], + const unsigned char d_src[56]) +{ + union { + struct { + unsigned char u_dst[64]; + unsigned char u_src[64]; + unsigned char d_src[64]; + } x448; + unsigned long long buff[512]; + } param; + int rc; + + memset(¶m, 0, sizeof(param)); + + memcpy(param.x448.u_src, u_src, 56); + memcpy(param.x448.d_src, d_src, 56); + + s390x_flip_endian64(param.x448.u_src, param.x448.u_src); + s390x_x448_mod_p(param.x448.u_src + 8); + + s390x_flip_endian64(param.x448.d_src, param.x448.d_src); + param.x448.d_src[63] &= 252; + param.x448.d_src[8] |= 128; + + rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, ¶m.x448) ? 0 : 1; + if (rc == 1) { + s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst); + memcpy(u_dst, param.x448.u_dst, 56); + } + + OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src)); + return rc; +} + +int s390x_ed25519_mul(unsigned char x_dst[32], + unsigned char y_dst[32], + const unsigned char x_src[32], + const unsigned char y_src[32], + const unsigned char d_src[32]) +{ + union { + struct { + unsigned char x_dst[32]; + unsigned char y_dst[32]; + unsigned char x_src[32]; + unsigned char y_src[32]; + unsigned char d_src[32]; + } ed25519; + unsigned long long buff[512]; + } param; + int rc; + + memset(¶m, 0, sizeof(param)); + + s390x_flip_endian32(param.ed25519.x_src, x_src); + s390x_flip_endian32(param.ed25519.y_src, y_src); + s390x_flip_endian32(param.ed25519.d_src, d_src); + + rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, ¶m.ed25519) ? 0 : 1; + if (rc == 1) { + s390x_flip_endian32(x_dst, param.ed25519.x_dst); + s390x_flip_endian32(y_dst, param.ed25519.y_dst); + } + + OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src)); + return rc; +} + +int s390x_ed448_mul(unsigned char x_dst[57], + unsigned char y_dst[57], + const unsigned char x_src[57], + const unsigned char y_src[57], + const unsigned char d_src[57]) +{ + union { + struct { + unsigned char x_dst[64]; + unsigned char y_dst[64]; + unsigned char x_src[64]; + unsigned char y_src[64]; + unsigned char d_src[64]; + } ed448; + unsigned long long buff[512]; + } param; + int rc; + + memset(¶m, 0, sizeof(param)); + + memcpy(param.ed448.x_src, x_src, 57); + memcpy(param.ed448.y_src, y_src, 57); + memcpy(param.ed448.d_src, d_src, 57); + s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src); + s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src); + s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src); + + rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, ¶m.ed448) ? 0 : 1; + if (rc == 1) { + s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst); + s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst); + memcpy(x_dst, param.ed448.x_dst, 57); + memcpy(y_dst, param.ed448.y_dst, 57); + } + + OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src)); + return rc; +} |