diff --git a/SOURCES/openssl-1.1.1-arm-update.patch b/SOURCES/openssl-1.1.1-arm-update.patch new file mode 100644 index 0000000..998905f --- /dev/null +++ b/SOURCES/openssl-1.1.1-arm-update.patch @@ -0,0 +1,1434 @@ +diff -up openssl-1.1.1c/crypto/aes/asm/aesv8-armx.pl.arm-update openssl-1.1.1c/crypto/aes/asm/aesv8-armx.pl +--- openssl-1.1.1c/crypto/aes/asm/aesv8-armx.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/aes/asm/aesv8-armx.pl 2019-11-20 11:36:22.389506155 +0100 +@@ -27,44 +27,72 @@ + # CBC encrypt case. On Cortex-A57 parallelizable mode performance + # seems to be limited by sheer amount of NEON instructions... + # ++# April 2019 ++# ++# Key to performance of parallelize-able modes is round instruction ++# interleaving. But which factor to use? There is optimal one for ++# each combination of instruction latency and issue rate, beyond ++# which increasing interleave factor doesn't pay off. While on cons ++# side we have code size increase and resource waste on platforms for ++# which interleave factor is too high. In other words you want it to ++# be just right. So far interleave factor of 3x was serving well all ++# platforms. But for ThunderX2 optimal interleave factor was measured ++# to be 5x... ++# + # Performance in cycles per byte processed with 128-bit key: + # + # CBC enc CBC dec CTR + # Apple A7 2.39 1.20 1.20 +-# Cortex-A53 1.32 1.29 1.46 +-# Cortex-A57(*) 1.95 0.85 0.93 +-# Denver 1.96 0.86 0.80 +-# Mongoose 1.33 1.20 1.20 +-# Kryo 1.26 0.94 1.00 ++# Cortex-A53 1.32 1.17/1.29(**) 1.36/1.46 ++# Cortex-A57(*) 1.95 0.82/0.85 0.89/0.93 ++# Cortex-A72 1.33 0.85/0.88 0.92/0.96 ++# Denver 1.96 0.65/0.86 0.76/0.80 ++# Mongoose 1.33 1.23/1.20 1.30/1.20 ++# Kryo 1.26 0.87/0.94 1.00/1.00 ++# ThunderX2 5.95 1.25 1.30 + # + # (*) original 3.64/1.34/1.32 results were for r0p0 revision + # and are still same even for updated module; ++# (**) numbers after slash are for 32-bit code, which is 3x- ++# interleaved; + +-$flavour = shift; +-$output = shift; ++# $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; + + $prefix="aes_v8"; + ++$_byte = ($flavour =~ /win/ ? "DCB" : ".byte"); ++ + $code=<<___; + #include "arm_arch.h" + + #if __ARM_MAX_ARCH__>=7 +-.text + ___ +-$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/); ++$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/); + $code.=<<___ if ($flavour !~ /64/); + .arch armv7-a // don't confuse not-so-latest binutils with argv8 :-) + .fpu neon ++#ifdef __thumb2__ ++.syntax unified ++.thumb ++# define INST(a,b,c,d) $_byte c,d|0xc,a,b ++#else + .code 32 +-#undef __thumb2__ ++# define INST(a,b,c,d) $_byte a,b,c,d ++#endif ++ ++.text + ___ + + # Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax, +@@ -514,6 +542,13 @@ $code.=<<___; + ___ + { + my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); ++ ++my ($dat3,$in3,$tmp3); # used only in 64-bit mode ++my ($dat4,$in4,$tmp4); ++if ($flavour =~ /64/) { ++ ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); ++} ++ + $code.=<<___; + .align 5 + .Lcbc_dec: +@@ -530,7 +565,196 @@ $code.=<<___; + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + vorr $in2,$dat2,$dat2 ++___ ++$code.=<<___ if ($flavour =~ /64/); ++ cmp $len,#32 ++ b.lo .Loop3x_cbc_dec ++ ++ vld1.8 {$dat3},[$inp],#16 ++ vld1.8 {$dat4},[$inp],#16 ++ sub $len,$len,#32 // bias ++ mov $cnt,$rounds ++ vorr $in3,$dat3,$dat3 ++ vorr $in4,$dat4,$dat4 ++ ++.Loop5x_cbc_dec: ++ aesd $dat0,q8 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q8 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q8 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q8 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q8 ++ aesimc $dat4,$dat4 ++ vld1.32 {q8},[$key_],#16 ++ subs $cnt,$cnt,#2 ++ aesd $dat0,q9 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q9 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q9 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q9 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q9 ++ aesimc $dat4,$dat4 ++ vld1.32 {q9},[$key_],#16 ++ b.gt .Loop5x_cbc_dec ++ ++ aesd $dat0,q8 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q8 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q8 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q8 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q8 ++ aesimc $dat4,$dat4 ++ cmp $len,#0x40 // because .Lcbc_tail4x ++ sub $len,$len,#0x50 ++ ++ aesd $dat0,q9 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q9 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q9 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q9 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q9 ++ aesimc $dat4,$dat4 ++ csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo ++ mov $key_,$key ++ ++ aesd $dat0,q10 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q10 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q10 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q10 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q10 ++ aesimc $dat4,$dat4 ++ add $inp,$inp,x6 // $inp is adjusted in such way that ++ // at exit from the loop $dat1-$dat4 ++ // are loaded with last "words" ++ add x6,$len,#0x60 // because .Lcbc_tail4x ++ ++ aesd $dat0,q11 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q11 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q11 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q11 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q11 ++ aesimc $dat4,$dat4 ++ ++ aesd $dat0,q12 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q12 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q12 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q12 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q12 ++ aesimc $dat4,$dat4 ++ ++ aesd $dat0,q13 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q13 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q13 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q13 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q13 ++ aesimc $dat4,$dat4 ++ ++ aesd $dat0,q14 ++ aesimc $dat0,$dat0 ++ aesd $dat1,q14 ++ aesimc $dat1,$dat1 ++ aesd $dat2,q14 ++ aesimc $dat2,$dat2 ++ aesd $dat3,q14 ++ aesimc $dat3,$dat3 ++ aesd $dat4,q14 ++ aesimc $dat4,$dat4 ++ ++ veor $tmp0,$ivec,$rndlast ++ aesd $dat0,q15 ++ veor $tmp1,$in0,$rndlast ++ vld1.8 {$in0},[$inp],#16 ++ aesd $dat1,q15 ++ veor $tmp2,$in1,$rndlast ++ vld1.8 {$in1},[$inp],#16 ++ aesd $dat2,q15 ++ veor $tmp3,$in2,$rndlast ++ vld1.8 {$in2},[$inp],#16 ++ aesd $dat3,q15 ++ veor $tmp4,$in3,$rndlast ++ vld1.8 {$in3},[$inp],#16 ++ aesd $dat4,q15 ++ vorr $ivec,$in4,$in4 ++ vld1.8 {$in4},[$inp],#16 ++ cbz x6,.Lcbc_tail4x ++ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] ++ veor $tmp0,$tmp0,$dat0 ++ vorr $dat0,$in0,$in0 ++ veor $tmp1,$tmp1,$dat1 ++ vorr $dat1,$in1,$in1 ++ veor $tmp2,$tmp2,$dat2 ++ vorr $dat2,$in2,$in2 ++ veor $tmp3,$tmp3,$dat3 ++ vorr $dat3,$in3,$in3 ++ veor $tmp4,$tmp4,$dat4 ++ vst1.8 {$tmp0},[$out],#16 ++ vorr $dat4,$in4,$in4 ++ vst1.8 {$tmp1},[$out],#16 ++ mov $cnt,$rounds ++ vst1.8 {$tmp2},[$out],#16 ++ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] ++ vst1.8 {$tmp3},[$out],#16 ++ vst1.8 {$tmp4},[$out],#16 ++ b.hs .Loop5x_cbc_dec ++ ++ add $len,$len,#0x50 ++ cbz $len,.Lcbc_done ++ ++ add $cnt,$rounds,#2 ++ subs $len,$len,#0x30 ++ vorr $dat0,$in2,$in2 ++ vorr $in0,$in2,$in2 ++ vorr $dat1,$in3,$in3 ++ vorr $in1,$in3,$in3 ++ vorr $dat2,$in4,$in4 ++ vorr $in2,$in4,$in4 ++ b.lo .Lcbc_dec_tail ++ ++ b .Loop3x_cbc_dec + ++.align 4 ++.Lcbc_tail4x: ++ veor $tmp1,$tmp0,$dat1 ++ veor $tmp2,$tmp2,$dat2 ++ veor $tmp3,$tmp3,$dat3 ++ veor $tmp4,$tmp4,$dat4 ++ vst1.8 {$tmp1},[$out],#16 ++ vst1.8 {$tmp2},[$out],#16 ++ vst1.8 {$tmp3},[$out],#16 ++ vst1.8 {$tmp4},[$out],#16 ++ ++ b .Lcbc_done ++.align 4 ++___ ++$code.=<<___; + .Loop3x_cbc_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 +@@ -691,6 +915,9 @@ my $step="x12"; # aliases with $tctr2 + my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7)); + my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + ++# used only in 64-bit mode... ++my ($dat3,$dat4,$in3,$in4)=map("q$_",(16..23)); ++ + my ($dat,$tmp)=($dat0,$tmp0); + + ### q8-q15 preloaded key schedule +@@ -743,6 +970,175 @@ $code.=<<___; + rev $tctr2, $ctr + sub $len,$len,#3 // bias + vmov.32 ${dat2}[3],$tctr2 ++___ ++$code.=<<___ if ($flavour =~ /64/); ++ cmp $len,#2 ++ b.lo .Loop3x_ctr32 ++ ++ add w13,$ctr,#1 ++ add w14,$ctr,#2 ++ vorr $dat3,$dat0,$dat0 ++ rev w13,w13 ++ vorr $dat4,$dat0,$dat0 ++ rev w14,w14 ++ vmov.32 ${dat3}[3],w13 ++ sub $len,$len,#2 // bias ++ vmov.32 ${dat4}[3],w14 ++ add $ctr,$ctr,#2 ++ b .Loop5x_ctr32 ++ ++.align 4 ++.Loop5x_ctr32: ++ aese $dat0,q8 ++ aesmc $dat0,$dat0 ++ aese $dat1,q8 ++ aesmc $dat1,$dat1 ++ aese $dat2,q8 ++ aesmc $dat2,$dat2 ++ aese $dat3,q8 ++ aesmc $dat3,$dat3 ++ aese $dat4,q8 ++ aesmc $dat4,$dat4 ++ vld1.32 {q8},[$key_],#16 ++ subs $cnt,$cnt,#2 ++ aese $dat0,q9 ++ aesmc $dat0,$dat0 ++ aese $dat1,q9 ++ aesmc $dat1,$dat1 ++ aese $dat2,q9 ++ aesmc $dat2,$dat2 ++ aese $dat3,q9 ++ aesmc $dat3,$dat3 ++ aese $dat4,q9 ++ aesmc $dat4,$dat4 ++ vld1.32 {q9},[$key_],#16 ++ b.gt .Loop5x_ctr32 ++ ++ mov $key_,$key ++ aese $dat0,q8 ++ aesmc $dat0,$dat0 ++ aese $dat1,q8 ++ aesmc $dat1,$dat1 ++ aese $dat2,q8 ++ aesmc $dat2,$dat2 ++ aese $dat3,q8 ++ aesmc $dat3,$dat3 ++ aese $dat4,q8 ++ aesmc $dat4,$dat4 ++ vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] ++ ++ aese $dat0,q9 ++ aesmc $dat0,$dat0 ++ aese $dat1,q9 ++ aesmc $dat1,$dat1 ++ aese $dat2,q9 ++ aesmc $dat2,$dat2 ++ aese $dat3,q9 ++ aesmc $dat3,$dat3 ++ aese $dat4,q9 ++ aesmc $dat4,$dat4 ++ vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] ++ ++ aese $dat0,q12 ++ aesmc $dat0,$dat0 ++ add $tctr0,$ctr,#1 ++ add $tctr1,$ctr,#2 ++ aese $dat1,q12 ++ aesmc $dat1,$dat1 ++ add $tctr2,$ctr,#3 ++ add w13,$ctr,#4 ++ aese $dat2,q12 ++ aesmc $dat2,$dat2 ++ add w14,$ctr,#5 ++ rev $tctr0,$tctr0 ++ aese $dat3,q12 ++ aesmc $dat3,$dat3 ++ rev $tctr1,$tctr1 ++ rev $tctr2,$tctr2 ++ aese $dat4,q12 ++ aesmc $dat4,$dat4 ++ rev w13,w13 ++ rev w14,w14 ++ ++ aese $dat0,q13 ++ aesmc $dat0,$dat0 ++ aese $dat1,q13 ++ aesmc $dat1,$dat1 ++ aese $dat2,q13 ++ aesmc $dat2,$dat2 ++ aese $dat3,q13 ++ aesmc $dat3,$dat3 ++ aese $dat4,q13 ++ aesmc $dat4,$dat4 ++ ++ aese $dat0,q14 ++ aesmc $dat0,$dat0 ++ vld1.8 {$in0},[$inp],#16 ++ aese $dat1,q14 ++ aesmc $dat1,$dat1 ++ vld1.8 {$in1},[$inp],#16 ++ aese $dat2,q14 ++ aesmc $dat2,$dat2 ++ vld1.8 {$in2},[$inp],#16 ++ aese $dat3,q14 ++ aesmc $dat3,$dat3 ++ vld1.8 {$in3},[$inp],#16 ++ aese $dat4,q14 ++ aesmc $dat4,$dat4 ++ vld1.8 {$in4},[$inp],#16 ++ ++ aese $dat0,q15 ++ veor $in0,$in0,$rndlast ++ aese $dat1,q15 ++ veor $in1,$in1,$rndlast ++ aese $dat2,q15 ++ veor $in2,$in2,$rndlast ++ aese $dat3,q15 ++ veor $in3,$in3,$rndlast ++ aese $dat4,q15 ++ veor $in4,$in4,$rndlast ++ ++ veor $in0,$in0,$dat0 ++ vorr $dat0,$ivec,$ivec ++ veor $in1,$in1,$dat1 ++ vorr $dat1,$ivec,$ivec ++ veor $in2,$in2,$dat2 ++ vorr $dat2,$ivec,$ivec ++ veor $in3,$in3,$dat3 ++ vorr $dat3,$ivec,$ivec ++ veor $in4,$in4,$dat4 ++ vorr $dat4,$ivec,$ivec ++ ++ vst1.8 {$in0},[$out],#16 ++ vmov.32 ${dat0}[3],$tctr0 ++ vst1.8 {$in1},[$out],#16 ++ vmov.32 ${dat1}[3],$tctr1 ++ vst1.8 {$in2},[$out],#16 ++ vmov.32 ${dat2}[3],$tctr2 ++ vst1.8 {$in3},[$out],#16 ++ vmov.32 ${dat3}[3],w13 ++ vst1.8 {$in4},[$out],#16 ++ vmov.32 ${dat4}[3],w14 ++ ++ mov $cnt,$rounds ++ cbz $len,.Lctr32_done ++ ++ add $ctr,$ctr,#5 ++ subs $len,$len,#5 ++ b.hs .Loop5x_ctr32 ++ ++ add $len,$len,#5 ++ sub $ctr,$ctr,#5 ++ ++ cmp $len,#2 ++ mov $step,#16 ++ cclr $step,lo ++ b.ls .Lctr32_tail ++ ++ sub $len,$len,#3 // bias ++ add $ctr,$ctr,#3 ++___ ++$code.=<<___; + b .Loop3x_ctr32 + + .align 4 +@@ -955,7 +1351,7 @@ if ($flavour =~ /64/) { ######## 64-bi + # since ARMv7 instructions are always encoded little-endian. + # correct solution is to use .inst directive, but older + # assemblers don't implement it:-( +- sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s", ++ sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s", + $word&0xff,($word>>8)&0xff, + ($word>>16)&0xff,($word>>24)&0xff, + $mnemonic,$arg; +@@ -996,14 +1392,17 @@ if ($flavour =~ /64/) { ######## 64-bi + s/\],#[0-9]+/]!/o; + + s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or +- s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or ++ s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or + s/vtbl\.8\s+(.*)/unvtbl($1)/geo or + s/vdup\.32\s+(.*)/unvdup32($1)/geo or + s/vmov\.32\s+(.*)/unvmov32($1)/geo or + s/^(\s+)b\./$1b/o or +- s/^(\s+)mov\./$1mov/o or + s/^(\s+)ret/$1bx\tlr/o; + ++ if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) { ++ print " it $2\n"; ++ } ++ + print $_,"\n"; + } + } +diff -up openssl-1.1.1c/crypto/aes/asm/vpaes-armv8.pl.arm-update openssl-1.1.1c/crypto/aes/asm/vpaes-armv8.pl +--- openssl-1.1.1c/crypto/aes/asm/vpaes-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/aes/asm/vpaes-armv8.pl 2019-11-20 11:36:22.389506155 +0100 +@@ -30,6 +30,7 @@ + # Denver(***) 16.6(**) 15.1/17.8(**) [8.80/9.93 ] + # Apple A7(***) 22.7(**) 10.9/14.3 [8.45/10.0 ] + # Mongoose(***) 26.3(**) 21.0/25.0(**) [13.3/16.8 ] ++# ThunderX2(***) 39.4(**) 33.8/48.6(**) + # + # (*) ECB denotes approximate result for parallelizable modes + # such as CBC decrypt, CTR, etc.; +diff -up openssl-1.1.1c/crypto/chacha/asm/chacha-armv8.pl.arm-update openssl-1.1.1c/crypto/chacha/asm/chacha-armv8.pl +--- openssl-1.1.1c/crypto/chacha/asm/chacha-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/chacha/asm/chacha-armv8.pl 2019-11-21 16:44:50.814651553 +0100 +@@ -18,32 +18,44 @@ + # + # ChaCha20 for ARMv8. + # ++# April 2019 ++# ++# Replace 3xNEON+1xIALU code path with 4+1. 4+1 is actually fastest ++# option on most(*), but not all, processors, yet 6+2 is retained. ++# This is because penalties are considered tolerable in comparison to ++# improvement on processors where 6+2 helps. Most notably +37% on ++# ThunderX2. It's server-oriented processor which will have to serve ++# as many requests as possible. While others are mostly clients, when ++# performance doesn't have to be absolute top-notch, just fast enough, ++# as majority of time is spent "entertaining" relatively slow human. ++# + # Performance in cycles per byte out of large buffer. + # +-# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU ++# IALU/gcc-4.9 4xNEON+1xIALU 6xNEON+2xIALU + # +-# Apple A7 5.50/+49% 3.33 1.70 +-# Cortex-A53 8.40/+80% 4.72 4.72(*) +-# Cortex-A57 8.06/+43% 4.90 4.43(**) +-# Denver 4.50/+82% 2.63 2.67(*) +-# X-Gene 9.50/+46% 8.82 8.89(*) +-# Mongoose 8.00/+44% 3.64 3.25 +-# Kryo 8.17/+50% 4.83 4.65 ++# Apple A7 5.50/+49% 2.72 1.60 ++# Cortex-A53 8.40/+80% 4.06 4.45(*) ++# Cortex-A57 8.06/+43% 4.15 4.40(*) ++# Denver 4.50/+82% 2.30 2.70(*) ++# X-Gene 9.50/+46% 8.20 8.90(*) ++# Mongoose 8.00/+44% 2.74 3.12(*) ++# Kryo 8.17/+50% 4.47 4.65(*) ++# ThunderX2 7.22/+48% 5.64 4.10 + # +-# (*) it's expected that doubling interleave factor doesn't help +-# all processors, only those with higher NEON latency and +-# higher instruction issue rate; +-# (**) expected improvement was actually higher; ++# (*) slower than 4+1:-( + +-$flavour=shift; +-$output=shift; ++# $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; + + sub AUTOLOAD() # thunk [simplified] x86-style perlasm +@@ -120,41 +132,36 @@ my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1) + } + + $code.=<<___; +-#include "arm_arch.h" ++#ifndef __KERNEL__ ++# include "arm_arch.h" ++.extern OPENSSL_armcap_P ++#endif + + .text + +-.extern OPENSSL_armcap_P +- + .align 5 + .Lsigma: + .quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral + .Lone: +-.long 1,0,0,0 +-.LOPENSSL_armcap_P: +-#ifdef __ILP32__ +-.long OPENSSL_armcap_P-. +-#else +-.quad OPENSSL_armcap_P-. +-#endif +-.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by " ++.long 1,2,3,4 ++.Lrot24: ++.long 0x02010003,0x06050407,0x0a09080b,0x0e0d0c0f ++.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by \@dot-asm" + + .globl ChaCha20_ctr32 + .type ChaCha20_ctr32,%function + .align 5 + ChaCha20_ctr32: + cbz $len,.Labort +- adr @x[0],.LOPENSSL_armcap_P + cmp $len,#192 + b.lo .Lshort +-#ifdef __ILP32__ +- ldrsw @x[1],[@x[0]] +-#else +- ldr @x[1],[@x[0]] +-#endif +- ldr w17,[@x[1],@x[0]] ++ ++#ifndef __KERNEL__ ++ adrp x17,OPENSSL_armcap_P ++ ldr w17,[x17,#:lo12:OPENSSL_armcap_P] + tst w17,#ARMV7_NEON +- b.ne ChaCha20_neon ++ b.ne .LChaCha20_neon ++#endif + + .Lshort: + .inst 0xd503233f // paciasp +@@ -173,7 +180,7 @@ ChaCha20_ctr32: + ldp @d[2],@d[3],[$key] // load key + ldp @d[4],@d[5],[$key,#16] + ldp @d[6],@d[7],[$ctr] // load counter +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 + ror @d[4],@d[4],#32 +@@ -242,7 +249,7 @@ $code.=<<___; + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -299,7 +306,7 @@ $code.=<<___; + add @x[10],@x[10],@x[11],lsl#32 + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -340,46 +347,91 @@ $code.=<<___; + ___ + + {{{ +-my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) = +- map("v$_.4s",(0..7,16..23)); +-my (@K)=map("v$_.4s",(24..30)); +-my $ONE="v31.4s"; ++my @K = map("v$_.4s",(0..3)); ++my ($xt0,$xt1,$xt2,$xt3, $CTR,$ROT24) = map("v$_.4s",(4..9)); ++my @X = map("v$_.4s",(16,20,24,28, 17,21,25,29, 18,22,26,30, 19,23,27,31)); ++my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3, ++ $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3) = @X; + +-sub NEONROUND { +-my $odd = pop; +-my ($a,$b,$c,$d,$t)=@_; ++sub NEON_lane_ROUND { ++my ($a0,$b0,$c0,$d0)=@_; ++my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0)); ++my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1)); ++my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); ++my @x=map("'$_'",@X); + + ( +- "&add ('$a','$a','$b')", +- "&eor ('$d','$d','$a')", +- "&rev32_16 ('$d','$d')", # vrot ($d,16) +- +- "&add ('$c','$c','$d')", +- "&eor ('$t','$b','$c')", +- "&ushr ('$b','$t',20)", +- "&sli ('$b','$t',12)", +- +- "&add ('$a','$a','$b')", +- "&eor ('$t','$d','$a')", +- "&ushr ('$d','$t',24)", +- "&sli ('$d','$t',8)", +- +- "&add ('$c','$c','$d')", +- "&eor ('$t','$b','$c')", +- "&ushr ('$b','$t',25)", +- "&sli ('$b','$t',7)", +- +- "&ext ('$c','$c','$c',8)", +- "&ext ('$d','$d','$d',$odd?4:12)", +- "&ext ('$b','$b','$b',$odd?12:4)" ++ "&add (@x[$a0],@x[$a0],@x[$b0])", # Q1 ++ "&add (@x[$a1],@x[$a1],@x[$b1])", # Q2 ++ "&add (@x[$a2],@x[$a2],@x[$b2])", # Q3 ++ "&add (@x[$a3],@x[$a3],@x[$b3])", # Q4 ++ "&eor (@x[$d0],@x[$d0],@x[$a0])", ++ "&eor (@x[$d1],@x[$d1],@x[$a1])", ++ "&eor (@x[$d2],@x[$d2],@x[$a2])", ++ "&eor (@x[$d3],@x[$d3],@x[$a3])", ++ "&rev32_16 (@x[$d0],@x[$d0])", ++ "&rev32_16 (@x[$d1],@x[$d1])", ++ "&rev32_16 (@x[$d2],@x[$d2])", ++ "&rev32_16 (@x[$d3],@x[$d3])", ++ ++ "&add (@x[$c0],@x[$c0],@x[$d0])", ++ "&add (@x[$c1],@x[$c1],@x[$d1])", ++ "&add (@x[$c2],@x[$c2],@x[$d2])", ++ "&add (@x[$c3],@x[$c3],@x[$d3])", ++ "&eor ('$xt0',@x[$b0],@x[$c0])", ++ "&eor ('$xt1',@x[$b1],@x[$c1])", ++ "&eor ('$xt2',@x[$b2],@x[$c2])", ++ "&eor ('$xt3',@x[$b3],@x[$c3])", ++ "&ushr (@x[$b0],'$xt0',20)", ++ "&ushr (@x[$b1],'$xt1',20)", ++ "&ushr (@x[$b2],'$xt2',20)", ++ "&ushr (@x[$b3],'$xt3',20)", ++ "&sli (@x[$b0],'$xt0',12)", ++ "&sli (@x[$b1],'$xt1',12)", ++ "&sli (@x[$b2],'$xt2',12)", ++ "&sli (@x[$b3],'$xt3',12)", ++ ++ "&add (@x[$a0],@x[$a0],@x[$b0])", ++ "&add (@x[$a1],@x[$a1],@x[$b1])", ++ "&add (@x[$a2],@x[$a2],@x[$b2])", ++ "&add (@x[$a3],@x[$a3],@x[$b3])", ++ "&eor ('$xt0',@x[$d0],@x[$a0])", ++ "&eor ('$xt1',@x[$d1],@x[$a1])", ++ "&eor ('$xt2',@x[$d2],@x[$a2])", ++ "&eor ('$xt3',@x[$d3],@x[$a3])", ++ "&tbl (@x[$d0],'{$xt0}','$ROT24')", ++ "&tbl (@x[$d1],'{$xt1}','$ROT24')", ++ "&tbl (@x[$d2],'{$xt2}','$ROT24')", ++ "&tbl (@x[$d3],'{$xt3}','$ROT24')", ++ ++ "&add (@x[$c0],@x[$c0],@x[$d0])", ++ "&add (@x[$c1],@x[$c1],@x[$d1])", ++ "&add (@x[$c2],@x[$c2],@x[$d2])", ++ "&add (@x[$c3],@x[$c3],@x[$d3])", ++ "&eor ('$xt0',@x[$b0],@x[$c0])", ++ "&eor ('$xt1',@x[$b1],@x[$c1])", ++ "&eor ('$xt2',@x[$b2],@x[$c2])", ++ "&eor ('$xt3',@x[$b3],@x[$c3])", ++ "&ushr (@x[$b0],'$xt0',25)", ++ "&ushr (@x[$b1],'$xt1',25)", ++ "&ushr (@x[$b2],'$xt2',25)", ++ "&ushr (@x[$b3],'$xt3',25)", ++ "&sli (@x[$b0],'$xt0',7)", ++ "&sli (@x[$b1],'$xt1',7)", ++ "&sli (@x[$b2],'$xt2',7)", ++ "&sli (@x[$b3],'$xt3',7)" + ); + } + + $code.=<<___; + ++#ifdef __KERNEL__ ++.globl ChaCha20_neon ++#endif + .type ChaCha20_neon,%function + .align 5 + ChaCha20_neon: ++.LChaCha20_neon: + .inst 0xd503233f // paciasp + stp x29,x30,[sp,#-96]! + add x29,sp,#0 +@@ -402,8 +454,9 @@ ChaCha20_neon: + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] +- ld1 {$ONE},[@x[0]] +-#ifdef __ARMEB__ ++ stp d8,d9,[sp] // meet ABI requirements ++ ld1 {$CTR,$ROT24},[@x[0]] ++#ifdef __AARCH64EB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 +@@ -412,115 +465,129 @@ ChaCha20_neon: + ror @d[6],@d[6],#32 + ror @d[7],@d[7],#32 + #endif +- add @K[3],@K[3],$ONE // += 1 +- add @K[4],@K[3],$ONE +- add @K[5],@K[4],$ONE +- shl $ONE,$ONE,#2 // 1 -> 4 + + .Loop_outer_neon: +- mov.32 @x[0],@d[0] // unpack key block +- lsr @x[1],@d[0],#32 +- mov $A0,@K[0] +- mov.32 @x[2],@d[1] +- lsr @x[3],@d[1],#32 +- mov $A1,@K[0] +- mov.32 @x[4],@d[2] +- lsr @x[5],@d[2],#32 +- mov $A2,@K[0] +- mov.32 @x[6],@d[3] +- mov $B0,@K[1] +- lsr @x[7],@d[3],#32 +- mov $B1,@K[1] +- mov.32 @x[8],@d[4] +- mov $B2,@K[1] +- lsr @x[9],@d[4],#32 +- mov $D0,@K[3] +- mov.32 @x[10],@d[5] +- mov $D1,@K[4] +- lsr @x[11],@d[5],#32 +- mov $D2,@K[5] +- mov.32 @x[12],@d[6] +- mov $C0,@K[2] +- lsr @x[13],@d[6],#32 +- mov $C1,@K[2] +- mov.32 @x[14],@d[7] +- mov $C2,@K[2] +- lsr @x[15],@d[7],#32 ++ dup $xa0,@{K[0]}[0] // unpack key block ++ mov.32 @x[0],@d[0] ++ dup $xa1,@{K[0]}[1] ++ lsr @x[1],@d[0],#32 ++ dup $xa2,@{K[0]}[2] ++ mov.32 @x[2],@d[1] ++ dup $xa3,@{K[0]}[3] ++ lsr @x[3],@d[1],#32 ++ dup $xb0,@{K[1]}[0] ++ mov.32 @x[4],@d[2] ++ dup $xb1,@{K[1]}[1] ++ lsr @x[5],@d[2],#32 ++ dup $xb2,@{K[1]}[2] ++ mov.32 @x[6],@d[3] ++ dup $xb3,@{K[1]}[3] ++ lsr @x[7],@d[3],#32 ++ dup $xd0,@{K[3]}[0] ++ mov.32 @x[8],@d[4] ++ dup $xd1,@{K[3]}[1] ++ lsr @x[9],@d[4],#32 ++ dup $xd2,@{K[3]}[2] ++ mov.32 @x[10],@d[5] ++ dup $xd3,@{K[3]}[3] ++ lsr @x[11],@d[5],#32 ++ add $xd0,$xd0,$CTR ++ mov.32 @x[12],@d[6] ++ dup $xc0,@{K[2]}[0] ++ lsr @x[13],@d[6],#32 ++ dup $xc1,@{K[2]}[1] ++ mov.32 @x[14],@d[7] ++ dup $xc2,@{K[2]}[2] ++ lsr @x[15],@d[7],#32 ++ dup $xc3,@{K[2]}[3] + + mov $ctr,#10 +- subs $len,$len,#256 ++ subs $len,$len,#320 + .Loop_neon: + sub $ctr,$ctr,#1 + ___ +- my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0); +- my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0); +- my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0); +- my @thread3=&ROUND(0,4,8,12); +- +- foreach (@thread0) { +- eval; eval(shift(@thread3)); +- eval(shift(@thread1)); eval(shift(@thread3)); +- eval(shift(@thread2)); eval(shift(@thread3)); +- } +- +- @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1); +- @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1); +- @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1); +- @thread3=&ROUND(0,5,10,15); ++ my @plus_one=&ROUND(0,4,8,12); ++ foreach (&NEON_lane_ROUND(0,4,8,12)) { eval; eval(shift(@plus_one)); } + +- foreach (@thread0) { +- eval; eval(shift(@thread3)); +- eval(shift(@thread1)); eval(shift(@thread3)); +- eval(shift(@thread2)); eval(shift(@thread3)); +- } ++ @plus_one=&ROUND(0,5,10,15); ++ foreach (&NEON_lane_ROUND(0,5,10,15)) { eval; eval(shift(@plus_one)); } + $code.=<<___; + cbnz $ctr,.Loop_neon + +- add.32 @x[0],@x[0],@d[0] // accumulate key block +- add $A0,$A0,@K[0] +- add @x[1],@x[1],@d[0],lsr#32 +- add $A1,$A1,@K[0] +- add.32 @x[2],@x[2],@d[1] +- add $A2,$A2,@K[0] +- add @x[3],@x[3],@d[1],lsr#32 +- add $C0,$C0,@K[2] +- add.32 @x[4],@x[4],@d[2] +- add $C1,$C1,@K[2] +- add @x[5],@x[5],@d[2],lsr#32 +- add $C2,$C2,@K[2] +- add.32 @x[6],@x[6],@d[3] +- add $D0,$D0,@K[3] +- add @x[7],@x[7],@d[3],lsr#32 +- add.32 @x[8],@x[8],@d[4] +- add $D1,$D1,@K[4] +- add @x[9],@x[9],@d[4],lsr#32 +- add.32 @x[10],@x[10],@d[5] +- add $D2,$D2,@K[5] +- add @x[11],@x[11],@d[5],lsr#32 +- add.32 @x[12],@x[12],@d[6] +- add $B0,$B0,@K[1] +- add @x[13],@x[13],@d[6],lsr#32 +- add.32 @x[14],@x[14],@d[7] +- add $B1,$B1,@K[1] +- add @x[15],@x[15],@d[7],lsr#32 +- add $B2,$B2,@K[1] ++ add $xd0,$xd0,$CTR ++ ++ zip1 $xt0,$xa0,$xa1 // transpose data ++ zip1 $xt1,$xa2,$xa3 ++ zip2 $xt2,$xa0,$xa1 ++ zip2 $xt3,$xa2,$xa3 ++ zip1.64 $xa0,$xt0,$xt1 ++ zip2.64 $xa1,$xt0,$xt1 ++ zip1.64 $xa2,$xt2,$xt3 ++ zip2.64 $xa3,$xt2,$xt3 ++ ++ zip1 $xt0,$xb0,$xb1 ++ zip1 $xt1,$xb2,$xb3 ++ zip2 $xt2,$xb0,$xb1 ++ zip2 $xt3,$xb2,$xb3 ++ zip1.64 $xb0,$xt0,$xt1 ++ zip2.64 $xb1,$xt0,$xt1 ++ zip1.64 $xb2,$xt2,$xt3 ++ zip2.64 $xb3,$xt2,$xt3 ++ ++ zip1 $xt0,$xc0,$xc1 ++ add.32 @x[0],@x[0],@d[0] // accumulate key block ++ zip1 $xt1,$xc2,$xc3 ++ add @x[1],@x[1],@d[0],lsr#32 ++ zip2 $xt2,$xc0,$xc1 ++ add.32 @x[2],@x[2],@d[1] ++ zip2 $xt3,$xc2,$xc3 ++ add @x[3],@x[3],@d[1],lsr#32 ++ zip1.64 $xc0,$xt0,$xt1 ++ add.32 @x[4],@x[4],@d[2] ++ zip2.64 $xc1,$xt0,$xt1 ++ add @x[5],@x[5],@d[2],lsr#32 ++ zip1.64 $xc2,$xt2,$xt3 ++ add.32 @x[6],@x[6],@d[3] ++ zip2.64 $xc3,$xt2,$xt3 ++ add @x[7],@x[7],@d[3],lsr#32 ++ ++ zip1 $xt0,$xd0,$xd1 ++ add.32 @x[8],@x[8],@d[4] ++ zip1 $xt1,$xd2,$xd3 ++ add @x[9],@x[9],@d[4],lsr#32 ++ zip2 $xt2,$xd0,$xd1 ++ add.32 @x[10],@x[10],@d[5] ++ zip2 $xt3,$xd2,$xd3 ++ add @x[11],@x[11],@d[5],lsr#32 ++ zip1.64 $xd0,$xt0,$xt1 ++ add.32 @x[12],@x[12],@d[6] ++ zip2.64 $xd1,$xt0,$xt1 ++ add @x[13],@x[13],@d[6],lsr#32 ++ zip1.64 $xd2,$xt2,$xt3 ++ add.32 @x[14],@x[14],@d[7] ++ zip2.64 $xd3,$xt2,$xt3 ++ add @x[15],@x[15],@d[7],lsr#32 + + b.lo .Ltail_neon + + add @x[0],@x[0],@x[1],lsl#32 // pack + add @x[2],@x[2],@x[3],lsl#32 + ldp @x[1],@x[3],[$inp,#0] // load input ++ add $xa0,$xa0,@K[0] // accumulate key block + add @x[4],@x[4],@x[5],lsl#32 + add @x[6],@x[6],@x[7],lsl#32 + ldp @x[5],@x[7],[$inp,#16] ++ add $xb0,$xb0,@K[1] + add @x[8],@x[8],@x[9],lsl#32 + add @x[10],@x[10],@x[11],lsl#32 + ldp @x[9],@x[11],[$inp,#32] ++ add $xc0,$xc0,@K[2] + add @x[12],@x[12],@x[13],lsl#32 + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] ++ add $xd0,$xd0,@K[3] + add $inp,$inp,#64 +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -530,48 +597,68 @@ $code.=<<___; + rev @x[12],@x[12] + rev @x[14],@x[14] + #endif +- ld1.8 {$T0-$T3},[$inp],#64 ++ ld1.8 {$xt0-$xt3},[$inp],#64 + eor @x[0],@x[0],@x[1] ++ add $xa1,$xa1,@K[0] + eor @x[2],@x[2],@x[3] ++ add $xb1,$xb1,@K[1] + eor @x[4],@x[4],@x[5] ++ add $xc1,$xc1,@K[2] + eor @x[6],@x[6],@x[7] ++ add $xd1,$xd1,@K[3] + eor @x[8],@x[8],@x[9] +- eor $A0,$A0,$T0 ++ eor $xa0,$xa0,$xt0 ++ movi $xt0,#5 + eor @x[10],@x[10],@x[11] +- eor $B0,$B0,$T1 ++ eor $xb0,$xb0,$xt1 + eor @x[12],@x[12],@x[13] +- eor $C0,$C0,$T2 ++ eor $xc0,$xc0,$xt2 + eor @x[14],@x[14],@x[15] +- eor $D0,$D0,$T3 +- ld1.8 {$T0-$T3},[$inp],#64 ++ eor $xd0,$xd0,$xt3 ++ add $CTR,$CTR,$xt0 // += 5 ++ ld1.8 {$xt0-$xt3},[$inp],#64 + + stp @x[0],@x[2],[$out,#0] // store output +- add @d[6],@d[6],#4 // increment counter ++ add @d[6],@d[6],#5 // increment counter + stp @x[4],@x[6],[$out,#16] +- add @K[3],@K[3],$ONE // += 4 + stp @x[8],@x[10],[$out,#32] +- add @K[4],@K[4],$ONE + stp @x[12],@x[14],[$out,#48] +- add @K[5],@K[5],$ONE + add $out,$out,#64 + +- st1.8 {$A0-$D0},[$out],#64 +- ld1.8 {$A0-$D0},[$inp],#64 +- +- eor $A1,$A1,$T0 +- eor $B1,$B1,$T1 +- eor $C1,$C1,$T2 +- eor $D1,$D1,$T3 +- st1.8 {$A1-$D1},[$out],#64 +- +- eor $A2,$A2,$A0 +- eor $B2,$B2,$B0 +- eor $C2,$C2,$C0 +- eor $D2,$D2,$D0 +- st1.8 {$A2-$D2},[$out],#64 ++ st1.8 {$xa0-$xd0},[$out],#64 ++ add $xa2,$xa2,@K[0] ++ add $xb2,$xb2,@K[1] ++ add $xc2,$xc2,@K[2] ++ add $xd2,$xd2,@K[3] ++ ld1.8 {$xa0-$xd0},[$inp],#64 ++ ++ eor $xa1,$xa1,$xt0 ++ eor $xb1,$xb1,$xt1 ++ eor $xc1,$xc1,$xt2 ++ eor $xd1,$xd1,$xt3 ++ st1.8 {$xa1-$xd1},[$out],#64 ++ add $xa3,$xa3,@K[0] ++ add $xb3,$xb3,@K[1] ++ add $xc3,$xc3,@K[2] ++ add $xd3,$xd3,@K[3] ++ ld1.8 {$xa1-$xd1},[$inp],#64 ++ ++ eor $xa2,$xa2,$xa0 ++ eor $xb2,$xb2,$xb0 ++ eor $xc2,$xc2,$xc0 ++ eor $xd2,$xd2,$xd0 ++ st1.8 {$xa2-$xd2},[$out],#64 ++ ++ eor $xa3,$xa3,$xa1 ++ eor $xb3,$xb3,$xb1 ++ eor $xc3,$xc3,$xc1 ++ eor $xd3,$xd3,$xd1 ++ st1.8 {$xa3-$xd3},[$out],#64 + + b.hi .Loop_outer_neon + ++ ldp d8,d9,[sp] // meet ABI requirements ++ + ldp x19,x20,[x29,#16] + add sp,sp,#64 + ldp x21,x22,[x29,#32] +@@ -582,8 +669,10 @@ $code.=<<___; + .inst 0xd50323bf // autiasp + ret + ++.align 4 + .Ltail_neon: +- add $len,$len,#256 ++ add $len,$len,#320 ++ ldp d8,d9,[sp] // meet ABI requirements + cmp $len,#64 + b.lo .Less_than_64 + +@@ -600,7 +689,7 @@ $code.=<<___; + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -620,48 +709,68 @@ $code.=<<___; + eor @x[14],@x[14],@x[15] + + stp @x[0],@x[2],[$out,#0] // store output +- add @d[6],@d[6],#4 // increment counter ++ add $xa0,$xa0,@K[0] // accumulate key block + stp @x[4],@x[6],[$out,#16] ++ add $xb0,$xb0,@K[1] + stp @x[8],@x[10],[$out,#32] ++ add $xc0,$xc0,@K[2] + stp @x[12],@x[14],[$out,#48] ++ add $xd0,$xd0,@K[3] + add $out,$out,#64 + b.eq .Ldone_neon + sub $len,$len,#64 + cmp $len,#64 +- b.lo .Less_than_128 ++ b.lo .Last_neon + +- ld1.8 {$T0-$T3},[$inp],#64 +- eor $A0,$A0,$T0 +- eor $B0,$B0,$T1 +- eor $C0,$C0,$T2 +- eor $D0,$D0,$T3 +- st1.8 {$A0-$D0},[$out],#64 ++ ld1.8 {$xt0-$xt3},[$inp],#64 ++ eor $xa0,$xa0,$xt0 ++ eor $xb0,$xb0,$xt1 ++ eor $xc0,$xc0,$xt2 ++ eor $xd0,$xd0,$xt3 ++ st1.8 {$xa0-$xd0},[$out],#64 + b.eq .Ldone_neon ++ ++ add $xa0,$xa1,@K[0] ++ add $xb0,$xb1,@K[1] + sub $len,$len,#64 ++ add $xc0,$xc1,@K[2] + cmp $len,#64 +- b.lo .Less_than_192 ++ add $xd0,$xd1,@K[3] ++ b.lo .Last_neon + +- ld1.8 {$T0-$T3},[$inp],#64 +- eor $A1,$A1,$T0 +- eor $B1,$B1,$T1 +- eor $C1,$C1,$T2 +- eor $D1,$D1,$T3 +- st1.8 {$A1-$D1},[$out],#64 ++ ld1.8 {$xt0-$xt3},[$inp],#64 ++ eor $xa1,$xa0,$xt0 ++ eor $xb1,$xb0,$xt1 ++ eor $xc1,$xc0,$xt2 ++ eor $xd1,$xd0,$xt3 ++ st1.8 {$xa1-$xd1},[$out],#64 + b.eq .Ldone_neon ++ ++ add $xa0,$xa2,@K[0] ++ add $xb0,$xb2,@K[1] + sub $len,$len,#64 ++ add $xc0,$xc2,@K[2] ++ cmp $len,#64 ++ add $xd0,$xd2,@K[3] ++ b.lo .Last_neon + +- st1.8 {$A2-$D2},[sp] +- b .Last_neon ++ ld1.8 {$xt0-$xt3},[$inp],#64 ++ eor $xa2,$xa0,$xt0 ++ eor $xb2,$xb0,$xt1 ++ eor $xc2,$xc0,$xt2 ++ eor $xd2,$xd0,$xt3 ++ st1.8 {$xa2-$xd2},[$out],#64 ++ b.eq .Ldone_neon + +-.Less_than_128: +- st1.8 {$A0-$D0},[sp] +- b .Last_neon +-.Less_than_192: +- st1.8 {$A1-$D1},[sp] +- b .Last_neon ++ add $xa0,$xa3,@K[0] ++ add $xb0,$xb3,@K[1] ++ add $xc0,$xc3,@K[2] ++ add $xd0,$xd3,@K[3] ++ sub $len,$len,#64 + +-.align 4 + .Last_neon: ++ st1.8 {$xa0-$xd0},[sp] ++ + sub $out,$out,#1 + add $inp,$inp,$len + add $out,$out,$len +@@ -694,9 +803,41 @@ $code.=<<___; + .size ChaCha20_neon,.-ChaCha20_neon + ___ + { ++my @K = map("v$_.4s",(0..6)); + my ($T0,$T1,$T2,$T3,$T4,$T5)=@K; + my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2, +- $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23)); ++ $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(8..31)); ++my $rot24 = @K[6]; ++my $ONE = "v7.4s"; ++ ++sub NEONROUND { ++my $odd = pop; ++my ($a,$b,$c,$d,$t)=@_; ++ ++ ( ++ "&add ('$a','$a','$b')", ++ "&eor ('$d','$d','$a')", ++ "&rev32_16 ('$d','$d')", # vrot ($d,16) ++ ++ "&add ('$c','$c','$d')", ++ "&eor ('$t','$b','$c')", ++ "&ushr ('$b','$t',20)", ++ "&sli ('$b','$t',12)", ++ ++ "&add ('$a','$a','$b')", ++ "&eor ('$d','$d','$a')", ++ "&tbl ('$d','{$d}','$rot24')", ++ ++ "&add ('$c','$c','$d')", ++ "&eor ('$t','$b','$c')", ++ "&ushr ('$b','$t',25)", ++ "&sli ('$b','$t',7)", ++ ++ "&ext ('$c','$c','$c',8)", ++ "&ext ('$d','$d','$d',$odd?4:12)", ++ "&ext ('$b','$b','$b',$odd?12:4)" ++ ); ++} + + $code.=<<___; + .type ChaCha20_512_neon,%function +@@ -716,6 +857,7 @@ ChaCha20_512_neon: + .L512_or_more_neon: + sub sp,sp,#128+64 + ++ eor $ONE,$ONE,$ONE + ldp @d[0],@d[1],[@x[0]] // load sigma + ld1 {@K[0]},[@x[0]],#16 + ldp @d[2],@d[3],[$key] // load key +@@ -723,8 +865,9 @@ ChaCha20_512_neon: + ld1 {@K[1],@K[2]},[$key] + ldp @d[6],@d[7],[$ctr] // load counter + ld1 {@K[3]},[$ctr] +- ld1 {$ONE},[@x[0]] +-#ifdef __ARMEB__ ++ ld1 {$ONE}[0],[@x[0]] ++ add $key,@x[0],#16 // .Lrot24 ++#ifdef __AARCH64EB__ + rev64 @K[0],@K[0] + ror @d[2],@d[2],#32 + ror @d[3],@d[3],#32 +@@ -791,9 +934,10 @@ ChaCha20_512_neon: + mov $C4,@K[2] + stp @K[3],@K[4],[sp,#48] // off-load key block, variable part + mov $C5,@K[2] +- str @K[5],[sp,#80] ++ stp @K[5],@K[6],[sp,#80] + + mov $ctr,#5 ++ ld1 {$rot24},[$key] + subs $len,$len,#512 + .Loop_upper_neon: + sub $ctr,$ctr,#1 +@@ -866,7 +1010,7 @@ $code.=<<___; + add @x[14],@x[14],@x[15],lsl#32 + ldp @x[13],@x[15],[$inp,#48] + add $inp,$inp,#64 +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -955,6 +1099,7 @@ $code.=<<___; + add.32 @x[2],@x[2],@d[1] + ldp @K[4],@K[5],[sp,#64] + add @x[3],@x[3],@d[1],lsr#32 ++ ldr @K[6],[sp,#96] + add $A0,$A0,@K[0] + add.32 @x[4],@x[4],@d[2] + add $A1,$A1,@K[0] +@@ -1007,7 +1152,7 @@ $code.=<<___; + add $inp,$inp,#64 + add $B5,$B5,@K[1] + +-#ifdef __ARMEB__ ++#ifdef __AARCH64EB__ + rev @x[0],@x[0] + rev @x[2],@x[2] + rev @x[4],@x[4] +@@ -1085,26 +1230,26 @@ $code.=<<___; + b.hs .Loop_outer_512_neon + + adds $len,$len,#512 +- ushr $A0,$ONE,#2 // 4 -> 1 ++ ushr $ONE,$ONE,#1 // 4 -> 2 + +- ldp d8,d9,[sp,#128+0] // meet ABI requirements + ldp d10,d11,[sp,#128+16] + ldp d12,d13,[sp,#128+32] + ldp d14,d15,[sp,#128+48] + +- stp @K[0],$ONE,[sp,#0] // wipe off-load area +- stp @K[0],$ONE,[sp,#32] +- stp @K[0],$ONE,[sp,#64] ++ stp @K[0],@K[0],[sp,#0] // wipe off-load area ++ stp @K[0],@K[0],[sp,#32] ++ stp @K[0],@K[0],[sp,#64] + + b.eq .Ldone_512_neon + ++ sub $key,$key,#16 // .Lone + cmp $len,#192 +- sub @K[3],@K[3],$A0 // -= 1 +- sub @K[4],@K[4],$A0 +- sub @K[5],@K[5],$A0 + add sp,sp,#128 ++ sub @K[3],@K[3],$ONE // -= 2 ++ ld1 {$CTR,$ROT24},[$key] + b.hs .Loop_outer_neon + ++ ldp d8,d9,[sp,#0] // meet ABI requirements + eor @K[1],@K[1],@K[1] + eor @K[2],@K[2],@K[2] + eor @K[3],@K[3],@K[3] +@@ -1114,6 +1259,7 @@ $code.=<<___; + b .Loop_outer + + .Ldone_512_neon: ++ ldp d8,d9,[sp,#128+0] // meet ABI requirements + ldp x19,x20,[x29,#16] + add sp,sp,#128+64 + ldp x21,x22,[x29,#32] +@@ -1132,9 +1278,11 @@ foreach (split("\n",$code)) { + s/\`([^\`]*)\`/eval $1/geo; + + (s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or +- (m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or ++ (m/\b(eor|ext|mov|tbl)\b/ and (s/\.4s/\.16b/g or 1)) or + (s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or + (m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or ++ (m/\b(dup|ld1)\b/ and (s/\.4(s}?\[[0-3]\])/.$1/g or 1)) or ++ (s/\b(zip[12])\.64\b/$1/ and (s/\.4s/\.2d/g or 1)) or + (s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1)); + + #s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo; +diff -up openssl-1.1.1c/crypto/modes/asm/ghashv8-armx.pl.arm-update openssl-1.1.1c/crypto/modes/asm/ghashv8-armx.pl +--- openssl-1.1.1c/crypto/modes/asm/ghashv8-armx.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/modes/asm/ghashv8-armx.pl 2019-11-20 11:36:22.389506155 +0100 +@@ -42,6 +42,7 @@ + # Denver 0.51 0.65 6.02 + # Mongoose 0.65 1.10 8.06 + # Kryo 0.76 1.16 8.00 ++# ThunderX2 1.05 + # + # (*) presented for reference/comparison purposes; + +diff -up openssl-1.1.1c/crypto/poly1305/asm/poly1305-armv8.pl.arm-update openssl-1.1.1c/crypto/poly1305/asm/poly1305-armv8.pl +--- openssl-1.1.1c/crypto/poly1305/asm/poly1305-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/poly1305/asm/poly1305-armv8.pl 2019-11-20 11:36:22.390506137 +0100 +@@ -29,6 +29,7 @@ + # X-Gene 2.13/+68% 2.27 + # Mongoose 1.77/+75% 1.12 + # Kryo 2.70/+55% 1.13 ++# ThunderX2 1.17/+95% 1.36 + # + # (*) estimate based on resources availability is less than 1.0, + # i.e. measured result is worse than expected, presumably binary +diff -up openssl-1.1.1c/crypto/sha/asm/keccak1600-armv8.pl.arm-update openssl-1.1.1c/crypto/sha/asm/keccak1600-armv8.pl +--- openssl-1.1.1c/crypto/sha/asm/keccak1600-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/sha/asm/keccak1600-armv8.pl 2019-11-20 11:36:22.390506137 +0100 +@@ -51,6 +51,7 @@ + # Kryo 12 + # Denver 7.8 + # Apple A7 7.2 ++# ThunderX2 9.7 + # + # (*) Corresponds to SHA3-256. No improvement coefficients are listed + # because they vary too much from compiler to compiler. Newer +diff -up openssl-1.1.1c/crypto/sha/asm/sha1-armv8.pl.arm-update openssl-1.1.1c/crypto/sha/asm/sha1-armv8.pl +--- openssl-1.1.1c/crypto/sha/asm/sha1-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/sha/asm/sha1-armv8.pl 2019-11-20 11:36:22.390506137 +0100 +@@ -27,6 +27,7 @@ + # X-Gene 8.80 (+200%) + # Mongoose 2.05 6.50 (+160%) + # Kryo 1.88 8.00 (+90%) ++# ThunderX2 2.64 6.36 (+150%) + # + # (*) Software results are presented mostly for reference purposes. + # (**) Keep in mind that Denver relies on binary translation, which +diff -up openssl-1.1.1c/crypto/sha/asm/sha512-armv8.pl.arm-update openssl-1.1.1c/crypto/sha/asm/sha512-armv8.pl +--- openssl-1.1.1c/crypto/sha/asm/sha512-armv8.pl.arm-update 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/sha/asm/sha512-armv8.pl 2019-11-20 11:36:22.390506137 +0100 +@@ -28,6 +28,7 @@ + # X-Gene 20.0 (+100%) 12.8 (+300%(***)) + # Mongoose 2.36 13.0 (+50%) 8.36 (+33%) + # Kryo 1.92 17.4 (+30%) 11.2 (+8%) ++# ThunderX2 2.54 13.2 (+40%) 8.40 (+18%) + # + # (*) Software SHA256 results are of lesser relevance, presented + # mostly for informational purposes. diff --git a/SOURCES/openssl-1.1.1-cve-2019-1547.patch b/SOURCES/openssl-1.1.1-cve-2019-1547.patch new file mode 100644 index 0000000..b4e2a05 --- /dev/null +++ b/SOURCES/openssl-1.1.1-cve-2019-1547.patch @@ -0,0 +1,171 @@ +From 30c22fa8b1d840036b8e203585738df62a03cec8 Mon Sep 17 00:00:00 2001 +From: Billy Brumley +Date: Thu, 5 Sep 2019 21:25:37 +0300 +Subject: [PATCH] [crypto/ec] for ECC parameters with NULL or zero cofactor, + compute it + +The cofactor argument to EC_GROUP_set_generator is optional, and SCA +mitigations for ECC currently use it. So the library currently falls +back to very old SCA-vulnerable code if the cofactor is not present. + +This PR allows EC_GROUP_set_generator to compute the cofactor for all +curves of cryptographic interest. Steering scalar multiplication to more +SCA-robust code. + +This issue affects persisted private keys in explicit parameter form, +where the (optional) cofactor field is zero or absent. + +It also affects curves not built-in to the library, but constructed +programatically with explicit parameters, then calling +EC_GROUP_set_generator with a nonsensical value (NULL, zero). + +The very old scalar multiplication code is known to be vulnerable to +local uarch attacks, outside of the OpenSSL threat model. New results +suggest the code path is also vulnerable to traditional wall clock +timing attacks. + +CVE-2019-1547 + +Reviewed-by: Matt Caswell +Reviewed-by: Tomas Mraz +Reviewed-by: Nicola Tuveri +(Merged from https://github.com/openssl/openssl/pull/9781) +--- + crypto/ec/ec_lib.c | 103 ++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 96 insertions(+), 7 deletions(-) + +diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c +index 8cab5a5061..1289c8608e 100644 +--- a/crypto/ec/ec_lib.c ++++ b/crypto/ec/ec_lib.c +@@ -265,6 +265,67 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth) + + static int ec_precompute_mont_data(EC_GROUP *); + ++/*- ++ * Try computing cofactor from the generator order (n) and field cardinality (q). ++ * This works for all curves of cryptographic interest. ++ * ++ * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q) ++ * h_min = (q + 1 - 2*sqrt(q))/n ++ * h_max = (q + 1 + 2*sqrt(q))/n ++ * h_max - h_min = 4*sqrt(q)/n ++ * So if n > 4*sqrt(q) holds, there is only one possible value for h: ++ * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil ++ * ++ * Otherwise, zero cofactor and return success. ++ */ ++static int ec_guess_cofactor(EC_GROUP *group) { ++ int ret = 0; ++ BN_CTX *ctx = NULL; ++ BIGNUM *q = NULL; ++ ++ /*- ++ * If the cofactor is too large, we cannot guess it. ++ * The RHS of below is a strict overestimate of lg(4 * sqrt(q)) ++ */ ++ if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) { ++ /* default to 0 */ ++ BN_zero(group->cofactor); ++ /* return success */ ++ return 1; ++ } ++ ++ if ((ctx = BN_CTX_new()) == NULL) ++ return 0; ++ ++ BN_CTX_start(ctx); ++ if ((q = BN_CTX_get(ctx)) == NULL) ++ goto err; ++ ++ /* set q = 2**m for binary fields; q = p otherwise */ ++ if (group->meth->field_type == NID_X9_62_characteristic_two_field) { ++ BN_zero(q); ++ if (!BN_set_bit(q, BN_num_bits(group->field) - 1)) ++ goto err; ++ } else { ++ if (!BN_copy(q, group->field)) ++ goto err; ++ } ++ ++ /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */ ++ if (!BN_rshift1(group->cofactor, group->order) /* n/2 */ ++ || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */ ++ /* q + 1 + n/2 */ ++ || !BN_add(group->cofactor, group->cofactor, BN_value_one()) ++ /* (q + 1 + n/2)/n */ ++ || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx)) ++ goto err; ++ ret = 1; ++ err: ++ BN_CTX_end(ctx); ++ BN_CTX_free(ctx); ++ return ret; ++} ++ + int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) + { +@@ -273,6 +334,34 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + 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); ++ return 0; ++ } ++ ++ /*- ++ * - require order >= 1 ++ * - enforce upper bound due to Hasse thm: order can be no more than one bit ++ * longer than field cardinality ++ */ ++ 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); ++ return 0; ++ } ++ ++ /*- ++ * Unfortunately the cofactor is an optional field in many standards. ++ * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor". ++ * 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); ++ return 0; ++ } ++ + if (group->generator == NULL) { + group->generator = EC_POINT_new(group); + if (group->generator == NULL) +@@ -281,17 +370,17 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + if (!EC_POINT_copy(group->generator, generator)) + return 0; + +- if (order != NULL) { +- if (!BN_copy(group->order, order)) +- return 0; +- } else +- BN_zero(group->order); ++ if (!BN_copy(group->order, order)) ++ return 0; + +- if (cofactor != NULL) { ++ /* Either take the provided positive cofactor, or try to compute it */ ++ if (cofactor != NULL && !BN_is_zero(cofactor)) { + if (!BN_copy(group->cofactor, cofactor)) + return 0; +- } else ++ } else if (!ec_guess_cofactor(group)) { + BN_zero(group->cofactor); ++ return 0; ++ } + + /* + * Some groups have an order with +-- +2.20.1 + diff --git a/SOURCES/openssl-1.1.1-cve-2019-1549.patch b/SOURCES/openssl-1.1.1-cve-2019-1549.patch new file mode 100644 index 0000000..787a2a3 --- /dev/null +++ b/SOURCES/openssl-1.1.1-cve-2019-1549.patch @@ -0,0 +1,300 @@ +diff -up openssl-1.1.1c/crypto/fips/fips.c.fork-safety openssl-1.1.1c/crypto/fips/fips.c +--- openssl-1.1.1c/crypto/fips/fips.c.fork-safety 2019-11-20 11:36:22.343506961 +0100 ++++ openssl-1.1.1c/crypto/fips/fips.c 2019-11-21 17:44:32.920776849 +0100 +@@ -472,7 +472,7 @@ int FIPS_module_mode_set(int onoff) + + fips_set_mode(onoff); + /* force RNG reseed with entropy from getrandom() on next call */ +- rand_fork(); ++ rand_force_reseed(); + + ret = 1; + goto end; +diff -up openssl-1.1.1c/crypto/include/internal/rand_int.h.fork-safety openssl-1.1.1c/crypto/include/internal/rand_int.h +--- openssl-1.1.1c/crypto/include/internal/rand_int.h.fork-safety 2019-11-20 11:36:22.382506277 +0100 ++++ openssl-1.1.1c/crypto/include/internal/rand_int.h 2019-11-21 17:45:42.102456672 +0100 +@@ -24,9 +24,9 @@ + typedef struct rand_pool_st RAND_POOL; + + void rand_cleanup_int(void); ++void rand_force_reseed(void); + void rand_drbg_cleanup_int(void); + void drbg_delete_thread_state(void); +-void rand_fork(void); + + /* Hardware-based seeding functions. */ + size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool); +diff -up openssl-1.1.1c/crypto/init.c.fork-safety openssl-1.1.1c/crypto/init.c +--- openssl-1.1.1c/crypto/init.c.fork-safety 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/init.c 2019-11-21 17:34:13.478597398 +0100 +@@ -847,6 +847,5 @@ void OPENSSL_fork_parent(void) + + void OPENSSL_fork_child(void) + { +- rand_fork(); + } + #endif +diff -up openssl-1.1.1c/crypto/rand/drbg_lib.c.fork-safety openssl-1.1.1c/crypto/rand/drbg_lib.c +--- openssl-1.1.1c/crypto/rand/drbg_lib.c.fork-safety 2019-11-20 11:36:22.383506260 +0100 ++++ openssl-1.1.1c/crypto/rand/drbg_lib.c 2019-11-21 17:46:37.583397431 +0100 +@@ -197,7 +197,7 @@ static RAND_DRBG *rand_drbg_new(int secu + } + + drbg->secure = secure && CRYPTO_secure_allocated(drbg); +- drbg->fork_count = rand_fork_count; ++ drbg->fork_id = openssl_get_fork_id(); + drbg->parent = parent; + + if (parent == NULL) { +@@ -583,6 +583,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, + int prediction_resistance, + const unsigned char *adin, size_t adinlen) + { ++ int fork_id; + int reseed_required = 0; + + if (drbg->state != DRBG_READY) { +@@ -608,8 +609,10 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, + return 0; + } + +- if (drbg->fork_count != rand_fork_count) { +- drbg->fork_count = rand_fork_count; ++ fork_id = openssl_get_fork_id(); ++ ++ if (drbg->fork_id != fork_id) { ++ drbg->fork_id = fork_id; + reseed_required = 1; + } + +@@ -1011,6 +1014,20 @@ size_t rand_drbg_seedlen(RAND_DRBG *drbg + return min_entropy > min_entropylen ? min_entropy : min_entropylen; + } + ++void rand_force_reseed(void) ++{ ++ RAND_DRBG *drbg; ++ ++ drbg = RAND_DRBG_get0_master(); ++ drbg->fork_id = 0; ++ ++ drbg = RAND_DRBG_get0_private(); ++ drbg->fork_id = 0; ++ ++ drbg = RAND_DRBG_get0_public(); ++ drbg->fork_id = 0; ++} ++ + /* Implements the default OpenSSL RAND_add() method */ + static int drbg_add(const void *buf, int num, double randomness) + { +diff -up openssl-1.1.1c/crypto/rand/rand_lcl.h.fork-safety openssl-1.1.1c/crypto/rand/rand_lcl.h +--- openssl-1.1.1c/crypto/rand/rand_lcl.h.fork-safety 2019-11-20 11:36:22.383506260 +0100 ++++ openssl-1.1.1c/crypto/rand/rand_lcl.h 2019-11-21 17:34:13.485597265 +0100 +@@ -176,12 +176,12 @@ struct rand_drbg_st { + int secure; /* 1: allocated on the secure heap, 0: otherwise */ + int type; /* the nid of the underlying algorithm */ + /* +- * Stores the value of the rand_fork_count global as of when we last +- * reseeded. The DRBG reseeds automatically whenever drbg->fork_count != +- * rand_fork_count. Used to provide fork-safety and reseed this DRBG in +- * the child process. ++ * Stores the return value of openssl_get_fork_id() as of when we last ++ * reseeded. The DRBG reseeds automatically whenever drbg->fork_id != ++ * openssl_get_fork_id(). Used to provide fork-safety and reseed this ++ * DRBG in the child process. + */ +- int fork_count; ++ int fork_id; + unsigned short flags; /* various external flags */ + + /* +@@ -273,19 +273,6 @@ struct rand_drbg_st { + /* The global RAND method, and the global buffer and DRBG instance. */ + extern RAND_METHOD rand_meth; + +-/* +- * A "generation count" of forks. Incremented in the child process after a +- * fork. Since rand_fork_count is increment-only, and only ever written to in +- * the child process of the fork, which is guaranteed to be single-threaded, no +- * locking is needed for normal (read) accesses; the rest of pthread fork +- * processing is assumed to introduce the necessary memory barriers. Sibling +- * children of a given parent will produce duplicate values, but this is not +- * problematic because the reseeding process pulls input from the system CSPRNG +- * and/or other global sources, so the siblings will end up generating +- * different output streams. +- */ +-extern int rand_fork_count; +- + /* DRBG helpers */ + int rand_drbg_restart(RAND_DRBG *drbg, + const unsigned char *buffer, size_t len, size_t entropy); +diff -up openssl-1.1.1c/crypto/rand/rand_lib.c.fork-safety openssl-1.1.1c/crypto/rand/rand_lib.c +--- openssl-1.1.1c/crypto/rand/rand_lib.c.fork-safety 2019-11-20 11:36:22.374506418 +0100 ++++ openssl-1.1.1c/crypto/rand/rand_lib.c 2019-11-21 17:34:13.487597227 +0100 +@@ -30,8 +30,6 @@ static CRYPTO_RWLOCK *rand_meth_lock; + static const RAND_METHOD *default_RAND_meth; + static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; + +-int rand_fork_count; +- + static CRYPTO_RWLOCK *rand_nonce_lock; + static int rand_nonce_count; + +@@ -303,11 +301,6 @@ void rand_drbg_cleanup_additional_data(R + rand_pool_reattach(pool, out); + } + +-void rand_fork(void) +-{ +- rand_fork_count++; +-} +- + DEFINE_RUN_ONCE_STATIC(do_rand_init) + { + #ifndef OPENSSL_NO_ENGINE +diff -up openssl-1.1.1c/crypto/threads_none.c.fork-safety openssl-1.1.1c/crypto/threads_none.c +--- openssl-1.1.1c/crypto/threads_none.c.fork-safety 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/threads_none.c 2019-11-21 17:34:13.489597189 +0100 +@@ -12,6 +12,11 @@ + + #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) + ++# if defined(OPENSSL_SYS_UNIX) ++# include ++# include ++# endif ++ + CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) + { + CRYPTO_RWLOCK *lock; +@@ -133,4 +138,12 @@ int openssl_init_fork_handlers(void) + return 0; + } + ++int openssl_get_fork_id(void) ++{ ++# if defined(OPENSSL_SYS_UNIX) ++ return getpid(); ++# else ++ return 0; ++# endif ++} + #endif +diff -up openssl-1.1.1c/crypto/threads_pthread.c.fork-safety openssl-1.1.1c/crypto/threads_pthread.c +--- openssl-1.1.1c/crypto/threads_pthread.c.fork-safety 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/threads_pthread.c 2019-11-21 17:34:13.492597131 +0100 +@@ -12,6 +12,11 @@ + + #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS) + ++# if defined(OPENSSL_SYS_UNIX) ++# include ++# include ++#endif ++ + # ifdef PTHREAD_RWLOCK_INITIALIZER + # define USE_RWLOCK + # endif +@@ -193,4 +198,9 @@ int openssl_init_fork_handlers(void) + # endif + return 0; + } ++ ++int openssl_get_fork_id(void) ++{ ++ return getpid(); ++} + #endif +diff -up openssl-1.1.1c/crypto/threads_win.c.fork-safety openssl-1.1.1c/crypto/threads_win.c +--- openssl-1.1.1c/crypto/threads_win.c.fork-safety 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/threads_win.c 2019-11-21 17:34:13.495597074 +0100 +@@ -164,4 +164,8 @@ int openssl_init_fork_handlers(void) + return 0; + } + ++int openssl_get_fork_id(void) ++{ ++ return 0; ++} + #endif +diff -up openssl-1.1.1c/include/internal/cryptlib.h.fork-safety openssl-1.1.1c/include/internal/cryptlib.h +--- openssl-1.1.1c/include/internal/cryptlib.h.fork-safety 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/include/internal/cryptlib.h 2019-11-21 17:34:13.497597036 +0100 +@@ -80,6 +80,7 @@ extern unsigned int OPENSSL_ia32cap_P[]; + void OPENSSL_showfatal(const char *fmta, ...); + void crypto_cleanup_all_ex_data_int(void); + int openssl_init_fork_handlers(void); ++int openssl_get_fork_id(void); + + char *ossl_safe_getenv(const char *name); + +diff -up openssl-1.1.1c/test/drbgtest.c.fork-safety openssl-1.1.1c/test/drbgtest.c +--- openssl-1.1.1c/test/drbgtest.c.fork-safety 2019-11-20 11:36:22.384506242 +0100 ++++ openssl-1.1.1c/test/drbgtest.c 2019-11-21 17:34:13.499596998 +0100 +@@ -22,6 +22,13 @@ + # include + #endif + ++ ++#if defined(OPENSSL_SYS_UNIX) ++# include ++# include ++# include ++#endif ++ + #include "testutil.h" + #include "drbgtest.h" + +@@ -696,6 +703,40 @@ static int test_drbg_reseed(int expect_s + return 1; + } + ++ ++#if defined(OPENSSL_SYS_UNIX) ++/* ++ * Test whether master, public and private DRBG are reseeded after ++ * forking the process. ++ */ ++static int test_drbg_reseed_after_fork(RAND_DRBG *master, ++ RAND_DRBG *public, ++ RAND_DRBG *private) ++{ ++ pid_t pid; ++ int status=0; ++ ++ pid = fork(); ++ if (!TEST_int_ge(pid, 0)) ++ return 0; ++ ++ if (pid > 0) { ++ /* I'm the parent; wait for the child and check its exit code */ ++ return TEST_int_eq(waitpid(pid, &status, 0), pid) && TEST_int_eq(status, 0); ++ } ++ ++ /* I'm the child; check whether all three DRBGs reseed. */ ++ if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) ++ status = 1; ++ ++ /* Remove hooks */ ++ unhook_drbg(master); ++ unhook_drbg(public); ++ unhook_drbg(private); ++ exit(status); ++} ++#endif ++ + /* + * Test whether the default rand_method (RAND_OpenSSL()) is + * setup correctly, in particular whether reseeding works +@@ -786,6 +827,10 @@ static int test_rand_drbg_reseed(void) + goto error; + reset_drbg_hook_ctx(); + ++#if defined(OPENSSL_SYS_UNIX) ++ if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) ++ goto error; ++#endif + + /* fill 'randomness' buffer with some arbitrary data */ + memset(rand_add_buf, 'r', sizeof(rand_add_buf)); diff --git a/SOURCES/openssl-1.1.1-cve-2019-1563.patch b/SOURCES/openssl-1.1.1-cve-2019-1563.patch new file mode 100644 index 0000000..4c0f533 --- /dev/null +++ b/SOURCES/openssl-1.1.1-cve-2019-1563.patch @@ -0,0 +1,147 @@ +From 08229ad838c50f644d7e928e2eef147b4308ad64 Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Sun, 1 Sep 2019 00:16:28 +0200 +Subject: [PATCH] Fix a padding oracle in PKCS7_dataDecode and + CMS_decrypt_set1_pkey + +An attack is simple, if the first CMS_recipientInfo is valid but the +second CMS_recipientInfo is chosen ciphertext. If the second +recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct +encryption key will be replaced by garbage, and the message cannot be +decoded, but if the RSA decryption fails, the correct encryption key is +used and the recipient will not notice the attack. + +As a work around for this potential attack the length of the decrypted +key must be equal to the cipher default key length, in case the +certifiate is not given and all recipientInfo are tried out. + +The old behaviour can be re-enabled in the CMS code by setting the +CMS_DEBUG_DECRYPT flag. + +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/9777) + +(cherry picked from commit 5840ed0cd1e6487d247efbc1a04136a41d7b3a37) +--- + crypto/cms/cms_env.c | 18 +++++++++++++++++- + crypto/cms/cms_lcl.h | 2 ++ + crypto/cms/cms_smime.c | 4 ++++ + crypto/pkcs7/pk7_doit.c | 12 ++++++++---- + 5 files changed, 45 insertions(+), 5 deletions(-) + +diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c +index bb95af75e3..25df1c40b1 100644 +--- a/crypto/cms/cms_env.c ++++ b/crypto/cms/cms_env.c +@@ -363,6 +363,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + unsigned char *ek = NULL; + size_t eklen; + int ret = 0; ++ size_t fixlen = 0; + CMS_EncryptedContentInfo *ec; + ec = cms->d.envelopedData->encryptedContentInfo; + +@@ -371,6 +372,19 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + return 0; + } + ++ if (cms->d.envelopedData->encryptedContentInfo->havenocert ++ && !cms->d.envelopedData->encryptedContentInfo->debug) { ++ X509_ALGOR *calg = ec->contentEncryptionAlgorithm; ++ const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm); ++ ++ if (ciph == NULL) { ++ CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER); ++ return 0; ++ } ++ ++ fixlen = EVP_CIPHER_key_length(ciph); ++ } ++ + ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ktri->pctx == NULL) + return 0; +@@ -401,7 +415,9 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + + if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, + ktri->encryptedKey->data, +- ktri->encryptedKey->length) <= 0) { ++ ktri->encryptedKey->length) <= 0 ++ || eklen == 0 ++ || (fixlen != 0 && eklen != fixlen)) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); + goto err; + } +diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h +index b5c06b7f6c..8eddb02493 100644 +--- a/crypto/cms/cms_lcl.h ++++ b/crypto/cms/cms_lcl.h +@@ -125,6 +125,8 @@ struct CMS_EncryptedContentInfo_st { + size_t keylen; + /* Set to 1 if we are debugging decrypt and don't fake keys for MMA */ + int debug; ++ /* Set to 1 if we have no cert and need extra safety measures for MMA */ ++ int havenocert; + }; + + struct CMS_RecipientInfo_st { +diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c +index 5dcf803f4b..3a26108b8c 100644 +--- a/crypto/cms/cms_smime.c ++++ b/crypto/cms/cms_smime.c +@@ -743,6 +743,10 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, + cms->d.envelopedData->encryptedContentInfo->debug = 1; + else + cms->d.envelopedData->encryptedContentInfo->debug = 0; ++ if (!cert) ++ cms->d.envelopedData->encryptedContentInfo->havenocert = 1; ++ else ++ cms->d.envelopedData->encryptedContentInfo->havenocert = 0; + if (!pk && !cert && !dcont && !out) + return 1; + if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert)) +diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c +index ee08e602a1..15a6160cfe 100644 +--- a/crypto/pkcs7/pk7_doit.c ++++ b/crypto/pkcs7/pk7_doit.c +@@ -137,7 +137,8 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, + } + + static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, +- PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) ++ PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey, ++ size_t fixlen) + { + EVP_PKEY_CTX *pctx = NULL; + unsigned char *ek = NULL; +@@ -170,7 +171,9 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, + } + + if (EVP_PKEY_decrypt(pctx, ek, &eklen, +- ri->enc_key->data, ri->enc_key->length) <= 0) { ++ ri->enc_key->data, ri->enc_key->length) <= 0 ++ || eklen == 0 ++ || (fixlen != 0 && eklen != fixlen)) { + ret = 0; + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); + goto err; +@@ -499,13 +502,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) + for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { + ri = sk_PKCS7_RECIP_INFO_value(rsk, i); + +- if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) ++ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, ++ EVP_CIPHER_key_length(evp_cipher)) < 0) + goto err; + ERR_clear_error(); + } + } else { + /* Only exit on fatal errors, not decrypt failure */ +- if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) ++ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0) + goto err; + ERR_clear_error(); + } +-- +2.20.1 + diff --git a/SOURCES/openssl-1.1.1-edk2-build.patch b/SOURCES/openssl-1.1.1-edk2-build.patch new file mode 100644 index 0000000..01045a3 --- /dev/null +++ b/SOURCES/openssl-1.1.1-edk2-build.patch @@ -0,0 +1,68 @@ +diff -up openssl-1.1.1c/crypto/evp/pkey_kdf.c.edk2-build openssl-1.1.1c/crypto/evp/pkey_kdf.c +--- openssl-1.1.1c/crypto/evp/pkey_kdf.c.edk2-build 2019-11-14 16:25:09.437914854 +0100 ++++ openssl-1.1.1c/crypto/evp/pkey_kdf.c 2019-11-15 14:52:40.216905772 +0100 +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include "internal/numbers.h" + #include "internal/evp_int.h" + + static int pkey_kdf_init(EVP_PKEY_CTX *ctx) +diff -up openssl-1.1.1c/crypto/include/internal/fips_int.h.edk2-build openssl-1.1.1c/crypto/include/internal/fips_int.h +--- openssl-1.1.1c/crypto/include/internal/fips_int.h.edk2-build 2019-11-14 16:25:09.430914981 +0100 ++++ openssl-1.1.1c/crypto/include/internal/fips_int.h 2019-11-15 14:48:02.489936610 +0100 +@@ -50,10 +50,6 @@ + #include + #include + +-#ifndef OPENSSL_FIPS +-# error FIPS is disabled. +-#endif +- + #ifdef OPENSSL_FIPS + + int FIPS_module_mode_set(int onoff); +@@ -97,4 +93,8 @@ void fips_set_selftest_fail(void); + + void FIPS_get_timevec(unsigned char *buf, unsigned long *pctr); + ++#else ++ ++# define fips_in_post() 0 ++ + #endif +diff -up openssl-1.1.1c/crypto/kdf/hkdf.c.edk2-build openssl-1.1.1c/crypto/kdf/hkdf.c +--- openssl-1.1.1c/crypto/kdf/hkdf.c.edk2-build 2019-11-14 16:25:09.438914836 +0100 ++++ openssl-1.1.1c/crypto/kdf/hkdf.c 2019-11-15 14:48:53.360015134 +0100 +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include "internal/numbers.h" + #include "internal/cryptlib.h" + #include "internal/evp_int.h" + #include "kdf_local.h" +diff -up openssl-1.1.1c/crypto/kdf/sshkdf.c.edk2-build openssl-1.1.1c/crypto/kdf/sshkdf.c +--- openssl-1.1.1c/crypto/kdf/sshkdf.c.edk2-build 2019-11-14 16:25:09.452914583 +0100 ++++ openssl-1.1.1c/crypto/kdf/sshkdf.c 2019-11-15 14:53:14.769279878 +0100 +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include "internal/numbers.h" + #include "internal/cryptlib.h" + #include "internal/evp_int.h" + #include "kdf_local.h" +diff -up openssl-1.1.1c/crypto/rand/rand_unix.c.edk2-build openssl-1.1.1c/crypto/rand/rand_unix.c +--- openssl-1.1.1c/crypto/rand/rand_unix.c.edk2-build 2019-11-14 16:25:09.430914981 +0100 ++++ openssl-1.1.1c/crypto/rand/rand_unix.c 2019-11-15 14:51:41.634966941 +0100 +@@ -19,7 +19,7 @@ + #include "internal/fips_int.h" + #include + #include "internal/dso.h" +-#if defined(__linux) ++#if defined(__linux) && !defined(OPENSSL_SYS_UEFI) + # include + # include + #endif diff --git a/SOURCES/openssl-1.1.1-fips-curves.patch b/SOURCES/openssl-1.1.1-fips-curves.patch new file mode 100644 index 0000000..038bbbf --- /dev/null +++ b/SOURCES/openssl-1.1.1-fips-curves.patch @@ -0,0 +1,212 @@ +diff -up openssl-1.1.1c/crypto/ec/ec_curve.c.fips-curves openssl-1.1.1c/crypto/ec/ec_curve.c +--- openssl-1.1.1c/crypto/ec/ec_curve.c.fips-curves 2019-11-25 13:18:40.719532357 +0100 ++++ openssl-1.1.1c/crypto/ec/ec_curve.c 2019-11-25 13:18:40.765531559 +0100 +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include "internal/nelem.h" + + typedef struct { +@@ -237,6 +238,7 @@ static const struct { + + typedef struct _ec_list_element_st { + int nid; ++ int fips_allowed; + const EC_CURVE_DATA *data; + const EC_METHOD *(*meth) (void); + const char *comment; +@@ -246,23 +248,23 @@ static const ec_list_element curve_list[ + /* prime field curves */ + /* secg curves */ + #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +- {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, ++ {NID_secp224r1, 1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, + "NIST/SECG curve over a 224 bit prime field"}, + #else +- {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, ++ {NID_secp224r1, 1, &_EC_NIST_PRIME_224.h, 0, + "NIST/SECG curve over a 224 bit prime field"}, + #endif +- {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, ++ {NID_secp256k1, 0, &_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, ++ {NID_secp384r1, 1, &_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, ++ {NID_secp521r1, 1, &_EC_NIST_PRIME_521.h, + # if defined(S390X_EC_ASM) + EC_GFp_s390x_nistp521_method, + # elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) +@@ -272,7 +274,7 @@ static const ec_list_element curve_list[ + # endif + "NIST/SECG curve over a 521 bit prime field"}, + /* X9.62 curves */ +- {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, ++ {NID_X9_62_prime256v1, 1, &_EC_X9_62_PRIME_256V1.h, + #if defined(ECP_NISTZ256_ASM) + EC_GFp_nistz256_method, + # elif defined(S390X_EC_ASM) +@@ -404,6 +406,10 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int + + for (i = 0; i < curve_list_length; i++) + if (curve_list[i].nid == nid) { ++ if (!curve_list[i].fips_allowed && FIPS_mode()) { ++ ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_NOT_A_NIST_PRIME); ++ return NULL; ++ } + ret = ec_group_new_from_data(curve_list[i]); + break; + } +@@ -418,19 +424,31 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int + + size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) + { +- size_t i, min; ++ size_t i, j, num; ++ int fips_mode = FIPS_mode(); + +- if (r == NULL || nitems == 0) +- return curve_list_length; ++ num = curve_list_length; ++ if (fips_mode) ++ for (i = 0; i < curve_list_length; i++) { ++ if (!curve_list[i].fips_allowed) ++ --num; ++ } + +- min = nitems < curve_list_length ? nitems : curve_list_length; ++ if (r == NULL || nitems == 0) { ++ return num; ++ } + +- for (i = 0; i < min; i++) { +- r[i].nid = curve_list[i].nid; +- r[i].comment = curve_list[i].comment; ++ for (i = 0, j = 0; i < curve_list_length; i++) { ++ if (j >= nitems) ++ break; ++ if (!fips_mode || curve_list[i].fips_allowed) { ++ r[j].nid = curve_list[i].nid; ++ r[j].comment = curve_list[i].comment; ++ ++j; ++ } + } + +- return curve_list_length; ++ return num; + } + + /* Functions to translate between common NIST curve names and NIDs */ +diff -up openssl-1.1.1c/ssl/t1_lib.c.fips-curves openssl-1.1.1c/ssl/t1_lib.c +--- openssl-1.1.1c/ssl/t1_lib.c.fips-curves 2019-11-25 13:18:40.658533416 +0100 ++++ openssl-1.1.1c/ssl/t1_lib.c 2019-11-26 17:57:15.014742428 +0100 +@@ -20,6 +20,7 @@ + #include "internal/nelem.h" + #include "ssl_locl.h" + #include ++#include + + SSL3_ENC_METHOD const TLSv1_enc_data = { + tls1_enc, +@@ -676,6 +677,36 @@ static const uint16_t tls12_sigalgs[] = + #endif + }; + ++static const uint16_t tls12_fips_sigalgs[] = { ++#ifndef OPENSSL_NO_EC ++ TLSEXT_SIGALG_ecdsa_secp256r1_sha256, ++ TLSEXT_SIGALG_ecdsa_secp384r1_sha384, ++ TLSEXT_SIGALG_ecdsa_secp521r1_sha512, ++#endif ++ ++ TLSEXT_SIGALG_rsa_pss_pss_sha256, ++ TLSEXT_SIGALG_rsa_pss_pss_sha384, ++ TLSEXT_SIGALG_rsa_pss_pss_sha512, ++ TLSEXT_SIGALG_rsa_pss_rsae_sha256, ++ TLSEXT_SIGALG_rsa_pss_rsae_sha384, ++ TLSEXT_SIGALG_rsa_pss_rsae_sha512, ++ ++ TLSEXT_SIGALG_rsa_pkcs1_sha256, ++ TLSEXT_SIGALG_rsa_pkcs1_sha384, ++ TLSEXT_SIGALG_rsa_pkcs1_sha512, ++ ++#ifndef OPENSSL_NO_EC ++ TLSEXT_SIGALG_ecdsa_sha224, ++#endif ++ TLSEXT_SIGALG_rsa_pkcs1_sha224, ++#ifndef OPENSSL_NO_DSA ++ TLSEXT_SIGALG_dsa_sha224, ++ TLSEXT_SIGALG_dsa_sha256, ++ TLSEXT_SIGALG_dsa_sha384, ++ TLSEXT_SIGALG_dsa_sha512, ++#endif ++}; ++ + #ifndef OPENSSL_NO_EC + static const uint16_t suiteb_sigalgs[] = { + TLSEXT_SIGALG_ecdsa_secp256r1_sha256, +@@ -890,8 +921,11 @@ static const SIGALG_LOOKUP *tls1_get_leg + if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg)) + return NULL; + if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) { +- const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]); ++ const SIGALG_LOOKUP *lu; + ++ if (FIPS_mode()) /* We do not allow SHA1 signatures in FIPS mode */ ++ return NULL; ++ lu = tls1_lookup_sigalg(tls_default_sigalg[idx]); + if (!tls1_lookup_md(lu, NULL)) + return NULL; + return lu; +@@ -945,6 +979,9 @@ size_t tls12_get_psigalgs(SSL *s, int se + } else if (s->cert->conf_sigalgs) { + *psigs = s->cert->conf_sigalgs; + return s->cert->conf_sigalgslen; ++ } else if (FIPS_mode()) { ++ *psigs = tls12_fips_sigalgs; ++ return OSSL_NELEM(tls12_fips_sigalgs); + } else { + *psigs = tls12_sigalgs; + return OSSL_NELEM(tls12_sigalgs); +@@ -964,6 +1001,9 @@ int tls_check_sigalg_curve(const SSL *s, + if (s->cert->conf_sigalgs) { + sigs = s->cert->conf_sigalgs; + siglen = s->cert->conf_sigalgslen; ++ } else if (FIPS_mode()) { ++ sigs = tls12_fips_sigalgs; ++ siglen = OSSL_NELEM(tls12_fips_sigalgs); + } else { + sigs = tls12_sigalgs; + siglen = OSSL_NELEM(tls12_sigalgs); +@@ -1582,6 +1622,8 @@ static int tls12_sigalg_allowed(SSL *s, + if (lu->sig == NID_id_GostR3410_2012_256 + || lu->sig == NID_id_GostR3410_2012_512 + || lu->sig == NID_id_GostR3410_2001) { ++ if (FIPS_mode()) ++ return 0; + /* We never allow GOST sig algs on the server with TLSv1.3 */ + if (s->server && SSL_IS_TLS13(s)) + return 0; +@@ -2720,6 +2762,13 @@ int tls_choose_sigalg(SSL *s, int fatale + const uint16_t *sent_sigs; + size_t sent_sigslen; + ++ if (fatalerrs && FIPS_mode()) { ++ /* There are no suitable legacy algorithms in FIPS mode */ ++ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ++ SSL_F_TLS_CHOOSE_SIGALG, ++ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM); ++ return 0; ++ } + if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) { + if (!fatalerrs) + return 1; diff --git a/SOURCES/openssl-1.1.1-fips.patch b/SOURCES/openssl-1.1.1-fips.patch index c565896..8204506 100644 --- a/SOURCES/openssl-1.1.1-fips.patch +++ b/SOURCES/openssl-1.1.1-fips.patch @@ -60,7 +60,7 @@ diff -up openssl-1.1.1b/apps/speed.c.fips openssl-1.1.1b/apps/speed.c eddsa_doit[i] = 2; continue; } -@@ -1734,23 +1739,30 @@ int speed_main(int argc, char **argv) +@@ -1734,23 +1739,31 @@ int speed_main(int argc, char **argv) /* No parameters; turn on everything. */ if ((argc == 0) && !doit[D_EVP]) { for (i = 0; i < ALGOR_NUM; i++) @@ -87,9 +87,11 @@ diff -up openssl-1.1.1b/apps/speed.c.fips openssl-1.1.1b/apps/speed.c for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++) ecdsa_doit[loop] = 1; for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++) - ecdh_doit[loop] = 1; +- ecdh_doit[loop] = 1; - for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) - eddsa_doit[loop] = 1; ++ if(!FIPS_mode() || (loop != R_EC_X25519 && loop != R_EC_X448)) ++ ecdh_doit[loop] = 1; + if (!FIPS_mode()) + for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++) + eddsa_doit[loop] = 1; @@ -459,7 +461,7 @@ diff -up openssl-1.1.1b/crypto/dsa/dsa_gen.c.fips openssl-1.1.1b/crypto/dsa/dsa_ + goto err; + } + -+ if (FIPS_mode() && (L != 1024 || N != 160) && ++ if (FIPS_mode() && + (L != 2048 || N != 224) && (L != 2048 || N != 256) && + (L != 3072 || N != 256)) { + DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_KEY_SIZE_INVALID); @@ -11546,6 +11548,108 @@ diff -up openssl-1.1.1b/include/openssl/rsaerr.h.fips openssl-1.1.1b/include/ope # define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 # define RSA_R_VALUE_MISSING 147 # define RSA_R_WRONG_SIGNATURE_LENGTH 119 +diff -up openssl-1.1.1c/ssl/s3_lib.c.fips openssl-1.1.1c/ssl/s3_lib.c +--- openssl-1.1.1c/ssl/s3_lib.c.fips 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/ssl/s3_lib.c 2019-11-20 12:00:32.770173240 +0100 +@@ -43,7 +43,7 @@ static SSL_CIPHER tls13_ciphers[] = { + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, +- SSL_HIGH, ++ SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, +@@ -58,7 +58,7 @@ static SSL_CIPHER tls13_ciphers[] = { + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, +- SSL_HIGH, ++ SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA384, + 256, + 256, +@@ -92,7 +92,7 @@ static SSL_CIPHER tls13_ciphers[] = { + SSL_AEAD, + TLS1_3_VERSION, TLS1_3_VERSION, + 0, 0, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256, + 128, + 128, +@@ -634,7 +634,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, +@@ -650,7 +650,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, +@@ -666,7 +666,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, +@@ -682,7 +682,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, +@@ -794,7 +794,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, +@@ -810,7 +810,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, +@@ -890,7 +890,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 128, + 128, +@@ -906,7 +906,7 @@ static SSL_CIPHER ssl3_ciphers[] = { + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + DTLS1_2_VERSION, DTLS1_2_VERSION, +- SSL_NOT_DEFAULT | SSL_HIGH, ++ SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS, + SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256, + 256, + 256, diff -up openssl-1.1.1b/ssl/ssl_ciph.c.fips openssl-1.1.1b/ssl/ssl_ciph.c --- openssl-1.1.1b/ssl/ssl_ciph.c.fips 2019-02-28 11:30:06.776746228 +0100 +++ openssl-1.1.1b/ssl/ssl_ciph.c 2019-02-28 11:30:06.822745372 +0100 diff --git a/SOURCES/openssl-1.1.1-krb5-kdf.patch b/SOURCES/openssl-1.1.1-krb5-kdf.patch new file mode 100644 index 0000000..f8332f6 --- /dev/null +++ b/SOURCES/openssl-1.1.1-krb5-kdf.patch @@ -0,0 +1,3022 @@ +diff -up openssl-1.1.1c/crypto/err/openssl.txt.krb5-kdf openssl-1.1.1c/crypto/err/openssl.txt +--- openssl-1.1.1c/crypto/err/openssl.txt.krb5-kdf 2019-11-14 16:25:09.445914709 +0100 ++++ openssl-1.1.1c/crypto/err/openssl.txt 2019-11-14 16:26:10.333811902 +0100 +@@ -816,6 +816,11 @@ EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_g + EVP_F_SCRYPT_ALG:228:scrypt_alg + EVP_F_UPDATE:173:update + KDF_F_HKDF_EXTRACT:112:HKDF_Extract ++KDF_F_KBKDF_CTRL:134:kbkdf_ctrl ++KDF_F_KBKDF_CTRL_STR:135:kbkdf_ctrl_str ++KDF_F_KBKDF_DERIVE:136:kbkdf_derive ++KDF_F_KBKDF_NEW:137:kbkdf_new ++KDF_F_KDF_CIPHER2CTRL:138:kdf_cipher2ctrl + KDF_F_KDF_HKDF_DERIVE:113:kdf_hkdf_derive + KDF_F_KDF_HKDF_NEW:114:kdf_hkdf_new + KDF_F_KDF_HKDF_SIZE:115:kdf_hkdf_size +@@ -835,6 +840,8 @@ KDF_F_KDF_SSHKDF_NEW:133:kdf_sshkdf_new + KDF_F_KDF_TLS1_PRF_CTRL_STR:125:kdf_tls1_prf_ctrl_str + KDF_F_KDF_TLS1_PRF_DERIVE:126:kdf_tls1_prf_derive + KDF_F_KDF_TLS1_PRF_NEW:127:kdf_tls1_prf_new ++KDF_F_KRB5KDF:139:KRB5KDF ++KDF_F_KRB5KDF_DERIVE:140:krb5kdf_derive + KDF_F_PBKDF2_SET_MEMBUF:128:pbkdf2_set_membuf + KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str + KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive +@@ -848,6 +855,9 @@ KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tl + KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive + KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init + KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf ++KDF_F_SSKDF_DERIVE:141:sskdf_derive ++KDF_F_SSKDF_NEW:142:sskdf_new ++KDF_F_SSKDF_SIZE:143:sskdf_size + KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg + OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object + OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid +@@ -2315,7 +2325,13 @@ EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM: + EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type + EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed + EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length ++KDF_R_FAILED_TO_GENERATE_KEY:118:failed to generate key ++KDF_R_INVALID_CIPHER:116:invalid cipher ++KDF_R_INVALID_CONSTANT_LENGTH:119:invalid constant length + KDF_R_INVALID_DIGEST:100:invalid digest ++KDF_R_INVALID_SEED_LENGTH:117:invalid seed length ++KDF_R_MISSING_CIPHER:120:missing cipher ++KDF_R_MISSING_CONSTANT:121:missing constant + KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count + KDF_R_MISSING_KEY:104:missing key + KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest +@@ -2330,6 +2346,7 @@ KDF_R_MISSING_XCGHASH:115:missing xcghas + KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type + KDF_R_VALUE_ERROR:108:value error + KDF_R_VALUE_MISSING:102:value missing ++KDF_R_WRONG_FINAL_BLOCK_LENGTH:120:wrong final block length + KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size + OBJ_R_OID_EXISTS:102:oid exists + OBJ_R_UNKNOWN_NID:101:unknown nid +diff -up openssl-1.1.1c/crypto/evp/kdf_lib.c.krb5-kdf openssl-1.1.1c/crypto/evp/kdf_lib.c +--- openssl-1.1.1c/crypto/evp/kdf_lib.c.krb5-kdf 2019-11-14 16:25:09.445914709 +0100 ++++ openssl-1.1.1c/crypto/evp/kdf_lib.c 2019-11-14 16:25:09.475914166 +0100 +@@ -31,6 +31,9 @@ static const EVP_KDF_METHOD *standard_me + &tls1_prf_kdf_meth, + &hkdf_kdf_meth, + &sshkdf_kdf_meth, ++ &kb_kdf_meth, ++ &krb5kdf_kdf_meth, ++ &ss_kdf_meth + }; + + DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *, +diff -up openssl-1.1.1c/crypto/include/internal/evp_int.h.krb5-kdf openssl-1.1.1c/crypto/include/internal/evp_int.h +--- openssl-1.1.1c/crypto/include/internal/evp_int.h.krb5-kdf 2019-11-14 16:25:09.446914691 +0100 ++++ openssl-1.1.1c/crypto/include/internal/evp_int.h 2019-11-14 16:25:09.475914166 +0100 +@@ -130,6 +130,9 @@ extern const EVP_KDF_METHOD scrypt_kdf_m + extern const EVP_KDF_METHOD tls1_prf_kdf_meth; + extern const EVP_KDF_METHOD hkdf_kdf_meth; + extern const EVP_KDF_METHOD sshkdf_kdf_meth; ++extern const EVP_KDF_METHOD kb_kdf_meth; ++extern const EVP_KDF_METHOD krb5kdf_kdf_meth; ++extern const EVP_KDF_METHOD ss_kdf_meth; + + struct evp_md_st { + int type; +diff -up openssl-1.1.1c/crypto/kdf/build.info.krb5-kdf openssl-1.1.1c/crypto/kdf/build.info +--- openssl-1.1.1c/crypto/kdf/build.info.krb5-kdf 2019-11-14 16:25:09.446914691 +0100 ++++ openssl-1.1.1c/crypto/kdf/build.info 2019-11-14 16:25:09.475914166 +0100 +@@ -1,3 +1,3 @@ + LIBS=../../libcrypto + SOURCE[../../libcrypto]=\ +- tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c sshkdf.c ++ tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c sshkdf.c kbkdf.c krb5kdf.c sskdf.c +diff -up openssl-1.1.1c/crypto/kdf/kbkdf.c.krb5-kdf openssl-1.1.1c/crypto/kdf/kbkdf.c +--- openssl-1.1.1c/crypto/kdf/kbkdf.c.krb5-kdf 2019-11-14 16:25:09.475914166 +0100 ++++ openssl-1.1.1c/crypto/kdf/kbkdf.c 2019-11-18 17:21:58.326635901 +0100 +@@ -0,0 +1,540 @@ ++/* ++ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2019 Red Hat, 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 ++ */ ++ ++/* ++ * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final ++ * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC ++ * and CMAC. That document does not name the KDFs it defines; the name is ++ * derived from ++ * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation ++ * ++ * Note that section 5.3 ("double-pipeline mode") is not implemented, though ++ * it would be possible to do so in the future. ++ * ++ * These versions all assume the counter is used. It would be relatively ++ * straightforward to expose a configuration handle should the need arise. ++ * ++ * Variable names attempt to match those of SP800-108. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "internal/numbers.h" ++#include "internal/cryptlib.h" ++#include "internal/evp_int.h" ++#include "kdf_local.h" ++ ++#include "e_os.h" ++ ++#ifdef MIN ++# undef MIN ++#endif ++#define MIN(a, b) ((a) < (b)) ? (a) : (b) ++ ++typedef struct { ++ int mac_type; ++ union { ++ HMAC_CTX *hmac; ++ CMAC_CTX *cmac; ++ } m; ++} MAC_CTX; ++ ++/* Our context structure. */ ++struct evp_kdf_impl_st { ++ int mode; ++ ++ MAC_CTX *ctx_init; ++ ++ const EVP_CIPHER *cipher; ++ const EVP_MD *md; ++ ++ /* Names are lowercased versions of those found in SP800-108. */ ++ unsigned char *ki; ++ size_t ki_len; ++ unsigned char *label; ++ size_t label_len; ++ unsigned char *context; ++ size_t context_len; ++ unsigned char *iv; ++ size_t iv_len; ++}; ++ ++static MAC_CTX *EVP_MAC_CTX_new(int mac_type) ++{ ++ MAC_CTX *ctx; ++ ++ ctx = OPENSSL_zalloc(sizeof(*ctx)); ++ if (ctx == NULL) ++ return NULL; ++ ++ ctx->mac_type = mac_type; ++ if (mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) { ++ if ((ctx->m.hmac = HMAC_CTX_new()) == NULL) ++ goto err; ++ } else { ++ if ((ctx->m.cmac = CMAC_CTX_new()) == NULL) ++ goto err; ++ } ++ return ctx; ++ ++err: ++ OPENSSL_free(ctx); ++ return NULL; ++} ++ ++static void EVP_MAC_CTX_free(MAC_CTX *ctx) ++{ ++ if (ctx == NULL) ++ return; ++ ++ if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) ++ HMAC_CTX_free(ctx->m.hmac); ++ else ++ CMAC_CTX_free(ctx->m.cmac); ++ OPENSSL_free(ctx); ++} ++ ++static MAC_CTX *EVP_MAC_CTX_dup(MAC_CTX *sctx) ++{ ++ MAC_CTX *ctx; ++ ++ ctx = OPENSSL_zalloc(sizeof(*sctx)); ++ if (ctx == NULL) ++ return NULL; ++ ++ ctx->mac_type = sctx->mac_type; ++ if (sctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) { ++ if ((ctx->m.hmac = HMAC_CTX_new()) == NULL ++ || HMAC_CTX_copy(ctx->m.hmac, sctx->m.hmac) <= 0) ++ goto err; ++ } else { ++ if ((ctx->m.cmac = CMAC_CTX_new()) == NULL ++ || CMAC_CTX_copy(ctx->m.cmac, sctx->m.cmac) <= 0) ++ goto err; ++ } ++ return ctx; ++ ++err: ++ EVP_MAC_CTX_free(ctx); ++ return NULL; ++} ++ ++static size_t EVP_MAC_size(MAC_CTX *ctx) ++{ ++ if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) { ++ const EVP_MD *md; ++ ++ if (ctx->m.hmac == NULL) ++ return 0; ++ if ((md = HMAC_CTX_get_md(ctx->m.hmac)) == NULL) ++ return 0; ++ return (size_t)EVP_MD_size(md); ++ } else { ++ const EVP_CIPHER_CTX *cctx; ++ ++ if (ctx->m.cmac == NULL) ++ return 0; ++ if ((cctx = CMAC_CTX_get0_cipher_ctx(ctx->m.cmac)) == NULL) ++ return 0; ++ return EVP_CIPHER_CTX_block_size(cctx); ++ } ++} ++ ++static int EVP_MAC_update(MAC_CTX *ctx, const unsigned char *data, ++ size_t datalen) ++{ ++ if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) ++ return HMAC_Update(ctx->m.hmac, data, datalen); ++ else ++ return CMAC_Update(ctx->m.cmac, data, datalen); ++} ++ ++static int EVP_MAC_final(MAC_CTX *ctx, unsigned char *out, ++ size_t *outl, size_t outsize) ++{ ++ if (outsize != EVP_MAC_size(ctx)) ++ /* we do not cope with anything else */ ++ return 0; ++ ++ if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) { ++ unsigned int intsize = (unsigned int)outsize; ++ int ret; ++ ++ ret = HMAC_Final(ctx->m.hmac, out, &intsize); ++ if (outl != NULL) ++ *outl = intsize; ++ return ret; ++ } else { ++ size_t size = outsize; ++ int ret; ++ ++ ret = CMAC_Final(ctx->m.cmac, out, &size); ++ if (outl != NULL) ++ *outl = size; ++ return ret; ++ } ++} ++ ++static int evp_mac_init(MAC_CTX *ctx, const EVP_MD *md, ++ const EVP_CIPHER *cipher, unsigned char *key, size_t keylen) ++{ ++ if (ctx->mac_type == EVP_KDF_KB_MAC_TYPE_HMAC) { ++ if (md == NULL) ++ return 0; ++ return HMAC_Init_ex(ctx->m.hmac, key, (int)keylen, md, NULL); ++ } else { ++ if (cipher == NULL) ++ return 0; ++ return CMAC_Init(ctx->m.cmac, key, keylen, cipher, NULL); ++ } ++} ++ ++static void kbkdf_reset(EVP_KDF_IMPL *ctx); ++ ++/* Not all platforms have htobe32(). */ ++static uint32_t be32(uint32_t host) ++{ ++ uint32_t big = 0; ++ const union { ++ long one; ++ char little; ++ } is_endian = { 1 }; ++ ++ if (!is_endian.little) ++ return host; ++ ++ big |= (host & 0xff000000) >> 24; ++ big |= (host & 0x00ff0000) >> 8; ++ big |= (host & 0x0000ff00) << 8; ++ big |= (host & 0x000000ff) << 24; ++ return big; ++} ++ ++static EVP_KDF_IMPL *kbkdf_new(void) ++{ ++ EVP_KDF_IMPL *ctx; ++ ++ ctx = OPENSSL_zalloc(sizeof(*ctx)); ++ if (ctx == NULL) { ++ KDFerr(KDF_F_KBKDF_NEW, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ return ctx; ++} ++ ++static void kbkdf_free(EVP_KDF_IMPL *ctx) ++{ ++ kbkdf_reset(ctx); ++ OPENSSL_free(ctx); ++} ++ ++static void kbkdf_reset(EVP_KDF_IMPL *ctx) ++{ ++ EVP_MAC_CTX_free(ctx->ctx_init); ++ OPENSSL_clear_free(ctx->context, ctx->context_len); ++ OPENSSL_clear_free(ctx->label, ctx->label_len); ++ OPENSSL_clear_free(ctx->ki, ctx->ki_len); ++ OPENSSL_clear_free(ctx->iv, ctx->iv_len); ++ memset(ctx, 0, sizeof(*ctx)); ++} ++ ++/* SP800-108 section 5.1 or section 5.2 depending on mode. */ ++static int derive(MAC_CTX *ctx_init, int mode, unsigned char *iv, ++ size_t iv_len, unsigned char *label, size_t label_len, ++ unsigned char *context, size_t context_len, ++ unsigned char *k_i, size_t h, uint32_t l, unsigned char *ko, ++ size_t ko_len) ++{ ++ int ret = 0; ++ MAC_CTX *ctx = NULL; ++ size_t written = 0, to_write, k_i_len = iv_len; ++ const unsigned char zero = 0; ++ uint32_t counter, i; ++ ++ /* Setup K(0) for feedback mode. */ ++ if (iv_len > 0) ++ memcpy(k_i, iv, iv_len); ++ ++ for (counter = 1; written < ko_len; counter++) { ++ i = be32(counter); ++ ++ ctx = EVP_MAC_CTX_dup(ctx_init); ++ if (ctx == NULL) ++ goto done; ++ ++ /* Perform feedback, if appropriate. */ ++ if (mode == EVP_KDF_KB_MODE_FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len)) ++ goto done; ++ ++ if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4) ++ || !EVP_MAC_update(ctx, label, label_len) ++ || !EVP_MAC_update(ctx, &zero, 1) ++ || !EVP_MAC_update(ctx, context, context_len) ++ || !EVP_MAC_update(ctx, (unsigned char *)&l, 4) ++ || !EVP_MAC_final(ctx, k_i, NULL, h)) ++ goto done; ++ ++ to_write = ko_len - written; ++ memcpy(ko + written, k_i, MIN(to_write, h)); ++ written += h; ++ ++ k_i_len = h; ++ EVP_MAC_CTX_free(ctx); ++ ctx = NULL; ++ } ++ ++ ret = 1; ++done: ++ EVP_MAC_CTX_free(ctx); ++ return ret; ++} ++ ++static int kbkdf_derive(EVP_KDF_IMPL *ctx, unsigned char *key, size_t keylen) ++{ ++ int ret = 0; ++ unsigned char *k_i = NULL; ++ uint32_t l = be32(keylen * 8); ++ size_t h = 0; ++ ++ /* label, context, and iv are permitted to be empty. Check everything ++ * else. */ ++ if (ctx->ctx_init == NULL ++ || evp_mac_init(ctx->ctx_init, ctx->md, ctx->cipher, ctx->ki, ctx->ki_len) <= 0) { ++ if (ctx->ki_len == 0 || ctx->ki == NULL) { ++ KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_MISSING_KEY); ++ return 0; ++ } ++ /* Could either be missing MAC or missing message digest or missing ++ * cipher - arbitrarily, I pick this one. */ ++ KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_MISSING_PARAMETER); ++ return 0; ++ } ++ ++ h = EVP_MAC_size(ctx->ctx_init); ++ if (h == 0) ++ goto done; ++ if (ctx->iv_len != 0 && ctx->iv_len != h) { ++ KDFerr(KDF_F_KBKDF_DERIVE, KDF_R_INVALID_SEED_LENGTH); ++ goto done; ++ } ++ ++ k_i = OPENSSL_zalloc(h); ++ if (k_i == NULL) ++ goto done; ++ ++ ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label, ++ ctx->label_len, ctx->context, ctx->context_len, k_i, h, l, ++ key, keylen); ++done: ++ if (ret != 1) ++ OPENSSL_cleanse(key, keylen); ++ OPENSSL_clear_free(k_i, h); ++ return ret; ++} ++ ++static size_t kbkdf_size(EVP_KDF_IMPL *ctx) ++{ ++ return UINT32_MAX/8; ++} ++ ++static int kbkdf_parse_buffer_arg(unsigned char **dst, size_t *dst_len, ++ va_list args) ++{ ++ const unsigned char *p; ++ size_t len; ++ ++ p = va_arg(args, const unsigned char *); ++ len = va_arg(args, size_t); ++ OPENSSL_clear_free(*dst, *dst_len); ++ if (len == 0) { ++ *dst = NULL; ++ *dst_len = 0; ++ return 1; ++ } ++ ++ *dst = OPENSSL_memdup(p, len); ++ if (*dst == NULL) ++ return 0; ++ ++ *dst_len = len; ++ return 1; ++} ++ ++static int kbkdf_ctrl(EVP_KDF_IMPL *ctx, int cmd, va_list args) ++{ ++ int t; ++ ++ switch (cmd) { ++ case EVP_KDF_CTRL_SET_MD: ++ ctx->md = va_arg(args, const EVP_MD *); ++ if (ctx->md == NULL) ++ return 0; ++ ++ return 1; ++ ++ case EVP_KDF_CTRL_SET_CIPHER: ++ ctx->cipher = va_arg(args, const EVP_CIPHER *); ++ if (ctx->cipher == NULL) ++ return 0; ++ ++ return 1; ++ ++ case EVP_KDF_CTRL_SET_KEY: ++ return kbkdf_parse_buffer_arg(&ctx->ki, ++ &ctx->ki_len, args); ++ ++ case EVP_KDF_CTRL_SET_SALT: ++ return kbkdf_parse_buffer_arg(&ctx->label, ++ &ctx->label_len, args); ++ ++ case EVP_KDF_CTRL_SET_KB_INFO: ++ return kbkdf_parse_buffer_arg(&ctx->context, ++ &ctx->context_len, args); ++ ++ case EVP_KDF_CTRL_SET_KB_SEED: ++ return kbkdf_parse_buffer_arg(&ctx->iv, ++ &ctx->iv_len, args); ++ ++ case EVP_KDF_CTRL_SET_KB_MODE: ++ t = va_arg(args, int); ++ if (t != EVP_KDF_KB_MODE_COUNTER && t != EVP_KDF_KB_MODE_FEEDBACK ) { ++ KDFerr(KDF_F_KBKDF_CTRL, KDF_R_VALUE_ERROR); ++ return 0; ++ } ++ ctx->mode = t; ++ return 1; ++ ++ case EVP_KDF_CTRL_SET_KB_MAC_TYPE: ++ t = va_arg(args, int); ++ if (t != EVP_KDF_KB_MAC_TYPE_HMAC && t != EVP_KDF_KB_MAC_TYPE_CMAC ) { ++ KDFerr(KDF_F_KBKDF_CTRL, KDF_R_VALUE_ERROR); ++ return 0; ++ } ++ ++ if (ctx->ctx_init != NULL) { ++ EVP_MAC_CTX_free(ctx->ctx_init); ++ } ++ ctx->ctx_init = EVP_MAC_CTX_new(t); ++ if (ctx->ctx_init == NULL) { ++ KDFerr(KDF_F_KBKDF_CTRL, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ return 1; ++ ++ default: ++ return -2; ++ ++ } ++} ++ ++static int kbkdf_ctrl_str(EVP_KDF_IMPL *ctx, const char *type, ++ const char *value) ++{ ++ if (value == NULL) { ++ KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_VALUE_MISSING); ++ return 0; ++ } ++ ++ if (strcmp(type, "digest") == 0) ++ return kdf_md2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_MD, value); ++ /* alias, for historical reasons */ ++ if (strcmp(type, "md") == 0) ++ return kdf_md2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_MD, value); ++ ++ if (strcmp(type, "cipher") == 0) ++ return kdf_cipher2ctrl(ctx, kbkdf_ctrl, EVP_KDF_CTRL_SET_CIPHER, value); ++ ++ if (strcmp(type, "key") == 0) ++ return kdf_str2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KEY, value); ++ ++ if (strcmp(type, "hexkey") == 0) ++ return kdf_hex2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KEY, value); ++ ++ if (strcmp(type, "salt") == 0) ++ return kdf_str2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_SALT, value); ++ ++ if (strcmp(type, "hexsalt") == 0) ++ return kdf_hex2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_SALT, value); ++ ++ if (strcmp(type, "info") == 0) ++ return kdf_str2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KB_INFO, value); ++ ++ if (strcmp(type, "hexinfo") == 0) ++ return kdf_hex2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KB_INFO, value); ++ ++ if (strcmp(type, "seed") == 0) ++ return kdf_str2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KB_SEED, value); ++ ++ if (strcmp(type, "hexseed") == 0) ++ return kdf_hex2ctrl(ctx, kbkdf_ctrl, ++ EVP_KDF_CTRL_SET_KB_SEED, value); ++ ++ if (strcmp(type, "mode") == 0) { ++ int mode; ++ ++ if (strcasecmp(value, "counter") == 0) { ++ mode = EVP_KDF_KB_MODE_COUNTER; ++ } else if (strcasecmp(value, "feedback") == 0) { ++ mode = EVP_KDF_KB_MODE_FEEDBACK; ++ } else { ++ KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_VALUE_ERROR); ++ return 0; ++ } ++ ++ return call_ctrl(kbkdf_ctrl, ctx, EVP_KDF_CTRL_SET_KB_MODE, ++ mode); ++ } ++ ++ if (strcmp(type, "mac_type") == 0) { ++ int mac_type; ++ ++ if (strcasecmp(value, "hmac") == 0) { ++ mac_type = EVP_KDF_KB_MAC_TYPE_HMAC; ++ } else if (strcasecmp(value, "cmac") == 0) { ++ mac_type = EVP_KDF_KB_MAC_TYPE_CMAC; ++ } else { ++ KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_VALUE_ERROR); ++ return 0; ++ } ++ ++ return call_ctrl(kbkdf_ctrl, ctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, ++ mac_type); ++ } ++ ++ KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); ++ return -2; ++} ++ ++const EVP_KDF_METHOD kb_kdf_meth = { ++ EVP_KDF_KB, ++ kbkdf_new, ++ kbkdf_free, ++ kbkdf_reset, ++ kbkdf_ctrl, ++ kbkdf_ctrl_str, ++ kbkdf_size, ++ kbkdf_derive, ++}; ++ +diff -up openssl-1.1.1c/crypto/kdf/kdf_err.c.krb5-kdf openssl-1.1.1c/crypto/kdf/kdf_err.c +--- openssl-1.1.1c/crypto/kdf/kdf_err.c.krb5-kdf 2019-11-14 16:25:09.446914691 +0100 ++++ openssl-1.1.1c/crypto/kdf/kdf_err.c 2019-11-14 16:25:09.475914166 +0100 +@@ -15,6 +15,11 @@ + + static const ERR_STRING_DATA KDF_str_functs[] = { + {ERR_PACK(ERR_LIB_KDF, KDF_F_HKDF_EXTRACT, 0), "HKDF_Extract"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KBKDF_CTRL, 0), "kbkdf_ctrl"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KBKDF_CTRL_STR, 0), "kbkdf_ctrl_str"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KBKDF_DERIVE, 0), "kbkdf_derive"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KBKDF_NEW, 0), "kbkdf_new"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_CIPHER2CTRL, 0), "kdf_cipher2ctrl"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_DERIVE, 0), "kdf_hkdf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_NEW, 0), "kdf_hkdf_new"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_SIZE, 0), "kdf_hkdf_size"}, +@@ -41,6 +46,8 @@ static const ERR_STRING_DATA KDF_str_fun + {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_DERIVE, 0), + "kdf_tls1_prf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_NEW, 0), "kdf_tls1_prf_new"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KRB5KDF, 0), "KRB5KDF"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_KRB5KDF_DERIVE, 0), "krb5kdf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PBKDF2_SET_MEMBUF, 0), "pbkdf2_set_membuf"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"}, +@@ -59,12 +66,22 @@ static const ERR_STRING_DATA KDF_str_fun + "pkey_tls1_prf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_SCRYPT_SET_MEMBUF, 0), "scrypt_set_membuf"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_DERIVE, 0), "sskdf_derive"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_NEW, 0), "sskdf_new"}, ++ {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_SIZE, 0), "sskdf_size"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"}, + {0, NULL} + }; + + static const ERR_STRING_DATA KDF_str_reasons[] = { ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_FAILED_TO_GENERATE_KEY), ++ "failed to generate key"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_CIPHER), "invalid cipher"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_CONSTANT_LENGTH), "invalid constant length"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_DIGEST), "invalid digest"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_SEED_LENGTH), "invalid seed length"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_CIPHER), "missing cipher"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_CONSTANT), "missing constant"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_ITERATION_COUNT), + "missing iteration count"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_KEY), "missing key"}, +@@ -82,6 +99,8 @@ static const ERR_STRING_DATA KDF_str_rea + "unknown parameter type"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"}, ++ {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_FINAL_BLOCK_LENGTH), ++ "wrong final block length"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_OUTPUT_BUFFER_SIZE), + "wrong output buffer size"}, + {0, NULL} +diff -up openssl-1.1.1c/crypto/kdf/kdf_local.h.krb5-kdf openssl-1.1.1c/crypto/kdf/kdf_local.h +--- openssl-1.1.1c/crypto/kdf/kdf_local.h.krb5-kdf 2019-11-14 16:25:09.438914836 +0100 ++++ openssl-1.1.1c/crypto/kdf/kdf_local.h 2019-11-14 16:25:09.475914166 +0100 +@@ -19,4 +19,6 @@ int kdf_hex2ctrl(EVP_KDF_IMPL *impl, + int kdf_md2ctrl(EVP_KDF_IMPL *impl, + int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args), + int cmd, const char *md_name); +- ++int kdf_cipher2ctrl(EVP_KDF_IMPL *impl, ++ int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args), ++ int cmd, const char *cipher_name); +diff -up openssl-1.1.1c/crypto/kdf/kdf_util.c.krb5-kdf openssl-1.1.1c/crypto/kdf/kdf_util.c +--- openssl-1.1.1c/crypto/kdf/kdf_util.c.krb5-kdf 2019-11-14 16:25:09.438914836 +0100 ++++ openssl-1.1.1c/crypto/kdf/kdf_util.c 2019-11-14 16:25:09.475914166 +0100 +@@ -71,3 +71,16 @@ int kdf_md2ctrl(EVP_KDF_IMPL *impl, + return call_ctrl(ctrl, impl, cmd, md); + } + ++/* Pass a cipher to a ctrl */ ++int kdf_cipher2ctrl(EVP_KDF_IMPL *impl, ++ int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args), ++ int cmd, const char *cipher_name) ++{ ++ const EVP_CIPHER *cipher; ++ ++ if (cipher_name == NULL || (cipher = EVP_get_cipherbyname(cipher_name)) == NULL) { ++ KDFerr(KDF_F_KDF_CIPHER2CTRL, KDF_R_INVALID_CIPHER); ++ return 0; ++ } ++ return call_ctrl(ctrl, impl, cmd, cipher); ++} +diff -up openssl-1.1.1c/crypto/kdf/krb5kdf.c.krb5-kdf openssl-1.1.1c/crypto/kdf/krb5kdf.c +--- openssl-1.1.1c/crypto/kdf/krb5kdf.c.krb5-kdf 2019-11-14 16:25:09.476914148 +0100 ++++ openssl-1.1.1c/crypto/kdf/krb5kdf.c 2019-11-18 17:18:13.056604404 +0100 +@@ -0,0 +1,423 @@ ++/* ++ * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "internal/cryptlib.h" ++#include "internal/evp_int.h" ++#include "kdf_local.h" ++ ++/* KRB5 KDF defined in RFC 3961, Section 5.1 */ ++ ++static int KRB5KDF(const EVP_CIPHER *cipher, ++ const unsigned char *key, size_t key_len, ++ const unsigned char *constant, size_t constant_len, ++ unsigned char *okey, size_t okey_len); ++ ++struct evp_kdf_impl_st { ++ const EVP_CIPHER *cipher; ++ unsigned char *key; ++ size_t key_len; ++ unsigned char *constant; ++ size_t constant_len; ++}; ++ ++static void krb5kdf_reset(EVP_KDF_IMPL *ctx); ++ ++static EVP_KDF_IMPL *krb5kdf_new(void) ++{ ++ EVP_KDF_IMPL *ctx; ++ ++ if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) ++ KDFerr(KDF_F_KBKDF_NEW, ERR_R_MALLOC_FAILURE); ++ return ctx; ++} ++ ++static void krb5kdf_free(EVP_KDF_IMPL *ctx) ++{ ++ krb5kdf_reset(ctx); ++ OPENSSL_free(ctx); ++} ++ ++static void krb5kdf_reset(EVP_KDF_IMPL *ctx) ++{ ++ OPENSSL_clear_free(ctx->key, ctx->key_len); ++ OPENSSL_clear_free(ctx->constant, ctx->constant_len); ++ memset(ctx, 0, sizeof(*ctx)); ++} ++ ++static int krb5kdf_derive(EVP_KDF_IMPL *ctx, unsigned char *key, ++ size_t keylen) ++{ ++ if (ctx->cipher == NULL) { ++ KDFerr(KDF_F_KRB5KDF_DERIVE, KDF_R_MISSING_CIPHER); ++ return 0; ++ } ++ if (ctx->key == NULL) { ++ KDFerr(KDF_F_KRB5KDF_DERIVE, KDF_R_MISSING_KEY); ++ return 0; ++ } ++ if (ctx->constant == NULL) { ++ KDFerr(KDF_F_KRB5KDF_DERIVE, KDF_R_MISSING_CONSTANT); ++ return 0; ++ } ++ return KRB5KDF(ctx->cipher, ctx->key, ctx->key_len, ++ ctx->constant, ctx->constant_len, ++ key, keylen); ++} ++ ++static size_t krb5kdf_size(EVP_KDF_IMPL *ctx) ++{ ++ if (ctx->cipher != NULL) ++ return EVP_CIPHER_key_length(ctx->cipher); ++ else ++ return EVP_MAX_KEY_LENGTH; ++} ++ ++ ++static int krb5kdf_parse_buffer_arg(unsigned char **dst, size_t *dst_len, ++ va_list args) ++{ ++ const unsigned char *p; ++ size_t len; ++ ++ p = va_arg(args, const unsigned char *); ++ len = va_arg(args, size_t); ++ OPENSSL_clear_free(*dst, *dst_len); ++ if (len == 0) { ++ *dst = NULL; ++ *dst_len = 0; ++ return 1; ++ } ++ ++ *dst = OPENSSL_memdup(p, len); ++ if (*dst == NULL) ++ return 0; ++ ++ *dst_len = len; ++ return 1; ++} ++ ++static int krb5kdf_ctrl(EVP_KDF_IMPL *ctx, int cmd, va_list args) ++{ ++ switch (cmd) { ++ case EVP_KDF_CTRL_SET_CIPHER: ++ ctx->cipher = va_arg(args, const EVP_CIPHER *); ++ if (ctx->cipher == NULL) ++ return 0; ++ ++ return 1; ++ ++ case EVP_KDF_CTRL_SET_KEY: ++ return krb5kdf_parse_buffer_arg(&ctx->key, ++ &ctx->key_len, args); ++ ++ case EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT: ++ return krb5kdf_parse_buffer_arg(&ctx->constant, ++ &ctx->constant_len, args); ++ default: ++ return -2; ++ ++ } ++} ++ ++static int krb5kdf_ctrl_str(EVP_KDF_IMPL *ctx, const char *type, ++ const char *value) ++{ ++ if (value == NULL) { ++ KDFerr(KDF_F_KDF_SSHKDF_CTRL_STR, KDF_R_VALUE_MISSING); ++ return 0; ++ } ++ ++ if (strcmp(type, "cipher") == 0) ++ return kdf_cipher2ctrl(ctx, krb5kdf_ctrl, EVP_KDF_CTRL_SET_CIPHER, value); ++ ++ if (strcmp(type, "key") == 0) ++ return kdf_str2ctrl(ctx, krb5kdf_ctrl, ++ EVP_KDF_CTRL_SET_KEY, value); ++ ++ if (strcmp(type, "hexkey") == 0) ++ return kdf_hex2ctrl(ctx, krb5kdf_ctrl, ++ EVP_KDF_CTRL_SET_KEY, value); ++ ++ if (strcmp(type, "constant") == 0) ++ return kdf_str2ctrl(ctx, krb5kdf_ctrl, ++ EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT, value); ++ ++ if (strcmp(type, "hexconstant") == 0) ++ return kdf_hex2ctrl(ctx, krb5kdf_ctrl, ++ EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT, value); ++ ++ KDFerr(KDF_F_KBKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); ++ return -2; ++} ++ ++ ++#ifndef OPENSSL_NO_DES ++/* ++ * DES3 is a special case, it requires a random-to-key function and its ++ * input truncated to 21 bytes of the 24 produced by the cipher. ++ * See RFC3961 6.3.1 ++ */ ++static int fixup_des3_key(unsigned char *key) ++{ ++ unsigned char *cblock; ++ int i, j; ++ ++ for (i = 2; i >= 0; i--) { ++ cblock = &key[i * 8]; ++ memmove(cblock, &key[i * 7], 7); ++ cblock[7] = 0; ++ for (j = 0; j < 7; j++) ++ cblock[7] |= (cblock[j] & 1) << (j + 1); ++ DES_set_odd_parity((DES_cblock *)cblock); ++ } ++ ++ /* fail if keys are such that triple des degrades to single des */ ++ if (CRYPTO_memcmp(&key[0], &key[8], 8) == 0 || ++ CRYPTO_memcmp(&key[8], &key[16], 8) == 0) { ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/* ++ * N-fold(K) where blocksize is N, and constant_len is K ++ * Note: Here |= denotes concatenation ++ * ++ * L = lcm(N,K) ++ * R = L/K ++ * ++ * for r: 1 -> R ++ * s |= constant rot 13*(r-1)) ++ * ++ * block = 0 ++ * for k: 1 -> K ++ * block += s[N(k-1)..(N-1)k] (one's complement addition) ++ * ++ * Optimizing for space we compute: ++ * for each l in L-1 -> 0: ++ * s[l] = (constant rot 13*(l/K))[l%k] ++ * block[l % N] += s[l] (with carry) ++ * finally add carry if any ++ */ ++static void n_fold(unsigned char *block, unsigned int blocksize, ++ const unsigned char *constant, size_t constant_len) ++{ ++ unsigned int tmp, gcd, remainder, lcm, carry; ++ int b, l; ++ ++ if (constant_len == blocksize) { ++ memcpy(block, constant, constant_len); ++ return; ++ } ++ ++ /* Least Common Multiple of lengths: LCM(a,b)*/ ++ gcd = blocksize; ++ remainder = constant_len; ++ /* Calculate Great Common Divisor first GCD(a,b) */ ++ while (remainder != 0) { ++ tmp = gcd % remainder; ++ gcd = remainder; ++ remainder = tmp; ++ } ++ /* resulting a is the GCD, LCM(a,b) = |a*b|/GCD(a,b) */ ++ lcm = blocksize * constant_len / gcd; ++ ++ /* now spread out the bits */ ++ memset(block, 0, blocksize); ++ ++ /* last to first to be able to bring carry forward */ ++ carry = 0; ++ for (l = lcm - 1; l >= 0; l--) { ++ unsigned int rotbits, rshift, rbyte; ++ ++ /* destination byte in block is l % N */ ++ b = l % blocksize; ++ /* Our virtual s buffer is R = L/K long (K = constant_len) */ ++ /* So we rotate backwards from R-1 to 0 (none) rotations */ ++ rotbits = 13 * (l / constant_len); ++ /* find the byte on s where rotbits falls onto */ ++ rbyte = l - (rotbits / 8); ++ /* calculate how much shift on that byte */ ++ rshift = rotbits & 0x07; ++ /* rbyte % constant_len gives us the unrotated byte in the ++ * constant buffer, get also the previous byte then ++ * appropriately shift them to get the rotated byte we need */ ++ tmp = (constant[(rbyte-1) % constant_len] << (8 - rshift) ++ | constant[rbyte % constant_len] >> rshift) ++ & 0xff; ++ /* add with carry to any value placed by previous passes */ ++ tmp += carry + block[b]; ++ block[b] = tmp & 0xff; ++ /* save any carry that may be left */ ++ carry = tmp >> 8; ++ } ++ ++ /* if any carry is left at the end, add it through the number */ ++ for (b = blocksize - 1; b >= 0 && carry != 0; b--) { ++ carry += block[b]; ++ block[b] = carry & 0xff; ++ carry >>= 8; ++ } ++} ++ ++static int cipher_init(EVP_CIPHER_CTX *ctx, ++ const EVP_CIPHER *cipher, ++ const unsigned char *key, size_t key_len) ++{ ++ int klen, ret; ++ ++ ret = EVP_EncryptInit_ex(ctx, cipher, NULL, key, NULL); ++ if (!ret) ++ goto out; ++ /* set the key len for the odd variable key len cipher */ ++ klen = EVP_CIPHER_CTX_key_length(ctx); ++ if (key_len != (size_t)klen) { ++ ret = EVP_CIPHER_CTX_set_key_length(ctx, key_len); ++ if (!ret) ++ goto out; ++ } ++ /* we never want padding, either the length requested is a multiple of ++ * the cipher block size or we are passed a cipher that can cope with ++ * partial blocks via techniques like cipher text stealing */ ++ ret = EVP_CIPHER_CTX_set_padding(ctx, 0); ++ if (!ret) ++ goto out; ++ ++out: ++ return ret; ++} ++ ++static int KRB5KDF(const EVP_CIPHER *cipher, ++ const unsigned char *key, size_t key_len, ++ const unsigned char *constant, size_t constant_len, ++ unsigned char *okey, size_t okey_len) ++{ ++ EVP_CIPHER_CTX *ctx = NULL; ++ unsigned char block[EVP_MAX_BLOCK_LENGTH * 2]; ++ unsigned char *plainblock, *cipherblock; ++ size_t blocksize; ++ size_t cipherlen; ++ size_t osize; ++ int des3_no_fixup = 0; ++ int ret; ++ ++ if (key_len != okey_len) { ++ /* special case for 3des, where the caller may be requesting ++ * the random raw key, instead of the fixed up key */ ++ if (EVP_CIPHER_nid(cipher) == NID_des_ede3_cbc && ++ key_len == 24 && okey_len == 21) { ++ des3_no_fixup = 1; ++ } else { ++ KDFerr(KDF_F_KRB5KDF, KDF_R_WRONG_OUTPUT_BUFFER_SIZE); ++ return 0; ++ } ++ } ++ ++ ctx = EVP_CIPHER_CTX_new(); ++ if (ctx == NULL) ++ return 0; ++ ++ ret = cipher_init(ctx, cipher, key, key_len); ++ if (!ret) ++ goto out; ++ ++ /* Initialize input block */ ++ blocksize = EVP_CIPHER_CTX_block_size(ctx); ++ ++ if (constant_len == 0 || constant_len > blocksize) { ++ KDFerr(KDF_F_KRB5KDF, KDF_R_INVALID_CONSTANT_LENGTH); ++ ret = 0; ++ goto out; ++ } ++ ++ n_fold(block, blocksize, constant, constant_len); ++ plainblock = block; ++ cipherblock = block + EVP_MAX_BLOCK_LENGTH; ++ ++ for (osize = 0; osize < okey_len; osize += cipherlen) { ++ int olen; ++ ++ ret = EVP_EncryptUpdate(ctx, cipherblock, &olen, ++ plainblock, blocksize); ++ if (!ret) ++ goto out; ++ cipherlen = olen; ++ ret = EVP_EncryptFinal_ex(ctx, cipherblock, &olen); ++ if (!ret) ++ goto out; ++ if (olen != 0) { ++ KDFerr(KDF_F_KRB5KDF, KDF_R_WRONG_FINAL_BLOCK_LENGTH); ++ ret = 0; ++ goto out; ++ } ++ ++ /* write cipherblock out */ ++ if (cipherlen > okey_len - osize) ++ cipherlen = okey_len - osize; ++ memcpy(okey + osize, cipherblock, cipherlen); ++ ++ if (okey_len > osize + cipherlen) { ++ /* we need to reinitialize cipher context per spec */ ++ ret = EVP_CIPHER_CTX_reset(ctx); ++ if (!ret) ++ goto out; ++ ret = cipher_init(ctx, cipher, key, key_len); ++ if (!ret) ++ goto out; ++ ++ /* also swap block offsets so last ciphertext becomes new ++ * plaintext */ ++ plainblock = cipherblock; ++ if (cipherblock == block) { ++ cipherblock += EVP_MAX_BLOCK_LENGTH; ++ } else { ++ cipherblock = block; ++ } ++ } ++ } ++ ++#ifndef OPENSSL_NO_DES ++ if (EVP_CIPHER_nid(cipher) == NID_des_ede3_cbc && !des3_no_fixup) { ++ ret = fixup_des3_key(okey); ++ if (!ret) { ++ KDFerr(KDF_F_KRB5KDF, KDF_R_FAILED_TO_GENERATE_KEY); ++ goto out; ++ } ++ } ++#endif ++ ++ ret = 1; ++ ++out: ++ EVP_CIPHER_CTX_free(ctx); ++ OPENSSL_cleanse(block, EVP_MAX_BLOCK_LENGTH * 2); ++ return ret; ++} ++ ++const EVP_KDF_METHOD krb5kdf_kdf_meth = { ++ EVP_KDF_KRB5KDF, ++ krb5kdf_new, ++ krb5kdf_free, ++ krb5kdf_reset, ++ krb5kdf_ctrl, ++ krb5kdf_ctrl_str, ++ krb5kdf_size, ++ krb5kdf_derive, ++}; ++ +diff -up openssl-1.1.1c/crypto/kdf/sshkdf.c.krb5-kdf openssl-1.1.1c/crypto/kdf/sshkdf.c +--- openssl-1.1.1c/crypto/kdf/sshkdf.c.krb5-kdf 2019-11-15 14:53:14.769279878 +0100 ++++ openssl-1.1.1c/crypto/kdf/sshkdf.c 2019-11-18 17:18:25.343388314 +0100 +@@ -69,6 +69,12 @@ static int kdf_sshkdf_parse_buffer_arg(u + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + OPENSSL_clear_free(*dst, *dst_len); ++ if (len == 0) { ++ *dst = NULL; ++ *dst_len = 0; ++ return 1; ++ } ++ + *dst = OPENSSL_memdup(p, len); + if (*dst == NULL) + return 0; +diff -up openssl-1.1.1c/crypto/kdf/sskdf.c.krb5-kdf openssl-1.1.1c/crypto/kdf/sskdf.c +--- openssl-1.1.1c/crypto/kdf/sskdf.c.krb5-kdf 2019-11-14 16:25:09.476914148 +0100 ++++ openssl-1.1.1c/crypto/kdf/sskdf.c 2019-11-18 17:21:40.349952802 +0100 +@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright (c) 2019, Oracle and/or its affiliates. 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 ++ */ ++ ++/* ++ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final ++ * Section 4.1. ++ * ++ * The Single Step KDF algorithm is given by: ++ * ++ * Result(0) = empty bit string (i.e., the null string). ++ * For i = 1 to reps, do the following: ++ * Increment counter by 1. ++ * Result(i) = Result(i – 1) || H(counter || Z || FixedInfo). ++ * DKM = LeftmostBits(Result(reps), L)) ++ * ++ * NOTES: ++ * Z is a shared secret required to produce the derived key material. ++ * counter is a 4 byte buffer. ++ * FixedInfo is a bit string containing context specific data. ++ * DKM is the output derived key material. ++ * L is the required size of the DKM. ++ * reps = [L / H_outputBits] ++ * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC. ++ * This backported version supports only a hash. ++ * H_outputBits is the length of the output of the auxiliary function H(x). ++ * ++ * Currently there is not a comprehensive list of test vectors for this ++ * algorithm, especially for H(x) = HMAC and H(x) = KMAC. ++ * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "internal/cryptlib.h" ++#include "internal/evp_int.h" ++#include "kdf_local.h" ++ ++struct evp_kdf_impl_st { ++ const EVP_MD *md; /* H(x) = hash */ ++ unsigned char *secret; ++ size_t secret_len; ++ unsigned char *info; ++ size_t info_len; ++}; ++ ++#define SSKDF_MAX_INLEN (1<<30) ++ ++/* ++ * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final ++ * Section 4. One-Step Key Derivation using H(x) = hash(x) ++ */ ++static int SSKDF_hash_kdm(const EVP_MD *kdf_md, ++ const unsigned char *z, size_t z_len, ++ const unsigned char *info, size_t info_len, ++ unsigned char *derived_key, size_t derived_key_len) ++{ ++ int ret = 0, hlen; ++ size_t counter, out_len, len = derived_key_len; ++ unsigned char c[4]; ++ unsigned char mac[EVP_MAX_MD_SIZE]; ++ unsigned char *out = derived_key; ++ EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; ++ ++ if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN ++ || derived_key_len > SSKDF_MAX_INLEN ++ || derived_key_len == 0) ++ return 0; ++ ++ hlen = EVP_MD_size(kdf_md); ++ if (hlen <= 0) ++ return 0; ++ out_len = (size_t)hlen; ++ ++ ctx = EVP_MD_CTX_create(); ++ ctx_init = EVP_MD_CTX_create(); ++ if (ctx == NULL || ctx_init == NULL) ++ goto end; ++ ++ if (!EVP_DigestInit(ctx_init, kdf_md)) ++ goto end; ++ ++ for (counter = 1;; counter++) { ++ c[0] = (unsigned char)((counter >> 24) & 0xff); ++ c[1] = (unsigned char)((counter >> 16) & 0xff); ++ c[2] = (unsigned char)((counter >> 8) & 0xff); ++ c[3] = (unsigned char)(counter & 0xff); ++ ++ if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init) ++ && EVP_DigestUpdate(ctx, c, sizeof(c)) ++ && EVP_DigestUpdate(ctx, z, z_len) ++ && EVP_DigestUpdate(ctx, info, info_len))) ++ goto end; ++ if (len >= out_len) { ++ if (!EVP_DigestFinal_ex(ctx, out, NULL)) ++ goto end; ++ out += out_len; ++ len -= out_len; ++ if (len == 0) ++ break; ++ } else { ++ if (!EVP_DigestFinal_ex(ctx, mac, NULL)) ++ goto end; ++ memcpy(out, mac, len); ++ break; ++ } ++ } ++ ret = 1; ++end: ++ EVP_MD_CTX_destroy(ctx); ++ EVP_MD_CTX_destroy(ctx_init); ++ OPENSSL_cleanse(mac, sizeof(mac)); ++ return ret; ++} ++ ++static EVP_KDF_IMPL *sskdf_new(void) ++{ ++ EVP_KDF_IMPL *impl; ++ ++ if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL) ++ KDFerr(KDF_F_SSKDF_NEW, ERR_R_MALLOC_FAILURE); ++ return impl; ++} ++ ++static void sskdf_reset(EVP_KDF_IMPL *impl) ++{ ++ OPENSSL_clear_free(impl->secret, impl->secret_len); ++ OPENSSL_clear_free(impl->info, impl->info_len); ++ memset(impl, 0, sizeof(*impl)); ++} ++ ++static void sskdf_free(EVP_KDF_IMPL *impl) ++{ ++ sskdf_reset(impl); ++ OPENSSL_free(impl); ++} ++ ++static int sskdf_set_buffer(va_list args, unsigned char **out, size_t *out_len) ++{ ++ const unsigned char *p; ++ size_t len; ++ ++ p = va_arg(args, const unsigned char *); ++ len = va_arg(args, size_t); ++ OPENSSL_clear_free(*out, *out_len); ++ if (len == 0) { ++ *out = NULL; ++ *out_len = 0; ++ return 1; ++ } ++ ++ *out = OPENSSL_memdup(p, len); ++ if (*out == NULL) ++ return 0; ++ ++ *out_len = len; ++ return 1; ++} ++ ++static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) ++{ ++ const EVP_MD *md; ++ ++ switch (cmd) { ++ case EVP_KDF_CTRL_SET_KEY: ++ return sskdf_set_buffer(args, &impl->secret, &impl->secret_len); ++ ++ case EVP_KDF_CTRL_SET_SSKDF_INFO: ++ return sskdf_set_buffer(args, &impl->info, &impl->info_len); ++ ++ case EVP_KDF_CTRL_SET_MD: ++ md = va_arg(args, const EVP_MD *); ++ if (md == NULL) ++ return 0; ++ ++ impl->md = md; ++ return 1; ++ ++ default: ++ return -2; ++ } ++} ++ ++static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, ++ const char *value) ++{ ++ if (strcmp(type, "secret") == 0 || strcmp(type, "key") == 0) ++ return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_KEY, ++ value); ++ ++ if (strcmp(type, "hexsecret") == 0 || strcmp(type, "hexkey") == 0) ++ return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_KEY, ++ value); ++ ++ if (strcmp(type, "info") == 0) ++ return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SSKDF_INFO, ++ value); ++ ++ if (strcmp(type, "hexinfo") == 0) ++ return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SSKDF_INFO, ++ value); ++ ++ if (strcmp(type, "digest") == 0) ++ return kdf_md2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MD, value); ++ ++ return -2; ++} ++ ++static size_t sskdf_size(EVP_KDF_IMPL *impl) ++{ ++ int len; ++ ++ if (impl->md == NULL) { ++ KDFerr(KDF_F_SSKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST); ++ return 0; ++ } ++ len = EVP_MD_size(impl->md); ++ return (len <= 0) ? 0 : (size_t)len; ++} ++ ++static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen) ++{ ++ if (impl->secret == NULL) { ++ KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_SECRET); ++ return 0; ++ } ++ ++ /* H(x) = hash */ ++ if (impl->md == NULL) { ++ KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); ++ return 0; ++ } ++ return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len, ++ impl->info, impl->info_len, key, keylen); ++} ++ ++const EVP_KDF_METHOD ss_kdf_meth = { ++ EVP_KDF_SS, ++ sskdf_new, ++ sskdf_free, ++ sskdf_reset, ++ sskdf_ctrl, ++ sskdf_ctrl_str, ++ sskdf_size, ++ sskdf_derive ++}; +diff -up openssl-1.1.1c/crypto/objects/obj_dat.h.krb5-kdf openssl-1.1.1c/crypto/objects/obj_dat.h +--- openssl-1.1.1c/crypto/objects/obj_dat.h.krb5-kdf 2019-11-14 16:25:09.447914673 +0100 ++++ openssl-1.1.1c/crypto/objects/obj_dat.h 2019-11-14 16:25:09.477914130 +0100 +@@ -1078,7 +1078,7 @@ static const unsigned char so[7762] = { + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */ + }; + +-#define NUM_NID 1196 ++#define NUM_NID 1199 + static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"UNDEF", "undefined", NID_undef}, + {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, +@@ -2276,9 +2276,12 @@ static const ASN1_OBJECT nid_objs[NUM_NI + {"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]}, + {"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]}, + {"SSHKDF", "sshkdf", NID_sshkdf}, ++ {"KBKDF", "kbkdf", NID_kbkdf}, ++ {"KRB5KDF", "krb5kdf", NID_krb5kdf}, ++ {"SSKDF", "sskdf", NID_sskdf}, + }; + +-#define NUM_SN 1187 ++#define NUM_SN 1190 + static const unsigned int sn_objs[NUM_SN] = { + 364, /* "AD_DVCS" */ + 419, /* "AES-128-CBC" */ +@@ -2442,7 +2445,9 @@ static const unsigned int sn_objs[NUM_SN + 183, /* "ISO-US" */ + 645, /* "ITU-T" */ + 646, /* "JOINT-ISO-ITU-T" */ ++ 1196, /* "KBKDF" */ + 773, /* "KISA" */ ++ 1197, /* "KRB5KDF" */ + 1063, /* "KxANY" */ + 1039, /* "KxDHE" */ + 1041, /* "KxDHE-PSK" */ +@@ -2557,6 +2562,7 @@ static const unsigned int sn_objs[NUM_SN + 100, /* "SN" */ + 1006, /* "SNILS" */ + 1195, /* "SSHKDF" */ ++ 1198, /* "SSKDF" */ + 16, /* "ST" */ + 143, /* "SXNetID" */ + 1062, /* "SipHash" */ +@@ -3469,7 +3475,7 @@ static const unsigned int sn_objs[NUM_SN + 1093, /* "x509ExtAdmission" */ + }; + +-#define NUM_LN 1187 ++#define NUM_LN 1190 + static const unsigned int ln_objs[NUM_LN] = { + 363, /* "AD Time Stamping" */ + 405, /* "ANSI X9.62" */ +@@ -4262,8 +4268,10 @@ static const unsigned int ln_objs[NUM_LN + 957, /* "jurisdictionCountryName" */ + 955, /* "jurisdictionLocalityName" */ + 956, /* "jurisdictionStateOrProvinceName" */ ++ 1196, /* "kbkdf" */ + 150, /* "keyBag" */ + 773, /* "kisa" */ ++ 1197, /* "krb5kdf" */ + 1063, /* "kx-any" */ + 1039, /* "kx-dhe" */ + 1041, /* "kx-dhe-psk" */ +@@ -4612,6 +4620,7 @@ static const unsigned int ln_objs[NUM_LN + 1133, /* "sm4-ecb" */ + 1135, /* "sm4-ofb" */ + 1195, /* "sshkdf" */ ++ 1198, /* "sskdf" */ + 16, /* "stateOrProvinceName" */ + 660, /* "streetAddress" */ + 498, /* "subtreeMaximumQuality" */ +diff -up openssl-1.1.1c/crypto/objects/objects.txt.krb5-kdf openssl-1.1.1c/crypto/objects/objects.txt +--- openssl-1.1.1c/crypto/objects/objects.txt.krb5-kdf 2019-11-14 16:25:09.447914673 +0100 ++++ openssl-1.1.1c/crypto/objects/objects.txt 2019-11-14 16:25:09.477914130 +0100 +@@ -1603,6 +1603,15 @@ secg-scheme 14 3 : dhSinglePass-cofactor + # NID for SSHKDF + : SSHKDF : sshkdf + ++# NID for KBKDF ++ : KBKDF : kbkdf ++ ++# NID for KRB5KDF ++ : KRB5KDF : krb5kdf ++ ++# NID for SSKDF ++ : SSKDF : sskdf ++ + # RFC 4556 + 1 3 6 1 5 2 3 : id-pkinit + id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth +diff -up openssl-1.1.1c/crypto/objects/obj_mac.num.krb5-kdf openssl-1.1.1c/crypto/objects/obj_mac.num +--- openssl-1.1.1c/crypto/objects/obj_mac.num.krb5-kdf 2019-11-14 16:25:09.447914673 +0100 ++++ openssl-1.1.1c/crypto/objects/obj_mac.num 2019-11-14 16:25:09.477914130 +0100 +@@ -1193,3 +1193,6 @@ magma_mac 1192 + hmacWithSHA512_224 1193 + hmacWithSHA512_256 1194 + sshkdf 1195 ++kbkdf 1196 ++krb5kdf 1197 ++sskdf 1198 +diff -up openssl-1.1.1c/doc/man3/EVP_KDF_CTX.pod.krb5-kdf openssl-1.1.1c/doc/man3/EVP_KDF_CTX.pod +--- openssl-1.1.1c/doc/man3/EVP_KDF_CTX.pod.krb5-kdf 2019-11-14 16:25:09.439914818 +0100 ++++ openssl-1.1.1c/doc/man3/EVP_KDF_CTX.pod 2019-11-14 16:25:09.477914130 +0100 +@@ -140,7 +140,14 @@ The value string is expected to be a dec + This control expects one argument: C + + For MAC implementations that use a message digest as an underlying computation +-algorithm, this control set what the digest algorithm should be. ++algorithm, this control sets what the digest algorithm should be. ++ ++=item B ++ ++This control expects one argument: C ++ ++For MAC implementations that use a cipher as an underlying computation ++algorithm, this control sets what the cipher algorithm should be. + + EVP_KDF_ctrl_str() type string: "md" + +diff -up openssl-1.1.1c/doc/man7/EVP_KDF_KB.pod.krb5-kdf openssl-1.1.1c/doc/man7/EVP_KDF_KB.pod +--- openssl-1.1.1c/doc/man7/EVP_KDF_KB.pod.krb5-kdf 2019-11-14 16:25:09.478914112 +0100 ++++ openssl-1.1.1c/doc/man7/EVP_KDF_KB.pod 2019-11-14 16:25:09.478914112 +0100 +@@ -0,0 +1,173 @@ ++=pod ++ ++=head1 NAME ++ ++EVP_KDF_KB - The Key-Based EVP_KDF implementation ++ ++=head1 DESCRIPTION ++ ++The EVP_KDF_KB algorithm implements the Key-Based key derivation function ++(KBKDF). KBKDF derives a key from repeated application of a keyed MAC to an ++input secret (and other optional values). ++ ++=head2 Numeric identity ++ ++B is the numeric identity for this implementation; it can be used with the ++EVP_KDF_CTX_new_id() function. ++ ++=head2 Supported controls ++ ++The supported controls are: ++ ++=over 4 ++ ++=item B ++ ++This control expects one argument: C ++ ++Sets the mode for the KBKDF operation. There are two supported modes: ++ ++=over 4 ++ ++=item B ++ ++The counter mode of KBKDF should be used. This is the default. ++ ++=item B ++ ++The feedback mode of KBKDF should be used. ++ ++=back ++ ++=item B ++ ++This control expects one argument: C ++ ++Sets the mac type for the KBKDF operation. There are two supported mac types: ++ ++=over 4 ++ ++=item B ++ ++The HMAC with the digest set by B should be used as the mac. ++ ++=item B ++ ++The CMAC with the cipher set by B should be used as the mac. ++ ++=back ++ ++=item B ++ ++=item B ++ ++=item B ++ ++=item B ++ ++These controls work as described in L. ++ ++=item B ++ ++This control expects two arguments: C, C ++ ++=item B ++ ++This control expects two arguments: C, C ++ ++It is used only in the feedback mode and the length must be the same ++as the block length of the cipher in CMAC or the size of the digest in HMAC. ++ ++=back ++ ++The controls B, B, ++B, and B ++correspond to KI, Label, Context, and IV (respectively) in SP800-108. ++As in that document, salt, info, and seed are optional and may be ++omitted. ++ ++Depending on whether mac is CMAC or HMAC, either digest or cipher is ++required (respectively) and the other is unused. ++ ++=head1 NOTES ++ ++A context for KBKDF can be obtained by calling: ++ ++ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB); ++ ++The output length of an KBKDF is specified via the C ++parameter to the L function. ++ ++Note that currently OpenSSL only implements counter and feedback modes. Other ++variants may be supported in the future. ++ ++=head1 EXAMPLES ++ ++This example derives 10 bytes using COUNTER-HMAC-SHA256, with KI "secret", ++Label "label", and Context "context". ++ ++ EVP_KDF_CTX *kctx; ++ unsigned char out[10]; ++ ++ kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB); ++ ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_HMAC); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", strlen("secret")); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "label", strlen("label")); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_INFO, "context", strlen("context")); ++ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) ++ error("EVP_KDF_derive"); ++ ++ EVP_KDF_CTX_free(kctx); ++ ++This example derives 10 bytes using FEEDBACK-CMAC-AES256, with KI "secret", ++Label "label", Context "context", and IV "sixteen bytes iv". ++ ++ EVP_KDF_CTX *kctx; ++ unsigned char out[10]; ++ unsigned char *iv = "sixteen bytes iv"; ++ ++ kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB); ++ ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CIPHER, EVP_aes_256_cbc()); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_CMAC); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MODE, EVP_KDF_KB_MODE_FEEDBACK); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", strlen("secret")); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "label", strlen("label")); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_INFO, "context", strlen("context")); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_SEED, iv, strlen(iv)); ++ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) ++ error("EVP_KDF_derive"); ++ ++ EVP_KDF_CTX_free(kctx); ++ ++=head1 CONFORMING TO ++ ++NIST SP800-108, IETF RFC 6803, IETF RFC 8009. ++ ++=head1 SEE ALSO ++ ++L, ++L, ++L, ++L, ++L, ++L, ++L ++ ++=head1 HISTORY ++ ++This functionality was added to OpenSSL 3.0. ++ ++=head1 COPYRIGHT ++ ++Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. ++Copyright 2019 Red Hat, 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 ++L. ++ ++=cut +diff -up openssl-1.1.1c/doc/man7/EVP_KDF_KRB5KDF.pod.krb5-kdf openssl-1.1.1c/doc/man7/EVP_KDF_KRB5KDF.pod +--- openssl-1.1.1c/doc/man7/EVP_KDF_KRB5KDF.pod.krb5-kdf 2019-11-14 16:25:09.478914112 +0100 ++++ openssl-1.1.1c/doc/man7/EVP_KDF_KRB5KDF.pod 2019-11-14 16:25:09.478914112 +0100 +@@ -0,0 +1,107 @@ ++=pod ++ ++=head1 NAME ++ ++EVP_KDF_KRB5KDF - The RFC3961 Krb5 KDF EVP_KDF implementation ++ ++=head1 DESCRIPTION ++ ++Support for computing the B KDF through the B API. ++ ++The B algorithm implements the key derivation function defined ++in RFC 3961, section 5.1 and is used by Krb5 to derive session keys. ++Three inputs are required to perform key derivation: a cipher, (for example ++AES-128-CBC), the initial key, and a constant. ++ ++=head2 Numeric identity ++ ++B is the numeric identity for this implementation; it can be used with the ++EVP_KDF_CTX_new_id() function. ++ ++=head2 Supported controls ++ ++The supported controls are: ++ ++=over 4 ++ ++=item B ++ ++=item B ++ ++These controls work as described in L. ++ ++=item B ++ ++This control expects two arguments: C, C ++ ++This control sets the I value for the KDF. ++If a value is already set, the contents are replaced. ++ ++=back ++ ++ ++=head1 NOTES ++ ++A context for KRB5KDF can be obtained by calling: ++ ++ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF); ++ ++The output length of the KRB5KDF derivation is specified via the I ++parameter to the L function, and MUST match the key ++length for the chosen cipher or an error is returned. Moreover the ++I's length must not exceed the block size of the cipher. ++Since the KRB5KDF output length depends on the chosen cipher, calling ++L to obtain the requisite length returns the correct length ++only after the cipher is set. Prior to that B is returned. ++The caller must allocate a buffer of the correct length for the chosen ++cipher, and pass that buffer to the L function along ++with that length. ++ ++=head1 EXAMPLES ++ ++This example derives a key using the AES-128-CBC cipher: ++ ++ EVP_KDF_CTX *kctx; ++ unsigned char key[16] = "01234..."; ++ unsigned char constant[] = "I'm a constant"; ++ unsigned char out[16]; ++ size_t outlen = sizeof(out); ++ ++ kctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF); ++ ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CIPHER, EVP_aes_128_cbc()); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, key, (size_t)16); ++ EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT, constant, strlen(constant)); ++ if (EVP_KDF_derive(kctx, out, outlen) <= 0) ++ /* Error */ ++ EVP_KDF_CTX_free(kctx); ++ ++=head1 CONFORMING TO ++ ++RFC 3961 ++ ++=head1 SEE ALSO ++ ++L, ++L, ++L, ++L, ++L, ++L, ++L ++ ++=head1 HISTORY ++ ++This functionality was added to OpenSSL 3.0. ++ ++=head1 COPYRIGHT ++ ++Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. ++ ++Licensed under the OpenSSL license (the "License"). You may not use ++this file except in compliance with the License. You can obtain a copy ++in the file LICENSE in the source distribution or at ++L. ++ ++=cut ++ +diff -up openssl-1.1.1c/doc/man7/EVP_KDF_SS.pod.krb5-kdf openssl-1.1.1c/doc/man7/EVP_KDF_SS.pod +--- openssl-1.1.1c/doc/man7/EVP_KDF_SS.pod.krb5-kdf 2019-11-14 16:25:09.478914112 +0100 ++++ openssl-1.1.1c/doc/man7/EVP_KDF_SS.pod 2019-11-14 16:25:09.478914112 +0100 +@@ -0,0 +1,146 @@ ++=pod ++ ++=head1 NAME ++ ++EVP_KDF_SS - The Single Step / One Step EVP_KDF implementation ++ ++=head1 DESCRIPTION ++ ++The EVP_KDF_SS algorithm implements the Single Step key derivation function (SSKDF). ++SSKDF derives a key using input such as a shared secret key (that was generated ++during the execution of a key establishment scheme) and fixedinfo. ++SSKDF is also informally referred to as 'Concat KDF'. ++ ++=head2 Auxilary function ++ ++The implementation uses a selectable auxiliary function H, which can be in the ++backported version only a: ++ ++=over 4 ++ ++=item B ++ ++=back ++ ++=head2 Numeric identity ++ ++B is the numeric identity for this implementation; it ++can be used with the EVP_KDF_CTX_new_id() function. ++ ++=head2 Supported controls ++ ++The supported controls are: ++ ++=over 4 ++ ++=item B ++ ++This control works as described in L. ++ ++=item B ++ ++This control expects two arguments: C, C ++ ++The shared secret used for key derivation. This control sets the secret. ++ ++EVP_KDF_ctrl_str() takes two type strings for this control: ++ ++=over 4 ++ ++=item "secret" ++ ++The value string is used as is. ++ ++=item "hexsecret" ++ ++The value string is expected to be a hexadecimal number, which will be ++decoded before being passed on as the control value. ++ ++=back ++ ++=item B ++ ++This control expects two arguments: C, C ++ ++An optional value for fixedinfo, also known as otherinfo. This control sets the fixedinfo. ++ ++EVP_KDF_ctrl_str() takes two type strings for this control: ++ ++=over 4 ++ ++=item "info" ++ ++The value string is used as is. ++ ++=item "hexinfo" ++ ++The value string is expected to be a hexadecimal number, which will be ++decoded before being passed on as the control value. ++ ++=back ++ ++=back ++ ++=head1 NOTES ++ ++A context for SSKDF can be obtained by calling: ++ ++EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS); ++ ++The output length of an SSKDF is specified via the C ++parameter to the L function. ++ ++=head1 EXAMPLE ++ ++This example derives 10 bytes using H(x) = SHA-256, with the secret key "secret" ++and fixedinfo value "label": ++ ++ EVP_KDF_CTX *kctx; ++ unsigned char out[10]; ++ ++ kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS); ++ ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) { ++ error("EVP_KDF_CTRL_SET_MD"); ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) { ++ error("EVP_KDF_CTRL_SET_KEY"); ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, "label", (size_t)5) <= 0) { ++ error("EVP_KDF_CTRL_SET_SSKDF_INFO"); ++ } ++ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) { ++ error("EVP_KDF_derive"); ++ } ++ ++ EVP_KDF_CTX_free(kctx); ++ ++=head1 CONFORMING TO ++ ++NIST SP800-56Cr1. ++ ++=head1 SEE ALSO ++ ++L, ++L, ++L, ++L, ++L, ++L, ++L ++ ++=head1 HISTORY ++ ++This functionality was added to OpenSSL 3.0.0. ++ ++=head1 COPYRIGHT ++ ++Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. Copyright ++(c) 2019, Oracle and/or its affiliates. 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 ++L. ++ ++=cut +diff -up openssl-1.1.1c/include/openssl/kdferr.h.krb5-kdf openssl-1.1.1c/include/openssl/kdferr.h +--- openssl-1.1.1c/include/openssl/kdferr.h.krb5-kdf 2019-11-14 16:25:09.448914655 +0100 ++++ openssl-1.1.1c/include/openssl/kdferr.h 2019-11-14 16:25:09.478914112 +0100 +@@ -20,6 +20,11 @@ int ERR_load_KDF_strings(void); + * KDF function codes. + */ + # define KDF_F_HKDF_EXTRACT 112 ++# define KDF_F_KBKDF_CTRL 134 ++# define KDF_F_KBKDF_CTRL_STR 135 ++# define KDF_F_KBKDF_DERIVE 136 ++# define KDF_F_KBKDF_NEW 137 ++# define KDF_F_KDF_CIPHER2CTRL 138 + # define KDF_F_KDF_HKDF_DERIVE 113 + # define KDF_F_KDF_HKDF_NEW 114 + # define KDF_F_KDF_HKDF_SIZE 115 +@@ -39,6 +44,8 @@ int ERR_load_KDF_strings(void); + # define KDF_F_KDF_TLS1_PRF_CTRL_STR 125 + # define KDF_F_KDF_TLS1_PRF_DERIVE 126 + # define KDF_F_KDF_TLS1_PRF_NEW 127 ++# define KDF_F_KRB5KDF 139 ++# define KDF_F_KRB5KDF_DERIVE 140 + # define KDF_F_PBKDF2_SET_MEMBUF 128 + # define KDF_F_PKEY_HKDF_CTRL_STR 103 + # define KDF_F_PKEY_HKDF_DERIVE 102 +@@ -52,12 +59,21 @@ int ERR_load_KDF_strings(void); + # define KDF_F_PKEY_TLS1_PRF_DERIVE 101 + # define KDF_F_PKEY_TLS1_PRF_INIT 110 + # define KDF_F_SCRYPT_SET_MEMBUF 129 ++# define KDF_F_SSKDF_DERIVE 141 ++# define KDF_F_SSKDF_NEW 142 ++# define KDF_F_SSKDF_SIZE 143 + # define KDF_F_TLS1_PRF_ALG 111 + + /* + * KDF reason codes. + */ ++# define KDF_R_FAILED_TO_GENERATE_KEY 118 ++# define KDF_R_INVALID_CIPHER 116 ++# define KDF_R_INVALID_CONSTANT_LENGTH 119 + # define KDF_R_INVALID_DIGEST 100 ++# define KDF_R_INVALID_SEED_LENGTH 117 ++# define KDF_R_MISSING_CIPHER 120 ++# define KDF_R_MISSING_CONSTANT 121 + # define KDF_R_MISSING_ITERATION_COUNT 109 + # define KDF_R_MISSING_KEY 104 + # define KDF_R_MISSING_MESSAGE_DIGEST 105 +@@ -72,6 +88,7 @@ int ERR_load_KDF_strings(void); + # define KDF_R_UNKNOWN_PARAMETER_TYPE 103 + # define KDF_R_VALUE_ERROR 108 + # define KDF_R_VALUE_MISSING 102 ++# define KDF_R_WRONG_FINAL_BLOCK_LENGTH 122 + # define KDF_R_WRONG_OUTPUT_BUFFER_SIZE 112 + + #endif +diff -up openssl-1.1.1c/include/openssl/kdf.h.krb5-kdf openssl-1.1.1c/include/openssl/kdf.h +--- openssl-1.1.1c/include/openssl/kdf.h.krb5-kdf 2019-11-14 16:25:09.448914655 +0100 ++++ openssl-1.1.1c/include/openssl/kdf.h 2019-11-14 16:25:09.478914112 +0100 +@@ -21,6 +21,9 @@ extern "C" { + # define EVP_KDF_TLS1_PRF NID_tls1_prf + # define EVP_KDF_HKDF NID_hkdf + # define EVP_KDF_SSHKDF NID_sshkdf ++# define EVP_KDF_KB NID_kbkdf ++# define EVP_KDF_KRB5KDF NID_krb5kdf ++# define EVP_KDF_SS NID_sskdf + + EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id); + void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx); +@@ -51,6 +54,13 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, uns + # define EVP_KDF_CTRL_SET_SSHKDF_XCGHASH 0x10 /* unsigned char *, size_t */ + # define EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID 0x11 /* unsigned char *, size_t */ + # define EVP_KDF_CTRL_SET_SSHKDF_TYPE 0x12 /* int */ ++# define EVP_KDF_CTRL_SET_KB_MODE 0x13 /* int */ ++# define EVP_KDF_CTRL_SET_KB_MAC_TYPE 0x14 /* int */ ++# define EVP_KDF_CTRL_SET_CIPHER 0x15 /* EVP_CIPHER * */ ++# define EVP_KDF_CTRL_SET_KB_INFO 0x16 /* unsigned char *, size_t */ ++# define EVP_KDF_CTRL_SET_KB_SEED 0x17 /* unsigned char *, size_t */ ++# define EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT 0x18 /* unsigned char *, size_t */ ++# define EVP_KDF_CTRL_SET_SSKDF_INFO 0x19 /* unsigned char *, size_t */ + + # define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND 0 + # define EVP_KDF_HKDF_MODE_EXTRACT_ONLY 1 +@@ -63,6 +73,12 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, uns + #define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_CLI_TO_SRV 69 + #define EVP_KDF_SSHKDF_TYPE_INTEGRITY_KEY_SRV_TO_CLI 70 + ++#define EVP_KDF_KB_MODE_COUNTER 0 ++#define EVP_KDF_KB_MODE_FEEDBACK 1 ++ ++#define EVP_KDF_KB_MAC_TYPE_HMAC 0 ++#define EVP_KDF_KB_MAC_TYPE_CMAC 1 ++ + /**** The legacy PKEY-based KDF API follows. ****/ + + # define EVP_PKEY_CTRL_TLS_MD (EVP_PKEY_ALG_CTRL) +diff -up openssl-1.1.1c/include/openssl/obj_mac.h.krb5-kdf openssl-1.1.1c/include/openssl/obj_mac.h +--- openssl-1.1.1c/include/openssl/obj_mac.h.krb5-kdf 2019-11-14 16:25:09.449914637 +0100 ++++ openssl-1.1.1c/include/openssl/obj_mac.h 2019-11-14 16:25:09.479914093 +0100 +@@ -4974,6 +4974,18 @@ + #define LN_sshkdf "sshkdf" + #define NID_sshkdf 1203 + ++#define SN_kbkdf "KBKDF" ++#define LN_kbkdf "kbkdf" ++#define NID_kbkdf 1204 ++ ++#define SN_krb5kdf "KRB5KDF" ++#define LN_krb5kdf "krb5kdf" ++#define NID_krb5kdf 1205 ++ ++#define SN_sskdf "SSKDF" ++#define LN_sskdf "sskdf" ++#define NID_sskdf 1206 ++ + #define SN_id_pkinit "id-pkinit" + #define NID_id_pkinit 1031 + #define OBJ_id_pkinit 1L,3L,6L,1L,5L,2L,3L +diff -up openssl-1.1.1c/test/evp_kdf_test.c.krb5-kdf openssl-1.1.1c/test/evp_kdf_test.c +--- openssl-1.1.1c/test/evp_kdf_test.c.krb5-kdf 2019-11-14 16:25:09.441914782 +0100 ++++ openssl-1.1.1c/test/evp_kdf_test.c 2019-11-14 16:25:09.479914093 +0100 +@@ -225,13 +225,358 @@ err: + } + #endif + ++/* ++ * KBKDF test vectors from RFC 6803 (Camellia Encryption for Kerberos 5) ++ * section 10. ++ */ ++static int test_kdf_kbkdf_6803_128(void) ++{ ++ int ret = 0, i; ++ EVP_KDF_CTX *kctx; ++ static unsigned char input_key[] = { ++ 0x57, 0xD0, 0x29, 0x72, 0x98, 0xFF, 0xD9, 0xD3, ++ 0x5D, 0xE5, 0xA4, 0x7F, 0xB4, 0xBD, 0xE2, 0x4B, ++ }; ++ static unsigned char constants[][5] = { ++ { 0x00, 0x00, 0x00, 0x02, 0x99 }, ++ { 0x00, 0x00, 0x00, 0x02, 0xaa }, ++ { 0x00, 0x00, 0x00, 0x02, 0x55 }, ++ }; ++ static unsigned char outputs[][16] = { ++ {0xD1, 0x55, 0x77, 0x5A, 0x20, 0x9D, 0x05, 0xF0, ++ 0x2B, 0x38, 0xD4, 0x2A, 0x38, 0x9E, 0x5A, 0x56}, ++ {0x64, 0xDF, 0x83, 0xF8, 0x5A, 0x53, 0x2F, 0x17, ++ 0x57, 0x7D, 0x8C, 0x37, 0x03, 0x57, 0x96, 0xAB}, ++ {0x3E, 0x4F, 0xBD, 0xF3, 0x0F, 0xB8, 0x25, 0x9C, ++ 0x42, 0x5C, 0xB6, 0xC9, 0x6F, 0x1F, 0x46, 0x35} ++ }; ++ static unsigned char iv[16] = { 0 }; ++ unsigned char result[16] = { 0 }; ++ ++ for (i = 0; i < 3; i++) { ++ ret = 0; ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB)) == NULL) { ++ TEST_error("EVP_KDF_KB"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_CMAC) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MAC_TYPE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MODE, EVP_KDF_KB_MODE_FEEDBACK) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MODE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CIPHER, EVP_camellia_128_cbc()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_CIPHER"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, input_key, sizeof(input_key)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, constants[i], sizeof(constants[i])) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_SALT"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_SEED, iv, sizeof(iv)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_SEED"); ++ goto err; ++ } ++ ret = TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) ++ && TEST_mem_eq(result, sizeof(result), outputs[i], ++ sizeof(outputs[i])); ++err: ++ EVP_KDF_CTX_free(kctx); ++ if (ret != 1) ++ return ret; ++ } ++ return ret; ++} ++ ++static int test_kdf_kbkdf_6803_256(void) ++{ ++ int ret = 0, i; ++ EVP_KDF_CTX *kctx; ++ static unsigned char input_key[] = { ++ 0xB9, 0xD6, 0x82, 0x8B, 0x20, 0x56, 0xB7, 0xBE, ++ 0x65, 0x6D, 0x88, 0xA1, 0x23, 0xB1, 0xFA, 0xC6, ++ 0x82, 0x14, 0xAC, 0x2B, 0x72, 0x7E, 0xCF, 0x5F, ++ 0x69, 0xAF, 0xE0, 0xC4, 0xDF, 0x2A, 0x6D, 0x2C, ++ }; ++ static unsigned char constants[][5] = { ++ { 0x00, 0x00, 0x00, 0x02, 0x99 }, ++ { 0x00, 0x00, 0x00, 0x02, 0xaa }, ++ { 0x00, 0x00, 0x00, 0x02, 0x55 }, ++ }; ++ static unsigned char outputs[][32] = { ++ {0xE4, 0x67, 0xF9, 0xA9, 0x55, 0x2B, 0xC7, 0xD3, ++ 0x15, 0x5A, 0x62, 0x20, 0xAF, 0x9C, 0x19, 0x22, ++ 0x0E, 0xEE, 0xD4, 0xFF, 0x78, 0xB0, 0xD1, 0xE6, ++ 0xA1, 0x54, 0x49, 0x91, 0x46, 0x1A, 0x9E, 0x50, ++ }, ++ {0x41, 0x2A, 0xEF, 0xC3, 0x62, 0xA7, 0x28, 0x5F, ++ 0xC3, 0x96, 0x6C, 0x6A, 0x51, 0x81, 0xE7, 0x60, ++ 0x5A, 0xE6, 0x75, 0x23, 0x5B, 0x6D, 0x54, 0x9F, ++ 0xBF, 0xC9, 0xAB, 0x66, 0x30, 0xA4, 0xC6, 0x04, ++ }, ++ {0xFA, 0x62, 0x4F, 0xA0, 0xE5, 0x23, 0x99, 0x3F, ++ 0xA3, 0x88, 0xAE, 0xFD, 0xC6, 0x7E, 0x67, 0xEB, ++ 0xCD, 0x8C, 0x08, 0xE8, 0xA0, 0x24, 0x6B, 0x1D, ++ 0x73, 0xB0, 0xD1, 0xDD, 0x9F, 0xC5, 0x82, 0xB0, ++ }, ++ }; ++ static unsigned char iv[16] = { 0 }; ++ unsigned char result[32] = { 0 }; ++ ++ for (i = 0; i < 3; i++) { ++ ret = 0; ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB)) == NULL) { ++ TEST_error("EVP_KDF_KB"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_CMAC) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MAC_TYPE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MODE, EVP_KDF_KB_MODE_FEEDBACK) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MODE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CIPHER, EVP_camellia_256_cbc()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_CIPHER"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, input_key, sizeof(input_key)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, constants[i], sizeof(constants[i])) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_SALT"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_SEED, iv, sizeof(iv)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_SEED"); ++ goto err; ++ } ++ ret = TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) ++ && TEST_mem_eq(result, sizeof(result), outputs[i], ++ sizeof(outputs[i])); ++err: ++ EVP_KDF_CTX_free(kctx); ++ if (ret != 1) ++ return ret; ++ } ++ return ret; ++} ++ ++/* Two test vectors from RFC 8009 (AES Encryption with HMAC-SHA2 for Kerberos ++ * 5) appendix A. */ ++static int test_kdf_kbkdf_8009_prf1(void) ++{ ++ int ret = 0; ++ EVP_KDF_CTX *kctx; ++ char *label = "prf", *prf_input = "test"; ++ static unsigned char input_key[] = { ++ 0x37, 0x05, 0xD9, 0x60, 0x80, 0xC1, 0x77, 0x28, ++ 0xA0, 0xE8, 0x00, 0xEA, 0xB6, 0xE0, 0xD2, 0x3C, ++ }; ++ static unsigned char output[] = { ++ 0x9D, 0x18, 0x86, 0x16, 0xF6, 0x38, 0x52, 0xFE, ++ 0x86, 0x91, 0x5B, 0xB8, 0x40, 0xB4, 0xA8, 0x86, ++ 0xFF, 0x3E, 0x6B, 0xB0, 0xF8, 0x19, 0xB4, 0x9B, ++ 0x89, 0x33, 0x93, 0xD3, 0x93, 0x85, 0x42, 0x95, ++ }; ++ unsigned char result[sizeof(output)] = { 0 }; ++ ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB)) == NULL) { ++ TEST_error("EVP_KDF_KB"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_HMAC) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MAC_TYPE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_MD"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, input_key, sizeof(input_key)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, label, strlen(label)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_SALT"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_INFO, prf_input, strlen(prf_input)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_INFO"); ++ goto err; ++ } ++ ret = TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) ++ && TEST_mem_eq(result, sizeof(result), output, ++ sizeof(output)); ++err: ++ EVP_KDF_CTX_free(kctx); ++ return ret; ++} ++ ++static int test_kdf_kbkdf_8009_prf2(void) ++{ ++ int ret = 0; ++ EVP_KDF_CTX *kctx; ++ char *label = "prf", *prf_input = "test"; ++ static unsigned char input_key[] = { ++ 0x6D, 0x40, 0x4D, 0x37, 0xFA, 0xF7, 0x9F, 0x9D, ++ 0xF0, 0xD3, 0x35, 0x68, 0xD3, 0x20, 0x66, 0x98, ++ 0x00, 0xEB, 0x48, 0x36, 0x47, 0x2E, 0xA8, 0xA0, ++ 0x26, 0xD1, 0x6B, 0x71, 0x82, 0x46, 0x0C, 0x52, ++ }; ++ static unsigned char output[] = { ++ 0x98, 0x01, 0xF6, 0x9A, 0x36, 0x8C, 0x2B, 0xF6, ++ 0x75, 0xE5, 0x95, 0x21, 0xE1, 0x77, 0xD9, 0xA0, ++ 0x7F, 0x67, 0xEF, 0xE1, 0xCF, 0xDE, 0x8D, 0x3C, ++ 0x8D, 0x6F, 0x6A, 0x02, 0x56, 0xE3, 0xB1, 0x7D, ++ 0xB3, 0xC1, 0xB6, 0x2A, 0xD1, 0xB8, 0x55, 0x33, ++ 0x60, 0xD1, 0x73, 0x67, 0xEB, 0x15, 0x14, 0xD2, ++ }; ++ unsigned char result[sizeof(output)] = { 0 }; ++ ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB)) == NULL) { ++ TEST_error("EVP_KDF_KB"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_HMAC) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_MAC_TYPE"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha384()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_MD"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, input_key, sizeof(input_key)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, label, strlen(label)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_SALT"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_INFO, prf_input, strlen(prf_input)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KB_INFO"); ++ goto err; ++ } ++ ret = TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) ++ && TEST_mem_eq(result, sizeof(result), output, ++ sizeof(output)); ++err: ++ EVP_KDF_CTX_free(kctx); ++ return ret; ++} ++ ++static int test_kdf_krb5kdf(void) ++{ ++ int ret = 0; ++ EVP_KDF_CTX *kctx; ++ unsigned char out[16]; ++ static unsigned char key[] = { ++ 0x42, 0x26, 0x3C, 0x6E, 0x89, 0xF4, 0xFC, 0x28, ++ 0xB8, 0xDF, 0x68, 0xEE, 0x09, 0x79, 0x9F, 0x15 ++ }; ++ static unsigned char constant[] = { ++ 0x00, 0x00, 0x00, 0x02, 0x99 ++ }; ++ static const unsigned char expected[sizeof(out)] = { ++ 0x34, 0x28, 0x0A, 0x38, 0x2B, 0xC9, 0x27, 0x69, ++ 0xB2, 0xDA, 0x2F, 0x9E, 0xF0, 0x66, 0x85, 0x4B ++ }; ++ ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KRB5KDF)) == NULL) { ++ TEST_error("EVP_KDF_KRB5KDF"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CIPHER, EVP_aes_128_cbc()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_CIPHER"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, key, sizeof(key)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT, constant, sizeof(constant)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KRB5KDF_CONSTANT"); ++ goto err; ++ } ++ ++ ret = ++ TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out)), 0) ++ && TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)); ++ ++err: ++ EVP_KDF_CTX_free(kctx); ++ return ret; ++} ++ ++static int test_kdf_ss_hash(void) ++{ ++ EVP_KDF_CTX *kctx; ++ const unsigned char z[] = { ++ 0x6d,0xbd,0xc2,0x3f,0x04,0x54,0x88,0xe4,0x06,0x27,0x57,0xb0,0x6b,0x9e, ++ 0xba,0xe1,0x83,0xfc,0x5a,0x59,0x46,0xd8,0x0d,0xb9,0x3f,0xec,0x6f,0x62, ++ 0xec,0x07,0xe3,0x72,0x7f,0x01,0x26,0xae,0xd1,0x2c,0xe4,0xb2,0x62,0xf4, ++ 0x7d,0x48,0xd5,0x42,0x87,0xf8,0x1d,0x47,0x4c,0x7c,0x3b,0x18,0x50,0xe9 ++ }; ++ const unsigned char other[] = { ++ 0xa1,0xb2,0xc3,0xd4,0xe5,0x43,0x41,0x56,0x53,0x69,0x64,0x3c,0x83,0x2e, ++ 0x98,0x49,0xdc,0xdb,0xa7,0x1e,0x9a,0x31,0x39,0xe6,0x06,0xe0,0x95,0xde, ++ 0x3c,0x26,0x4a,0x66,0xe9,0x8a,0x16,0x58,0x54,0xcd,0x07,0x98,0x9b,0x1e, ++ 0xe0,0xec,0x3f,0x8d,0xbe ++ }; ++ const unsigned char expected[] = { ++ 0xa4,0x62,0xde,0x16,0xa8,0x9d,0xe8,0x46,0x6e,0xf5,0x46,0x0b,0x47,0xb8 ++ }; ++ unsigned char out[14]; ++ ++ kctx = EVP_KDF_CTX_new_id(EVP_KDF_SS); ++ ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha224()) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_MD"); ++ return 0; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, z, sizeof(z)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_KEY"); ++ return 0; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSKDF_INFO, other, ++ sizeof(other)) <= 0) { ++ TEST_error("EVP_KDF_CTRL_SET_SSKDF_INFO"); ++ return 0; ++ } ++ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) { ++ TEST_error("EVP_KDF_derive"); ++ return 0; ++ } ++ ++ if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) ++ return 0; ++ ++ EVP_KDF_CTX_free(kctx); ++ return 1; ++} ++ + int setup_tests(void) + { ++ ADD_TEST(test_kdf_kbkdf_6803_128); ++ ADD_TEST(test_kdf_kbkdf_6803_256); ++ ADD_TEST(test_kdf_kbkdf_8009_prf1); ++ ADD_TEST(test_kdf_kbkdf_8009_prf2); + ADD_TEST(test_kdf_tls1_prf); + ADD_TEST(test_kdf_hkdf); + ADD_TEST(test_kdf_pbkdf2); + #ifndef OPENSSL_NO_SCRYPT + ADD_TEST(test_kdf_scrypt); + #endif ++ ADD_TEST(test_kdf_krb5kdf); ++ ADD_TEST(test_kdf_ss_hash); + return 1; + } +diff -up openssl-1.1.1c/test/recipes/30-test_evp_data/evpkdf.txt.krb5-kdf openssl-1.1.1c/test/recipes/30-test_evp_data/evpkdf.txt +--- openssl-1.1.1c/test/recipes/30-test_evp_data/evpkdf.txt.krb5-kdf 2019-11-14 16:25:09.451914601 +0100 ++++ openssl-1.1.1c/test/recipes/30-test_evp_data/evpkdf.txt 2019-11-14 16:25:09.480914075 +0100 +@@ -5286,3 +5286,559 @@ Ctrl.hexsession_id = hexsession_id:a4ebd + Ctrl.type = type:A + Output = FF + Result = KDF_MISMATCH ++ ++Title = KRB5KDF tests (from RFC 3961 test vectors and krb5 sources) ++ ++#RFC3961 ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:dce06b1f64c857a11c3db57c51899b2cc1791008ce973b92 ++Ctrl.hexconstant = hexconstant:0000000155 ++Output = 925179d04591a79b5d3192c4a7e9c289b049c71f6ee604cd ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:5e13d31c70ef765746578531cb51c15bf11ca82c97cee9f2 ++Ctrl.hexconstant = hexconstant:00000001aa ++Output = 9e58e5a146d9942a101c469845d67a20e3c4259ed913f207 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:98e6fd8a04a4b6859b75a176540b9752bad3ecd610a252bc ++Ctrl.hexconstant = hexconstant:0000000155 ++Output = 13fef80d763e94ec6d13fd2ca1d085070249dad39808eabf ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:622aec25a2fe2cad7094680b7c64940280084c1a7cec92b5 ++Ctrl.hexconstant = hexconstant:00000001aa ++Output = f8dfbf04b097e6d9dc0702686bcb3489d91fd9a4516b703e ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:d3f8298ccb166438dcb9b93ee5a7629286a491f838f802fb ++Ctrl.hexconstant = hexconstant:6b65726265726f73 ++Output = 2370da575d2a3da864cebfdc5204d56df779a7df43d9da43 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:c1081649ada74362e6a1459d01dfd30d67c2234c940704da ++Ctrl.hexconstant = hexconstant:0000000155 ++Output = 348057ec98fdc48016161c2a4c7a943e92ae492c989175f7 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:5d154af238f46713155719d55e2f1f790dd661f279a7917c ++Ctrl.hexconstant = hexconstant:00000001aa ++Output = a8808ac267dada3dcbe9a7c84626fbc761c294b01315e5c1 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:798562e049852f57dc8c343ba17f2ca1d97394efc8adc443 ++Ctrl.hexconstant = hexconstant:0000000155 ++Output = c813f88a3be3b334f75425ce9175fbe3c8493b89c8703b49 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:26dce334b545292f2feab9a8701a89a4b99eb9942cecd016 ++Ctrl.hexconstant = hexconstant:00000001aa ++Output = f48ffd6e83f83e7354e694fd252cf83bfe58f7d5ba37ec5d ++ ++#Krb5 sources ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E ++Ctrl.hexconstant = hexconstant:0000000299 ++Output = F78C496D16E6C2DAE0E0B6C24057A84C0426AEEF26FD6DCE ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E ++Ctrl.hexconstant = hexconstant:00000002AA ++Output = 5B5723D0B634CB684C3EBA5264E9A70D52E683231AD3C4CE ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E ++Ctrl.hexconstant = hexconstant:0000000255 ++Output = A77C94980E9B7345A81525C423A737CE67F4CD91B6B3DA45 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-128-CBC ++Ctrl.hexkey = hexkey:42263C6E89F4FC28B8DF68EE09799F15 ++Ctrl.hexconstant = hexconstant:0000000299 ++Output = 34280A382BC92769B2DA2F9EF066854B ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-128-CBC ++Ctrl.hexkey = hexkey:42263C6E89F4FC28B8DF68EE09799F15 ++Ctrl.hexconstant = hexconstant:00000002AA ++Output = 5B14FC4E250E14DDF9DCCF1AF6674F53 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-128-CBC ++Ctrl.hexkey = hexkey:42263C6E89F4FC28B8DF68EE09799F15 ++Ctrl.hexconstant = hexconstant:0000000255 ++Output = 4ED31063621684F09AE8D89991AF3E8F ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-256-CBC ++Ctrl.hexkey = hexkey:FE697B52BC0D3CE14432BA036A92E65BBB52280990A2FA27883998D72AF30161 ++Ctrl.hexconstant = hexconstant:0000000299 ++Output = BFAB388BDCB238E9F9C98D6A878304F04D30C82556375AC507A7A852790F4674 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-256-CBC ++Ctrl.hexkey = hexkey:FE697B52BC0D3CE14432BA036A92E65BBB52280990A2FA27883998D72AF30161 ++Ctrl.hexconstant = hexconstant:00000002AA ++Output = C7CFD9CD75FE793A586A542D87E0D1396F1134A104BB1A9190B8C90ADA3DDF37 ++ ++KDF = KRB5KDF ++Ctrl.cipher = cipher:AES-256-CBC ++Ctrl.hexkey = hexkey:FE697B52BC0D3CE14432BA036A92E65BBB52280990A2FA27883998D72AF30161 ++Ctrl.hexconstant = hexconstant:0000000255 ++Output = 97151B4C76945063E2EB0529DC067D97D7BBA90776D8126D91F34F3101AEA8BA ++ ++#Same as the first but with no "fixup" ++KDF = KRB5KDF ++Ctrl.cipher = cipher:DES-EDE3-CBC ++Ctrl.hexkey = hexkey:dce06b1f64c857a11c3db57c51899b2cc1791008ce973b92 ++Ctrl.hexconstant = hexconstant:0000000155 ++Output = 935079d14490a75c3093c4a6e8c3b049c71e6ee705 ++ ++#There are currently no official test vectors for Single Step KDF ++#https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors ++Title = Single Step KDF tests ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:d09a6b1a472f930db4f5e6b967900744 ++Ctrl.hexinfo = hexinfo:b117255ab5f1b6b96fc434b0 ++Output = b5a3c52e97ae6e8c5069954354eab3c7 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:343666c0dd34b756e70f759f14c304f5 ++Ctrl.hexinfo = hexinfo:722b28448d7eab85491bce09 ++Output = 1003b650ddd3f0891a15166db5ec881d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:b84acf03ab08652dd7f82fa956933261 ++Ctrl.hexinfo = hexinfo:3d8773ec068c86053a918565 ++Output = 1635dcd1ce698f736831b4badb68ab2b ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:8cc24ca3f1d1a8b34783780b79890430 ++Ctrl.hexinfo = hexinfo:f08d4f2d9a8e6d7105c0bc16 ++Output = b8e716fb84a420aed4812cd76d9700ee ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:b616905a6f7562cd2689142ce21e42a3 ++Ctrl.hexinfo = hexinfo:ead310159a909da87e7b4b40 ++Output = 1b9201358c50fe5d5d42907c4a9fce78 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:3f57fd3fd56199b3eb33890f7ee28180 ++Ctrl.hexinfo = hexinfo:7a5056ba4fdb034c7cb6c4fe ++Output = e51ebd30a8c4b8449b0fb29d9adc11af ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:fb9fb108d104e9f662d6593fc84cde69 ++Ctrl.hexinfo = hexinfo:5faf29211c1bdbf1b2696a7c ++Output = 7a3a7e670656e48c390cdd7c51e167e0 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:237a39981794f4516dccffc3dda28396 ++Ctrl.hexinfo = hexinfo:62ed9528d104c241e0f66275 ++Output = 0c26fc9e90e1c5c5f943428301682045 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:b9b6c45f7279218fa09894e06366a3a1 ++Ctrl.hexinfo = hexinfo:0f384339670aaed4b89ecb7e ++Output = ee5fad414e32fad5d52a2bf61a7f6c72 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:08b7140e2cd0a4abd79171e4d5a71cad ++Ctrl.hexinfo = hexinfo:099211f0d8a2e02dbb5958c0 ++Output = 6162f5142e057efafd2c4f2bad5985a1 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a2 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f4853 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759a ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac704 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbe ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf1050 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f3 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8b ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f22 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f227688 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abf ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d480d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:ebe28edbae5a410b87a479243db3f690 ++Ctrl.hexinfo = hexinfo:e60dd8b28228ce5b9be74d3b ++Output = b4a23963e07f485382cb358a493daec1759ac7043dbeac37152c6ddf105031f0f239f270b7f30616166f10e5d2b4cb11ba8bf4ba3f2276885abfbc3e811a568d480d9192 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:d7e6 ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 31e798e9931b612a3ad1b9b1008faa8c ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:4646779d ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 139f68bcca879b490e268e569087d04d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:d9811c81d4c6 ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 914dc4f09cb633a76e6c389e04c64485 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:8838f9d99ec46f09 ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 4f07dfb6f7a5bf348689e08b2e29c948 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:3e0939b33f34e779f30e ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = b42c7a98c23be19d1187ff960e87557f ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:f36230cacca4d245d303058c ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 50f2068d8010d355d56c5e34aaffbc67 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:7005d32c3d4284c73c3aefc70438 ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 66fd712ccf5462bbd41e89041ea7ea26 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:c01c83150b7734f8dbd6efd6f54d7365 ++Ctrl.hexinfo = hexinfo:0bbe1fa8722023d7c3da4fff ++Output = 5c5edb0ceda9cd0c7f1f3d9e239c67d5 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:9949 ++Output = 33c83f54ed00fb1bccd2113e88550941 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:17144da6 ++Output = a999c28961424cab35ec06015e8c376a ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:dffdee1062eb ++Output = 4101ad50e626ed6f957bff926dfbb7db ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:9f365043e23b4648 ++Output = 4d3e4b971b88771f229df9f564984832 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:a885a0c4567ddc4f96da ++Output = bebbc30f5a83df5e9c9b57db33c0c879 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:c9d86183295bfe4c3d85f0fd ++Output = 87c947e45407db63eb94cbaa02d14e94 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:825fadce46964236a486732c5dad ++Output = 192370a85ff78e3c0245129d9b398558 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:da69f1dbbebc837480af692e7e9ee6b9 ++Ctrl.hexinfo = hexinfo:5c0b5eb3ac9f342347d73d7a521723aa ++Output = c7b7634fd809383e87c4b1b3e728be56 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:8d7a4e7d5cf34b3f74873b862aeb33b7 ++Output = 6a5594f402f74f69 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:9b208e7ee1e641fac1dff48fc1beb2d2 ++Output = 556ed67e24ac0c7c46cc432da8bdb23c ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:4d2572539fed433211da28c8a0eebac3 ++Output = 5a4054c59c5b92814025578f43c1b79fe84968fc284e240b ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:4e1e70c9886819a31bc29a537911add9 ++Output = ddbfc440449aab4131c6d8aec08ce1496f2702241d0e27cc155c5c7c3cda75b5 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:68f144c952528e540c686dc353b766f2 ++Output = 59ed66bb6f54a9688a0b891d0b2ea6743621d9e1b5cc098cf3a55e6f864f9af8a95e4d945d2f987f ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:b66c9d507c9f837fbe60b6675fdbf38b ++Output = c282787ddf421a72fc88811be81b08d0d6ab66c92d1011974aa58335a6bbbd62e9e982bfae5929865ea1d517247089d2 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:34e730b49e46c7ed2fb25975a4cccd2d ++Output = 39e76e6571cb00740260b9070accbdcc4a492c295cbef33d9e37dac21e5e9d07e0f12dc7063d2172641475d4e08b8e3712fb26a10c8376b8 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:e340d87e2d7adbc1b95ec2dbdc3b82be ++Output = a660c0037a53f76f1e7667043f5869348ad07ac0e272e615ce31f16d4ab90d4b35fe5c370c0010ce79aff45682c6fb8b97f9a05b7d40b5af3c62999a10df9c6d ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA256 ++Ctrl.hexsecret = hexsecret:afc4e154498d4770aa8365f6903dc83b ++Ctrl.hexinfo = hexinfo:662af20379b29d5ef813e655 ++Output = f0b80d6ae4c1e19e2105a37024e35dc6 ++ ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA512 ++Ctrl.hexsecret = hexsecret:108cf63318555c787fa578731dd4f037 ++Ctrl.hexinfo = hexinfo:53191b1dd3f94d83084d61d6 ++Output = 0ad475c1826da3007637970c8b92b993 ++ ++Title = SSKDF Test vectors from RFC 8636 Section 8 (With precoumputed ASN.1 info) ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA1 ++Ctrl.hexsecret = hexsecret:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ++Ctrl.hexinfo = hexinfo:307e300a06082b06010502030601a01f041d301ba0071b0553552e5345a110300ea003020101a10730051b036c6861a12904273025a0071b0553552e5345a11a3018a003020101a111300f1b066b72627467741b0553552e5345a22404223020a003020112a10c040aaaaaaaaaaaaaaaaaaaaaa20b0409bbbbbbbbbbbbbbbbbb ++Output = e6ab38c9413e035bb079201ed0b6b73d8d49a814a737c04ee6649614206f73ad ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA256 ++Ctrl.hexsecret = hexsecret:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ++Ctrl.hexinfo = hexinfo:307e300a06082b06010502030602a01f041d301ba0071b0553552e5345a110300ea003020101a10730051b036c6861a12904273025a0071b0553552e5345a11a3018a003020101a111300f1b066b72627467741b0553552e5345a22404223020a003020112a10c040aaaaaaaaaaaaaaaaaaaaaa20b0409bbbbbbbbbbbbbbbbbb ++Output = 77ef4e48c420ae3fec75109d7981697eed5d295c90c62564f7bfd101fa9bc1d5 ++ ++KDF = SSKDF ++Ctrl.digest = digest:SHA512 ++Ctrl.hexsecret = hexsecret:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ++Ctrl.hexinfo = hexinfo:307e300a06082b06010502030603a01f041d301ba0071b0553552e5345a110300ea003020101a10730051b036c6861a12904273025a0071b0553552e5345a11a3018a003020101a111300f1b066b72627467741b0553552e5345a22404223020a003020110a10c040aaaaaaaaaaaaaaaaaaaaaa20b0409bbbbbbbbbbbbbbbbbb ++Output = d3c78b78d75313e9a926f75dfb012363fa17fa01db diff --git a/SOURCES/openssl-1.1.1-s390x-ecc.patch b/SOURCES/openssl-1.1.1-s390x-ecc.patch new file mode 100644 index 0000000..30d6866 --- /dev/null +++ b/SOURCES/openssl-1.1.1-s390x-ecc.patch @@ -0,0 +1,2327 @@ +diff -up openssl-1.1.1c/Configurations/00-base-templates.conf.s390x-ecc openssl-1.1.1c/Configurations/00-base-templates.conf +--- openssl-1.1.1c/Configurations/00-base-templates.conf.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/Configurations/00-base-templates.conf 2019-11-20 11:36:02.190860451 +0100 +@@ -289,6 +289,7 @@ my %targets=( + template => 1, + cpuid_asm_src => "s390xcap.c s390xcpuid.S", + bn_asm_src => "asm/s390x.S s390x-mont.S s390x-gf2m.s", ++ ec_asm_src => "ecp_s390x_nistp.c", + aes_asm_src => "aes-s390x.S aes-ctr.fake aes-xts.fake", + sha1_asm_src => "sha1-s390x.S sha256-s390x.S sha512-s390x.S", + rc4_asm_src => "rc4-s390x.s", +diff -up openssl-1.1.1c/Configure.s390x-ecc openssl-1.1.1c/Configure +--- openssl-1.1.1c/Configure.s390x-ecc 2019-11-20 11:36:02.078862415 +0100 ++++ openssl-1.1.1c/Configure 2019-11-20 11:36:02.191860433 +0100 +@@ -1410,6 +1410,9 @@ unless ($disabled{asm}) { + if ($target{ec_asm_src} =~ /ecp_nistz256/) { + push @{$config{lib_defines}}, "ECP_NISTZ256_ASM"; + } ++ if ($target{ec_asm_src} =~ /ecp_s390x_nistp/) { ++ push @{$config{lib_defines}}, "S390X_EC_ASM"; ++ } + if ($target{ec_asm_src} =~ /x25519/) { + push @{$config{lib_defines}}, "X25519_ASM"; + } +diff -up openssl-1.1.1c/crypto/bn/asm/s390x.S.s390x-ecc openssl-1.1.1c/crypto/bn/asm/s390x.S +--- openssl-1.1.1c/crypto/bn/asm/s390x.S.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/bn/asm/s390x.S 2019-11-20 11:36:02.191860433 +0100 +@@ -511,7 +511,7 @@ bn_mul_comba4: + lghi zero,0 + + mul_add_c(0,0,c1,c2,c3); +- stg c1,0*8(%r3) ++ stg c1,0*8(%r2) + lghi c1,0 + + mul_add_c(0,1,c2,c3,c1); +diff -up openssl-1.1.1c/crypto/cmac/cm_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/cmac/cm_pmeth.c +--- openssl-1.1.1c/crypto/cmac/cm_pmeth.c.s390x-ecc 2019-11-20 11:36:02.078862415 +0100 ++++ openssl-1.1.1c/crypto/cmac/cm_pmeth.c 2019-11-20 11:36:02.191860433 +0100 +@@ -159,3 +159,8 @@ const EVP_PKEY_METHOD cmac_pkey_meth = { + pkey_cmac_ctrl, + pkey_cmac_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *cmac_pkey_method(void) ++{ ++ return &cmac_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/dh/dh_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/dh/dh_pmeth.c +--- openssl-1.1.1c/crypto/dh/dh_pmeth.c.s390x-ecc 2019-11-20 11:36:02.079862397 +0100 ++++ openssl-1.1.1c/crypto/dh/dh_pmeth.c 2019-11-20 11:36:02.191860433 +0100 +@@ -512,6 +512,11 @@ const EVP_PKEY_METHOD dh_pkey_meth = { + pkey_dh_ctrl_str + }; + ++const EVP_PKEY_METHOD *dh_pkey_method(void) ++{ ++ return &dh_pkey_meth; ++} ++ + const EVP_PKEY_METHOD dhx_pkey_meth = { + EVP_PKEY_DHX, + EVP_PKEY_FLAG_FIPS, +@@ -545,3 +550,8 @@ const EVP_PKEY_METHOD dhx_pkey_meth = { + pkey_dh_ctrl, + pkey_dh_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *dhx_pkey_method(void) ++{ ++ return &dhx_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/dsa/dsa_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/dsa/dsa_pmeth.c +--- openssl-1.1.1c/crypto/dsa/dsa_pmeth.c.s390x-ecc 2019-11-20 11:36:02.100862029 +0100 ++++ openssl-1.1.1c/crypto/dsa/dsa_pmeth.c 2019-11-20 11:36:02.191860433 +0100 +@@ -275,3 +275,8 @@ const EVP_PKEY_METHOD dsa_pkey_meth = { + pkey_dsa_ctrl, + pkey_dsa_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *dsa_pkey_method(void) ++{ ++ return &dsa_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/ec/build.info.s390x-ecc openssl-1.1.1c/crypto/ec/build.info +--- openssl-1.1.1c/crypto/ec/build.info.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/build.info 2019-11-20 11:36:02.192860416 +0100 +@@ -26,6 +26,9 @@ GENERATE[ecp_nistz256-armv8.S]=asm/ecp_n + INCLUDE[ecp_nistz256-armv8.o]=.. + GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl $(PERLASM_SCHEME) + ++INCLUDE[ecp_s390x_nistp.o]=.. ++INCLUDE[ecx_meth.o]=.. ++ + GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl $(PERLASM_SCHEME) + GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl $(PERLASM_SCHEME) + +diff -up openssl-1.1.1c/crypto/ec/ec_curve.c.s390x-ecc openssl-1.1.1c/crypto/ec/ec_curve.c +--- openssl-1.1.1c/crypto/ec/ec_curve.c.s390x-ecc 2019-11-20 11:36:02.043863029 +0100 ++++ openssl-1.1.1c/crypto/ec/ec_curve.c 2019-11-20 11:36:02.192860416 +0100 +@@ -255,20 +255,29 @@ static const ec_list_element curve_list[ + {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_prime256v1, &_EC_X9_62_PRIME_256V1.h, + #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 + 0, +diff -up openssl-1.1.1c/crypto/ec/ecdsa_ossl.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecdsa_ossl.c +--- openssl-1.1.1c/crypto/ec/ecdsa_ossl.c.s390x-ecc 2019-11-20 11:36:02.100862029 +0100 ++++ openssl-1.1.1c/crypto/ec/ecdsa_ossl.c 2019-11-20 11:36:02.192860416 +0100 +@@ -18,6 +18,41 @@ + # include + #endif + ++int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, ++ BIGNUM **rp) ++{ ++ if (eckey->group->meth->ecdsa_sign_setup == NULL) { ++ ECerr(EC_F_OSSL_ECDSA_SIGN_SETUP, 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) { ++ ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, 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) { ++ ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, 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) +@@ -145,15 +180,15 @@ static int ecdsa_sign_setup(EC_KEY *ecke + return ret; + } + +-int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, +- BIGNUM **rp) ++int 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 *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; + BIGNUM *kinv = NULL, *s, *m = NULL; +@@ -210,25 +245,25 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const uns + 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_MALLOC_FAILURE); + goto err; + } + } +@@ -242,11 +277,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const uns + */ + 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + /* +@@ -255,7 +290,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const uns + */ + 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB); + goto err; + } + +@@ -265,7 +300,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const uns + * 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); ++ ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES); + goto err; + } + } else { +@@ -317,8 +352,8 @@ int ossl_ecdsa_verify(int type, const un + return ret; + } + +-int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, +- const ECDSA_SIG *sig, EC_KEY *eckey) ++int 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; +@@ -338,18 +373,18 @@ int ossl_ecdsa_verify_sig(const unsigned + /* 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); + return -1; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { +- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_MALLOC_FAILURE); + return -1; + } + BN_CTX_start(ctx); +@@ -358,26 +393,26 @@ int ossl_ecdsa_verify_sig(const unsigned + m = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + if (X == NULL) { +- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* digest -> m */ +@@ -388,41 +423,41 @@ int ossl_ecdsa_verify_sig(const unsigned + 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + + if ((point = EC_POINT_new(group)) == NULL) { +- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, 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); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_EC_LIB); + goto err; + } + + if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) { +- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_EC_LIB); + goto err; + } + + if (!BN_nnmod(u1, X, order, ctx)) { +- ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB); ++ ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB); + goto err; + } + /* if the signature is correct u1 is equal to sig->r */ +diff -up openssl-1.1.1c/crypto/ec/ec_err.c.s390x-ecc openssl-1.1.1c/crypto/ec/ec_err.c +--- openssl-1.1.1c/crypto/ec/ec_err.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ec_err.c 2019-11-20 11:36:02.192860416 +0100 +@@ -31,6 +31,11 @@ static const ERR_STRING_DATA EC_str_func + {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_ECDSA_SIMPLE_SIGN_SETUP, 0), "ecdsa_simple_sign_setup"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIMPLE_SIGN_SIG, 0), "ecdsa_simple_sign_sig"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_SIMPLE_VERIFY_SIG, 0), "ecdsa_simple_verify_sig"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_S390X_NISTP_SIGN_SIG, 0), "ecdsa_s390x_nistp_sign_sig"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, 0), "ecdsa_s390x_nistp_verify_sig"}, + {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"}, +@@ -266,6 +271,7 @@ static const ERR_STRING_DATA EC_str_func + {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_SETUP, 0), "ossl_ecdsa_sign_setup"}, + {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"}, +@@ -284,6 +290,12 @@ static const ERR_STRING_DATA EC_str_func + {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_S390X_PKEY_ECD_DIGESTSIGN25519, 0), "s390x_pkey_ecd_digestsign25519"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_S390X_PKEY_ECD_DIGESTSIGN448, 0), "s390x_pkey_ecd_digestsign448"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_S390X_PKEY_ECD_KEYGEN25519, 0), "s390x_pkey_ecd_keygen25519"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_S390X_PKEY_ECD_KEYGEN448, 0), "s390x_pkey_ecd_keygen448"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_S390X_PKEY_ECX_KEYGEN25519, 0), "s390x_pkey_ecx_keygen25519"}, ++ {ERR_PACK(ERR_LIB_EC, EC_F_S390X_PKEY_ECX_KEYGEN448, 0), "s390x_pkey_ecx_keygen448"}, + {ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"}, + {0, NULL} + }; +@@ -298,6 +310,8 @@ static const ERR_STRING_DATA EC_str_reas + "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), +diff -up openssl-1.1.1c/crypto/ec/ec_lcl.h.s390x-ecc openssl-1.1.1c/crypto/ec/ec_lcl.h +--- openssl-1.1.1c/crypto/ec/ec_lcl.h.s390x-ecc 2019-11-20 11:36:01.676869466 +0100 ++++ openssl-1.1.1c/crypto/ec/ec_lcl.h 2019-11-20 11:36:02.192860416 +0100 +@@ -154,7 +154,7 @@ struct ec_method_st { + int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + /*- +- * 'field_inv' computes the multipicative inverse of a in the field, ++ * 'field_inv' computes the multiplicative inverse of a in the field, + * storing the result in r. + * + * If 'a' is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. +@@ -179,6 +179,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 *); +@@ -587,6 +595,11 @@ int ec_group_simple_order_bits(const EC_ + */ + 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); +@@ -649,6 +662,13 @@ int ossl_ecdsa_verify(int type, const un + 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 ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, ++ BIGNUM **rp); ++ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, ++ const BIGNUM *in_kinv, const BIGNUM *in_r, ++ EC_KEY *eckey); ++int 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]); +diff -up openssl-1.1.1c/crypto/ec/ec_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/ec/ec_pmeth.c +--- openssl-1.1.1c/crypto/ec/ec_pmeth.c.s390x-ecc 2019-11-20 11:36:02.101862012 +0100 ++++ openssl-1.1.1c/crypto/ec/ec_pmeth.c 2019-11-20 11:36:02.193860398 +0100 +@@ -474,3 +474,8 @@ const EVP_PKEY_METHOD ec_pkey_meth = { + pkey_ec_ctrl, + pkey_ec_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *ec_pkey_method(void) ++{ ++ return &ec_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/ec/ecp_mont.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_mont.c +--- openssl-1.1.1c/crypto/ec/ecp_mont.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_mont.c 2019-11-20 11:36:02.193860398 +0100 +@@ -63,6 +63,9 @@ const EC_METHOD *EC_GFp_mont_method(void + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, +diff -up openssl-1.1.1c/crypto/ec/ecp_nist.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_nist.c +--- openssl-1.1.1c/crypto/ec/ecp_nist.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_nist.c 2019-11-20 11:36:02.193860398 +0100 +@@ -65,6 +65,9 @@ const EC_METHOD *EC_GFp_nist_method(void + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, +diff -up openssl-1.1.1c/crypto/ec/ecp_nistp224.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_nistp224.c +--- openssl-1.1.1c/crypto/ec/ecp_nistp224.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_nistp224.c 2019-11-20 11:36:02.193860398 +0100 +@@ -292,6 +292,9 @@ const EC_METHOD *EC_GFp_nistp224_method( + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ +diff -up openssl-1.1.1c/crypto/ec/ecp_nistp256.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_nistp256.c +--- openssl-1.1.1c/crypto/ec/ecp_nistp256.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_nistp256.c 2019-11-20 11:36:02.194860380 +0100 +@@ -1823,6 +1823,9 @@ const EC_METHOD *EC_GFp_nistp256_method( + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ +diff -up openssl-1.1.1c/crypto/ec/ecp_nistp521.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_nistp521.c +--- openssl-1.1.1c/crypto/ec/ecp_nistp521.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_nistp521.c 2019-11-20 11:36:02.194860380 +0100 +@@ -1665,6 +1665,9 @@ const EC_METHOD *EC_GFp_nistp521_method( + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ +diff -up openssl-1.1.1c/crypto/ec/ecp_nistz256.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_nistz256.c +--- openssl-1.1.1c/crypto/ec/ecp_nistz256.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecp_nistz256.c 2019-11-20 11:36:02.195860363 +0100 +@@ -1689,6 +1689,9 @@ const EC_METHOD *EC_GFp_nistz256_method( + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ +diff -up openssl-1.1.1c/crypto/ec/ecp_s390x_nistp.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_s390x_nistp.c +--- openssl-1.1.1c/crypto/ec/ecp_s390x_nistp.c.s390x-ecc 2019-11-20 11:36:02.195860363 +0100 ++++ openssl-1.1.1c/crypto/ec/ecp_s390x_nistp.c 2019-11-20 11:36:02.195860363 +0100 +@@ -0,0 +1,394 @@ ++/* ++ * Copyright 2019 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 ++#include ++#include ++#include ++#include "ec_lcl.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(); ++ 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 = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); ++ OPENSSL_cleanse(param + S390X_OFF_SCALAR(len), len); ++ 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, EC_R_MISSING_PARAMETERS); ++ return NULL; ++ } ++ ++ if (!EC_KEY_can_sign(eckey)) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ++ EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); ++ return NULL; ++ } ++ ++ k = BN_secure_new(); ++ sig = ECDSA_SIG_new(); ++ if (k == NULL || sig == NULL) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_MALLOC_FAILURE); ++ goto ret; ++ } ++ ++ sig->r = BN_new(); ++ sig->s = BN_new(); ++ if (sig->r == NULL || sig->s == NULL) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB); ++ goto ret; ++ } ++ ++ if (r == NULL || kinv == NULL) { ++ /* ++ * Generate random k and copy to param param block. RAND_priv_bytes ++ * 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(param + S390X_OFF_RN(len), len) != 1) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ++ EC_R_RANDOM_NUMBER_GENERATION_FAILED); ++ goto ret; ++ } ++ } else { ++ /* Reconstruct k = (k^-1)^-1. */ ++ if (ec_group_do_inverse_ord(group, k, kinv, NULL) == 0 ++ || BN_bn2binpad(k, param + S390X_OFF_RN(len), len) == -1) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB); ++ goto ret; ++ } ++ /* Turns KDSA internal nonce-generation off. */ ++ fc |= S390X_KDSA_D; ++ } ++ ++ if (s390x_kdsa(fc, param, NULL, 0) != 0) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB); ++ goto ret; ++ } ++ ++ ok = 1; ++ret: ++ OPENSSL_cleanse(param + S390X_OFF_K(len), 2 * len); ++ 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, EC_R_MISSING_PARAMETERS); ++ return -1; ++ } ++ ++ if (!EC_KEY_can_sign(eckey)) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, ++ EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); ++ return -1; ++ } ++ ++ ctx = BN_CTX_new(); ++ if (ctx == NULL) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, 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) { ++ ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, 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, \ ++ 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, \ ++ NULL, /* point_set_compressed_coordinates */ \ ++ NULL, /* point2oct */ \ ++ NULL, /* 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_s390x_nistp##bits##_mul, \ ++ NULL, /* precompute_mult */ \ ++ NULL, /* have_precompute_mult */ \ ++ ec_GFp_simple_field_mul, \ ++ ec_GFp_simple_field_sqr, \ ++ NULL, /* field_div */ \ ++ ec_GFp_simple_field_inv, \ ++ NULL, /* field_encode */ \ ++ NULL, /* field_decode */ \ ++ NULL, /* field_set_to_one */ \ ++ ec_key_simple_priv2oct, \ ++ ec_key_simple_oct2priv, \ ++ NULL, /* set_private */ \ ++ ec_key_simple_generate_key, \ ++ ec_key_simple_check_key, \ ++ ec_key_simple_generate_public_key, \ ++ NULL, /* keycopy */ \ ++ NULL, /* keyfinish */ \ ++ ecdh_simple_compute_key, \ ++ ecdsa_simple_sign_setup, \ ++ ecdsa_s390x_nistp##bits##_sign_sig, \ ++ ecdsa_s390x_nistp##bits##_verify_sig, \ ++ NULL, /* field_inverse_mod_ord */ \ ++ ec_GFp_simple_blind_coordinates, \ ++ ec_GFp_simple_ladder_pre, \ ++ ec_GFp_simple_ladder_step, \ ++ 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 -up openssl-1.1.1c/crypto/ec/ecp_smpl.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecp_smpl.c +--- openssl-1.1.1c/crypto/ec/ecp_smpl.c.s390x-ecc 2019-11-20 11:36:02.066862626 +0100 ++++ openssl-1.1.1c/crypto/ec/ecp_smpl.c 2019-11-20 11:36:02.195860363 +0100 +@@ -64,6 +64,9 @@ const EC_METHOD *EC_GFp_simple_method(vo + 0, /* keycopy */ + 0, /* keyfinish */ + ecdh_simple_compute_key, ++ ecdsa_simple_sign_setup, ++ ecdsa_simple_sign_sig, ++ ecdsa_simple_verify_sig, + 0, /* field_inverse_mod_ord */ + ec_GFp_simple_blind_coordinates, + ec_GFp_simple_ladder_pre, +diff -up openssl-1.1.1c/crypto/ec/ecx_meth.c.s390x-ecc openssl-1.1.1c/crypto/ec/ecx_meth.c +--- openssl-1.1.1c/crypto/ec/ecx_meth.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/ec/ecx_meth.c 2019-11-20 11:36:02.196860345 +0100 +@@ -20,6 +20,7 @@ + #define X25519_BITS 253 + #define X25519_SECURITY_BITS 128 + ++#define ED25519_KEYLEN 32 + #define ED25519_SIGSIZE 64 + + #define X448_BITS 448 +@@ -839,3 +840,666 @@ const EVP_PKEY_METHOD ed448_pkey_meth = + pkey_ecd_digestsign448, + pkey_ecd_digestverify448 + }; ++ ++#ifdef S390X_EC_ASM ++# include "s390x_arch.h" ++# include "internal/constant_time_locl.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)); ++} ++ ++static 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; ++} ++ ++static 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; ++} ++ ++static 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; ++} ++ ++static 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; ++} ++ ++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; ++ unsigned char *privkey = NULL, *pubkey; ++ ++ key = OPENSSL_zalloc(sizeof(*key)); ++ if (key == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ pubkey = key->pubkey; ++ ++ privkey = key->privkey = OPENSSL_secure_malloc(X25519_KEYLEN); ++ if (privkey == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (RAND_priv_bytes(privkey, X25519_KEYLEN) <= 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: ++ OPENSSL_secure_clear_free(privkey, X25519_KEYLEN); ++ key->privkey = NULL; ++ OPENSSL_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; ++ unsigned char *privkey = NULL, *pubkey; ++ ++ key = OPENSSL_zalloc(sizeof(*key)); ++ if (key == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ pubkey = key->pubkey; ++ ++ privkey = key->privkey = OPENSSL_secure_malloc(X448_KEYLEN); ++ if (privkey == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (RAND_priv_bytes(privkey, X448_KEYLEN) <= 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: ++ OPENSSL_secure_clear_free(privkey, X448_KEYLEN); ++ key->privkey = NULL; ++ OPENSSL_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; ++ unsigned char *privkey = NULL, *pubkey; ++ ++ key = OPENSSL_zalloc(sizeof(*key)); ++ if (key == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ pubkey = key->pubkey; ++ ++ privkey = key->privkey = OPENSSL_secure_malloc(ED25519_KEYLEN); ++ if (privkey == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (RAND_priv_bytes(privkey, ED25519_KEYLEN) <= 0) ++ goto err; ++ ++ SHA512(privkey, 32, buff); ++ 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: ++ OPENSSL_secure_clear_free(privkey, ED25519_KEYLEN); ++ key->privkey = NULL; ++ OPENSSL_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; ++ unsigned char *privkey = NULL, *pubkey; ++ EVP_MD_CTX *hashctx = NULL; ++ ++ key = OPENSSL_zalloc(sizeof(*key)); ++ if (key == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ pubkey = key->pubkey; ++ ++ privkey = key->privkey = OPENSSL_secure_malloc(ED448_KEYLEN); ++ if (privkey == NULL) { ++ ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ if (RAND_priv_bytes(privkey, ED448_KEYLEN) <= 0) ++ goto err; ++ ++ hashctx = EVP_MD_CTX_new(); ++ if (hashctx == NULL) ++ goto err; ++ if (EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) != 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: ++ OPENSSL_secure_clear_free(privkey, ED448_KEYLEN); ++ key->privkey = NULL; ++ OPENSSL_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)) ++ return 0; ++ ++ if (key != NULL) ++ return s390x_x25519_mul(key, pubkey, privkey); ++ ++ *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)) ++ return 0; ++ ++ if (key != NULL) ++ return s390x_x448_mul(key, pubkey, privkey); ++ ++ *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_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; ++ int rc; ++ ++ if (sig == NULL) { ++ *siglen = ED25519_SIGSIZE; ++ return 1; ++ } ++ ++ if (*siglen < ED25519_SIGSIZE) { ++ ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN25519, 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_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; ++ int rc; ++ ++ if (sig == NULL) { ++ *siglen = ED448_SIGSIZE; ++ return 1; ++ } ++ ++ if (*siglen < ED448_SIGSIZE) { ++ ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN448, 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_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; ++ ++ 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_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx; ++ ++ 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 *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 *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 *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 *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 -up openssl-1.1.1c/crypto/err/openssl.txt.s390x-ecc openssl-1.1.1c/crypto/err/openssl.txt +--- openssl-1.1.1c/crypto/err/openssl.txt.s390x-ecc 2019-11-20 11:36:02.158861012 +0100 ++++ openssl-1.1.1c/crypto/err/openssl.txt 2019-11-20 11:36:02.196860345 +0100 +@@ -495,6 +495,11 @@ EC_F_ECDSA_SIGN_EX:254:ECDSA_sign_ex + EC_F_ECDSA_SIGN_SETUP:248:ECDSA_sign_setup + EC_F_ECDSA_SIG_NEW:265:ECDSA_SIG_new + EC_F_ECDSA_VERIFY:253:ECDSA_verify ++EC_F_ECDSA_SIMPLE_SIGN_SETUP:310:ecdsa_simple_sign_setup ++EC_F_ECDSA_SIMPLE_SIGN_SIG:311:ecdsa_simple_sign_sig ++EC_F_ECDSA_SIMPLE_VERIFY_SIG:312:ecdsa_simple_verify_sig ++EC_F_ECDSA_S390X_NISTP_SIGN_SIG:313:ecdsa_s390x_nistp_sign_sig ++EC_F_ECDSA_S390X_NISTP_VERIFY_SIG:314:ecdsa_s390x_nistp_verify_sig + EC_F_ECD_ITEM_VERIFY:270:ecd_item_verify + EC_F_ECKEY_PARAM2TYPE:223:eckey_param2type + EC_F_ECKEY_PARAM_DECODE:212:eckey_param_decode +@@ -656,6 +661,7 @@ EC_F_NISTP521_PRE_COMP_NEW:237:nistp521_ + EC_F_O2I_ECPUBLICKEY:152:o2i_ECPublicKey + EC_F_OLD_EC_PRIV_DECODE:222:old_ec_priv_decode + EC_F_OSSL_ECDH_COMPUTE_KEY:247:ossl_ecdh_compute_key ++EC_F_OSSL_ECDSA_SIGN_SETUP:300:ossl_ecdsa_sign_setup + EC_F_OSSL_ECDSA_SIGN_SIG:249:ossl_ecdsa_sign_sig + EC_F_OSSL_ECDSA_VERIFY_SIG:250:ossl_ecdsa_verify_sig + EC_F_PKEY_ECD_CTRL:271:pkey_ecd_ctrl +@@ -671,6 +677,12 @@ EC_F_PKEY_EC_KDF_DERIVE:283:pkey_ec_kdf_ + EC_F_PKEY_EC_KEYGEN:199:pkey_ec_keygen + EC_F_PKEY_EC_PARAMGEN:219:pkey_ec_paramgen + EC_F_PKEY_EC_SIGN:218:pkey_ec_sign ++EC_F_S390X_PKEY_ECD_DIGESTSIGN25519:303:s390x_pkey_ecd_digestsign25519 ++EC_F_S390X_PKEY_ECD_DIGESTSIGN448:304:s390x_pkey_ecd_digestsign448 ++EC_F_S390X_PKEY_ECD_KEYGEN25519:305:s390x_pkey_ecd_keygen25519 ++EC_F_S390X_PKEY_ECD_KEYGEN448:306:s390x_pkey_ecd_keygen448 ++EC_F_S390X_PKEY_ECX_KEYGEN25519:307:s390x_pkey_ecx_keygen25519 ++EC_F_S390X_PKEY_ECX_KEYGEN448:308:s390x_pkey_ecx_keygen448 + EC_F_VALIDATE_ECX_DERIVE:278:validate_ecx_derive + ENGINE_F_DIGEST_UPDATE:198:digest_update + ENGINE_F_DYNAMIC_CTRL:180:dynamic_ctrl +@@ -2149,6 +2161,7 @@ EC_R_BUFFER_TOO_SMALL:100:buffer too sma + EC_R_CANNOT_INVERT:165:cannot invert + EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range + EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh ++EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA:170:curve does not support ecdsa + EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing + EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters failure + EC_R_DECODE_ERROR:142:decode error +diff -up openssl-1.1.1c/crypto/evp/pmeth_lib.c.s390x-ecc openssl-1.1.1c/crypto/evp/pmeth_lib.c +--- openssl-1.1.1c/crypto/evp/pmeth_lib.c.s390x-ecc 2019-11-20 11:36:02.105861942 +0100 ++++ openssl-1.1.1c/crypto/evp/pmeth_lib.c 2019-11-20 11:36:02.197860328 +0100 +@@ -17,60 +17,67 @@ + #include "internal/evp_int.h" + #include "internal/numbers.h" + ++typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void); + typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); + + static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; + + /* This array needs to be in order of NIDs */ +-static const EVP_PKEY_METHOD *standard_methods[] = { ++static pmeth_fn standard_methods[] = { + #ifndef OPENSSL_NO_RSA +- &rsa_pkey_meth, ++ rsa_pkey_method, + #endif + #ifndef OPENSSL_NO_DH +- &dh_pkey_meth, ++ dh_pkey_method, + #endif + #ifndef OPENSSL_NO_DSA +- &dsa_pkey_meth, ++ dsa_pkey_method, + #endif + #ifndef OPENSSL_NO_EC +- &ec_pkey_meth, ++ ec_pkey_method, + #endif +- &hmac_pkey_meth, ++ hmac_pkey_method, + #ifndef OPENSSL_NO_CMAC +- &cmac_pkey_meth, ++ cmac_pkey_method, + #endif + #ifndef OPENSSL_NO_RSA +- &rsa_pss_pkey_meth, ++ rsa_pss_pkey_method, + #endif + #ifndef OPENSSL_NO_DH +- &dhx_pkey_meth, ++ dhx_pkey_method, + #endif + #ifndef OPENSSL_NO_SCRYPT +- &scrypt_pkey_meth, ++ scrypt_pkey_method, + #endif +- &tls1_prf_pkey_meth, ++ tls1_prf_pkey_method, + #ifndef OPENSSL_NO_EC +- &ecx25519_pkey_meth, +- &ecx448_pkey_meth, ++ ecx25519_pkey_method, ++ ecx448_pkey_method, + #endif +- &hkdf_pkey_meth, ++ hkdf_pkey_method, + #ifndef OPENSSL_NO_POLY1305 +- &poly1305_pkey_meth, ++ poly1305_pkey_method, + #endif + #ifndef OPENSSL_NO_SIPHASH +- &siphash_pkey_meth, ++ siphash_pkey_method, + #endif + #ifndef OPENSSL_NO_EC +- &ed25519_pkey_meth, +- &ed448_pkey_meth, ++ ed25519_pkey_method, ++ ed448_pkey_method, + #endif + #ifndef OPENSSL_NO_SM2 +- &sm2_pkey_meth, ++ sm2_pkey_method, + #endif + }; + +-DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, +- pmeth); ++DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func); ++ ++static int pmeth_func_cmp(const EVP_PKEY_METHOD *const *a, pmeth_fn const *b) ++{ ++ return ((*a)->pkey_id - ((**b)())->pkey_id); ++} ++ ++IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, pmeth_fn, pmeth_func); + + static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, + const EVP_PKEY_METHOD *const *b) +@@ -78,13 +85,11 @@ static int pmeth_cmp(const EVP_PKEY_METH + return ((*a)->pkey_id - (*b)->pkey_id); + } + +-IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, +- pmeth); +- + const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) + { ++ pmeth_fn *ret; + EVP_PKEY_METHOD tmp; +- const EVP_PKEY_METHOD *t = &tmp, **ret; ++ const EVP_PKEY_METHOD *t = &tmp; + tmp.pkey_id = type; + if (app_pkey_methods) { + int idx; +@@ -92,12 +97,12 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_fin + if (idx >= 0) + return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); + } +- ret = OBJ_bsearch_pmeth(&t, standard_methods, +- sizeof(standard_methods) / +- sizeof(EVP_PKEY_METHOD *)); ++ ret = OBJ_bsearch_pmeth_func(&t, standard_methods, ++ sizeof(standard_methods) / ++ sizeof(pmeth_fn)); + if (!ret || !*ret) + return NULL; +- return *ret; ++ return (**ret)(); + } + + static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) +@@ -348,7 +353,7 @@ size_t EVP_PKEY_meth_get_count(void) + const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx) + { + if (idx < OSSL_NELEM(standard_methods)) +- return standard_methods[idx]; ++ return (standard_methods[idx])(); + if (app_pkey_methods == NULL) + return NULL; + idx -= OSSL_NELEM(standard_methods); +diff -up openssl-1.1.1c/crypto/hmac/hm_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/hmac/hm_pmeth.c +--- openssl-1.1.1c/crypto/hmac/hm_pmeth.c.s390x-ecc 2019-11-20 11:36:02.115861766 +0100 ++++ openssl-1.1.1c/crypto/hmac/hm_pmeth.c 2019-11-20 11:36:02.197860328 +0100 +@@ -210,3 +210,8 @@ const EVP_PKEY_METHOD hmac_pkey_meth = { + pkey_hmac_ctrl, + pkey_hmac_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *hmac_pkey_method(void) ++{ ++ return &hmac_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/include/internal/evp_int.h.s390x-ecc openssl-1.1.1c/crypto/include/internal/evp_int.h +--- openssl-1.1.1c/crypto/include/internal/evp_int.h.s390x-ecc 2019-11-20 11:36:02.158861012 +0100 ++++ openssl-1.1.1c/crypto/include/internal/evp_int.h 2019-11-20 11:36:02.197860328 +0100 +@@ -459,3 +459,22 @@ void evp_encode_ctx_set_flags(EVP_ENCODE + #define EVP_ENCODE_CTX_NO_NEWLINES 1 + /* Use the SRP base64 alphabet instead of the standard one */ + #define EVP_ENCODE_CTX_USE_SRP_ALPHABET 2 ++ ++const EVP_PKEY_METHOD *cmac_pkey_method(void); ++const EVP_PKEY_METHOD *dh_pkey_method(void); ++const EVP_PKEY_METHOD *dhx_pkey_method(void); ++const EVP_PKEY_METHOD *dsa_pkey_method(void); ++const EVP_PKEY_METHOD *ec_pkey_method(void); ++const EVP_PKEY_METHOD *sm2_pkey_method(void); ++const EVP_PKEY_METHOD *ecx25519_pkey_method(void); ++const EVP_PKEY_METHOD *ecx448_pkey_method(void); ++const EVP_PKEY_METHOD *ed25519_pkey_method(void); ++const EVP_PKEY_METHOD *ed448_pkey_method(void); ++const EVP_PKEY_METHOD *hmac_pkey_method(void); ++const EVP_PKEY_METHOD *rsa_pkey_method(void); ++const EVP_PKEY_METHOD *rsa_pss_pkey_method(void); ++const EVP_PKEY_METHOD *scrypt_pkey_method(void); ++const EVP_PKEY_METHOD *tls1_prf_pkey_method(void); ++const EVP_PKEY_METHOD *hkdf_pkey_method(void); ++const EVP_PKEY_METHOD *poly1305_pkey_method(void); ++const EVP_PKEY_METHOD *siphash_pkey_method(void); +diff -up openssl-1.1.1c/crypto/kdf/hkdf.c.s390x-ecc openssl-1.1.1c/crypto/kdf/hkdf.c +--- openssl-1.1.1c/crypto/kdf/hkdf.c.s390x-ecc 2019-11-20 11:36:02.148861187 +0100 ++++ openssl-1.1.1c/crypto/kdf/hkdf.c 2019-11-20 11:36:02.198860310 +0100 +@@ -233,6 +233,11 @@ const EVP_KDF_METHOD hkdf_kdf_meth = { + kdf_hkdf_derive + }; + ++const EVP_PKEY_METHOD *hkdf_pkey_method(void) ++{ ++ return &hkdf_pkey_meth; ++} ++ + static int HKDF(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, +diff -up openssl-1.1.1c/crypto/kdf/scrypt.c.s390x-ecc openssl-1.1.1c/crypto/kdf/scrypt.c +--- openssl-1.1.1c/crypto/kdf/scrypt.c.s390x-ecc 2019-11-20 11:36:02.149861170 +0100 ++++ openssl-1.1.1c/crypto/kdf/scrypt.c 2019-11-20 11:36:02.198860310 +0100 +@@ -503,4 +503,9 @@ static int scrypt_alg(const char *pass, + return rv; + } + ++const EVP_PKEY_METHOD *scrypt_pkey_method(void) ++{ ++ return &scrypt_pkey_meth; ++} ++ + #endif +diff -up openssl-1.1.1c/crypto/kdf/tls1_prf.c.s390x-ecc openssl-1.1.1c/crypto/kdf/tls1_prf.c +--- openssl-1.1.1c/crypto/kdf/tls1_prf.c.s390x-ecc 2019-11-20 11:36:02.149861170 +0100 ++++ openssl-1.1.1c/crypto/kdf/tls1_prf.c 2019-11-20 11:36:02.198860310 +0100 +@@ -168,6 +168,11 @@ const EVP_KDF_METHOD tls1_prf_kdf_meth = + kdf_tls1_prf_derive + }; + ++const EVP_PKEY_METHOD *tls1_prf_pkey_method(void) ++{ ++ return &tls1_prf_pkey_meth; ++} ++ + static int tls1_prf_P_hash(const EVP_MD *md, + const unsigned char *sec, size_t sec_len, + const unsigned char *seed, size_t seed_len, +diff -up openssl-1.1.1c/crypto/poly1305/poly1305_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/poly1305/poly1305_pmeth.c +--- openssl-1.1.1c/crypto/poly1305/poly1305_pmeth.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/poly1305/poly1305_pmeth.c 2019-11-20 11:36:02.199860293 +0100 +@@ -192,3 +192,8 @@ const EVP_PKEY_METHOD poly1305_pkey_meth + pkey_poly1305_ctrl, + pkey_poly1305_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *poly1305_pkey_method(void) ++{ ++ return &poly1305_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/rsa/rsa_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/rsa/rsa_pmeth.c +--- openssl-1.1.1c/crypto/rsa/rsa_pmeth.c.s390x-ecc 2019-11-20 11:36:02.117861731 +0100 ++++ openssl-1.1.1c/crypto/rsa/rsa_pmeth.c 2019-11-20 11:36:02.199860293 +0100 +@@ -789,6 +789,11 @@ const EVP_PKEY_METHOD rsa_pkey_meth = { + pkey_rsa_ctrl_str + }; + ++const EVP_PKEY_METHOD *rsa_pkey_method(void) ++{ ++ return &rsa_pkey_meth; ++} ++ + /* + * Called for PSS sign or verify initialisation: checks PSS parameter + * sanity and sets any restrictions on key usage. +@@ -859,3 +864,8 @@ const EVP_PKEY_METHOD rsa_pss_pkey_meth + pkey_rsa_ctrl, + pkey_rsa_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *rsa_pss_pkey_method(void) ++{ ++ return &rsa_pss_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/s390x_arch.h.s390x-ecc openssl-1.1.1c/crypto/s390x_arch.h +--- openssl-1.1.1c/crypto/s390x_arch.h.s390x-ecc 2019-11-20 11:36:01.867866116 +0100 ++++ openssl-1.1.1c/crypto/s390x_arch.h 2019-11-20 11:36:02.199860293 +0100 +@@ -26,6 +26,12 @@ void s390x_kmf(const unsigned char *in, + unsigned int fc, void *param); + void s390x_kma(const unsigned char *aad, size_t alen, const unsigned char *in, + size_t len, unsigned char *out, unsigned int fc, void *param); ++int s390x_pcc(unsigned int fc, void *param); ++int s390x_kdsa(unsigned int fc, void *param, const unsigned char *in, ++ size_t len); ++ ++void s390x_flip_endian32(unsigned char dst[32], const unsigned char src[32]); ++void s390x_flip_endian64(unsigned char dst[64], const unsigned char src[64]); + + /* + * The field elements of OPENSSL_s390xcap_P are the 64-bit words returned by +@@ -45,6 +51,8 @@ struct OPENSSL_s390xcap_st { + unsigned long long kmf[2]; + unsigned long long prno[2]; + unsigned long long kma[2]; ++ unsigned long long pcc[2]; ++ unsigned long long kdsa[2]; + }; + + extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; +@@ -66,11 +74,14 @@ extern struct OPENSSL_s390xcap_st OPENSS + # define S390X_KMF 0x90 + # define S390X_PRNO 0xa0 + # define S390X_KMA 0xb0 ++# define S390X_PCC 0xc0 ++# define S390X_KDSA 0xd0 + + /* Facility Bit Numbers */ + # define S390X_VX 129 + # define S390X_VXD 134 + # define S390X_VXE 135 ++# define S390X_MSA9 155 /* message-security-assist-ext. 9 */ + + /* Function Codes */ + +@@ -94,10 +105,32 @@ extern struct OPENSSL_s390xcap_st OPENSS + /* prno */ + # define S390X_TRNG 114 + ++/* pcc */ ++# define S390X_SCALAR_MULTIPLY_P256 64 ++# define S390X_SCALAR_MULTIPLY_P384 65 ++# define S390X_SCALAR_MULTIPLY_P521 66 ++# define S390X_SCALAR_MULTIPLY_ED25519 72 ++# define S390X_SCALAR_MULTIPLY_ED448 73 ++# define S390X_SCALAR_MULTIPLY_X25519 80 ++# define S390X_SCALAR_MULTIPLY_X448 81 ++ ++/* kdsa */ ++# define S390X_ECDSA_VERIFY_P256 1 ++# define S390X_ECDSA_VERIFY_P384 2 ++# define S390X_ECDSA_VERIFY_P521 3 ++# define S390X_ECDSA_SIGN_P256 9 ++# define S390X_ECDSA_SIGN_P384 10 ++# define S390X_ECDSA_SIGN_P521 11 ++# define S390X_EDDSA_VERIFY_ED25519 32 ++# define S390X_EDDSA_VERIFY_ED448 36 ++# define S390X_EDDSA_SIGN_ED25519 40 ++# define S390X_EDDSA_SIGN_ED448 44 ++ + /* Register 0 Flags */ + # define S390X_DECRYPT 0x80 + # define S390X_KMA_LPC 0x100 + # define S390X_KMA_LAAD 0x200 + # define S390X_KMA_HS 0x400 ++# define S390X_KDSA_D 0x80 + + #endif +diff -up openssl-1.1.1c/crypto/s390xcpuid.pl.s390x-ecc openssl-1.1.1c/crypto/s390xcpuid.pl +--- openssl-1.1.1c/crypto/s390xcpuid.pl.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/s390xcpuid.pl 2019-11-20 11:36:02.199860293 +0100 +@@ -58,6 +58,10 @@ OPENSSL_s390x_facilities: + stg %r0,S390X_PRNO+8(%r4) + stg %r0,S390X_KMA(%r4) + stg %r0,S390X_KMA+8(%r4) ++ stg %r0,S390X_PCC(%r4) ++ stg %r0,S390X_PCC+8(%r4) ++ stg %r0,S390X_KDSA(%r4) ++ stg %r0,S390X_KDSA+8(%r4) + + .long 0xb2b04000 # stfle 0(%r4) + brc 8,.Ldone +@@ -68,6 +72,7 @@ OPENSSL_s390x_facilities: + .long 0xb2b04000 # stfle 0(%r4) + .Ldone: + lmg %r2,%r3,S390X_STFLE(%r4) ++ + tmhl %r2,0x4000 # check for message-security-assist + jz .Lret + +@@ -91,6 +96,13 @@ OPENSSL_s390x_facilities: + la %r1,S390X_KMAC(%r4) + .long 0xb91e0042 # kmac %r4,%r2 + ++ tmhh %r3,0x0008 # check for message-security-assist-3 ++ jz .Lret ++ ++ lghi %r0,S390X_QUERY # query pcc capability vector ++ la %r1,S390X_PCC(%r4) ++ .long 0xb92c0000 # pcc ++ + tmhh %r3,0x0004 # check for message-security-assist-4 + jz .Lret + +@@ -114,6 +126,7 @@ OPENSSL_s390x_facilities: + .long 0xb93c0042 # prno %r4,%r2 + + lg %r2,S390X_STFLE+16(%r4) ++ + tmhl %r2,0x2000 # check for message-security-assist-8 + jz .Lret + +@@ -121,6 +134,13 @@ OPENSSL_s390x_facilities: + la %r1,S390X_KMA(%r4) + .long 0xb9294022 # kma %r2,%r4,%r2 + ++ tmhl %r2,0x0010 # check for message-security-assist-9 ++ jz .Lret ++ ++ lghi %r0,S390X_QUERY # query kdsa capability vector ++ la %r1,S390X_KDSA(%r4) ++ .long 0xb93a0002 # kdsa %r0,%r2 ++ + .Lret: + br $ra + .size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities +@@ -411,6 +431,113 @@ s390x_kma: + ___ + } + ++################ ++# int s390x_pcc(unsigned int fc, void *param) ++{ ++my ($fc,$param) = map("%r$_",(2..3)); ++$code.=<<___; ++.globl s390x_pcc ++.type s390x_pcc,\@function ++.align 16 ++s390x_pcc: ++ lr %r0,$fc ++ l${g}r %r1,$param ++ lhi %r2,0 ++ ++ .long 0xb92c0000 # pcc ++ brc 1,.-4 # pay attention to "partial completion" ++ brc 7,.Lpcc_err # if CC==0 return 0, else return 1 ++.Lpcc_out: ++ br $ra ++.Lpcc_err: ++ lhi %r2,1 ++ j .Lpcc_out ++.size s390x_pcc,.-s390x_pcc ++___ ++} ++ ++################ ++# int s390x_kdsa(unsigned int fc, void *param, ++# const unsigned char *in, size_t len) ++{ ++my ($fc,$param,$in,$len) = map("%r$_",(2..5)); ++$code.=<<___; ++.globl s390x_kdsa ++.type s390x_kdsa,\@function ++.align 16 ++s390x_kdsa: ++ lr %r0,$fc ++ l${g}r %r1,$param ++ lhi %r2,0 ++ ++ .long 0xb93a0004 # kdsa %r0,$in ++ brc 1,.-4 # pay attention to "partial completion" ++ brc 7,.Lkdsa_err # if CC==0 return 0, else return 1 ++.Lkdsa_out: ++ br $ra ++.Lkdsa_err: ++ lhi %r2,1 ++ j .Lkdsa_out ++.size s390x_kdsa,.-s390x_kdsa ++___ ++} ++ ++################ ++# void s390x_flip_endian32(unsigned char dst[32], const unsigned char src[32]) ++{ ++my ($dst,$src) = map("%r$_",(2..3)); ++$code.=<<___; ++.globl s390x_flip_endian32 ++.type s390x_flip_endian32,\@function ++.align 16 ++s390x_flip_endian32: ++ lrvg %r0,0(%r0,$src) ++ lrvg %r1,8(%r0,$src) ++ lrvg %r4,16(%r0,$src) ++ lrvg %r5,24(%r0,$src) ++ stg %r0,24(%r0,$dst) ++ stg %r1,16(%r0,$dst) ++ stg %r4,8(%r0,$dst) ++ stg %r5,0(%r0,$dst) ++ br $ra ++.size s390x_flip_endian32,.-s390x_flip_endian32 ++___ ++} ++ ++################ ++# void s390x_flip_endian64(unsigned char dst[64], const unsigned char src[64]) ++{ ++my ($dst,$src) = map("%r$_",(2..3)); ++$code.=<<___; ++.globl s390x_flip_endian64 ++.type s390x_flip_endian64,\@function ++.align 16 ++s390x_flip_endian64: ++ stmg %r6,%r9,6*$SIZE_T($sp) ++ ++ lrvg %r0,0(%r0,$src) ++ lrvg %r1,8(%r0,$src) ++ lrvg %r4,16(%r0,$src) ++ lrvg %r5,24(%r0,$src) ++ lrvg %r6,32(%r0,$src) ++ lrvg %r7,40(%r0,$src) ++ lrvg %r8,48(%r0,$src) ++ lrvg %r9,56(%r0,$src) ++ stg %r0,56(%r0,$dst) ++ stg %r1,48(%r0,$dst) ++ stg %r4,40(%r0,$dst) ++ stg %r5,32(%r0,$dst) ++ stg %r6,24(%r0,$dst) ++ stg %r7,16(%r0,$dst) ++ stg %r8,8(%r0,$dst) ++ stg %r9,0(%r0,$dst) ++ ++ lmg %r6,%r9,6*$SIZE_T($sp) ++ br $ra ++.size s390x_flip_endian64,.-s390x_flip_endian64 ++___ ++} ++ + $code.=<<___; + .section .init + brasl $ra,OPENSSL_cpuid_setup +diff -up openssl-1.1.1c/crypto/siphash/siphash_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/siphash/siphash_pmeth.c +--- openssl-1.1.1c/crypto/siphash/siphash_pmeth.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/siphash/siphash_pmeth.c 2019-11-20 11:36:02.200860275 +0100 +@@ -203,3 +203,8 @@ const EVP_PKEY_METHOD siphash_pkey_meth + pkey_siphash_ctrl, + pkey_siphash_ctrl_str + }; ++ ++const EVP_PKEY_METHOD *siphash_pkey_method(void) ++{ ++ return &siphash_pkey_meth; ++} +diff -up openssl-1.1.1c/crypto/sm2/sm2_pmeth.c.s390x-ecc openssl-1.1.1c/crypto/sm2/sm2_pmeth.c +--- openssl-1.1.1c/crypto/sm2/sm2_pmeth.c.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/sm2/sm2_pmeth.c 2019-11-20 11:36:02.200860275 +0100 +@@ -323,3 +323,8 @@ const EVP_PKEY_METHOD sm2_pkey_meth = { + + pkey_sm2_digest_custom + }; ++ ++const EVP_PKEY_METHOD *sm2_pkey_method(void) ++{ ++ return &sm2_pkey_meth; ++} +diff -up openssl-1.1.1c/include/internal/constant_time_locl.h.s390x-ecc openssl-1.1.1c/include/internal/constant_time_locl.h +--- openssl-1.1.1c/include/internal/constant_time_locl.h.s390x-ecc 2019-11-20 11:36:02.176860696 +0100 ++++ openssl-1.1.1c/include/internal/constant_time_locl.h 2019-11-20 11:36:02.200860275 +0100 +@@ -347,6 +347,34 @@ static ossl_inline void constant_time_co + } + + /* ++ * mask must be 0xFF or 0x00. ++ * "constant time" is per len. ++ * ++ * if (mask) { ++ * unsigned char tmp[len]; ++ * ++ * memcpy(tmp, a, len); ++ * memcpy(a, b); ++ * memcpy(b, tmp); ++ * } ++ */ ++static ossl_inline void constant_time_cond_swap_buff(unsigned char mask, ++ unsigned char *a, ++ unsigned char *b, ++ size_t len) ++{ ++ size_t i; ++ unsigned char tmp; ++ ++ for (i = 0; i < len; i++) { ++ tmp = a[i] ^ b[i]; ++ tmp &= mask; ++ a[i] ^= tmp; ++ b[i] ^= tmp; ++ } ++} ++ ++/* + * table is a two dimensional array of bytes. Each row has rowsize elements. + * Copies row number idx into out. rowsize and numrows are not considered + * private. +diff -up openssl-1.1.1c/include/openssl/ecerr.h.s390x-ecc openssl-1.1.1c/include/openssl/ecerr.h +--- openssl-1.1.1c/include/openssl/ecerr.h.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/include/openssl/ecerr.h 2019-11-20 11:36:02.200860275 +0100 +@@ -38,6 +38,11 @@ int ERR_load_EC_strings(void); + # define EC_F_ECDSA_SIGN_SETUP 248 + # define EC_F_ECDSA_SIG_NEW 265 + # define EC_F_ECDSA_VERIFY 253 ++# define EC_F_ECDSA_SIMPLE_SIGN_SETUP 310 ++# define EC_F_ECDSA_SIMPLE_SIGN_SIG 311 ++# define EC_F_ECDSA_SIMPLE_VERIFY_SIG 312 ++# define EC_F_ECDSA_S390X_NISTP_SIGN_SIG 313 ++# define EC_F_ECDSA_S390X_NISTP_VERIFY_SIG 314 + # define EC_F_ECD_ITEM_VERIFY 270 + # define EC_F_ECKEY_PARAM2TYPE 223 + # define EC_F_ECKEY_PARAM_DECODE 212 +@@ -181,6 +186,7 @@ int ERR_load_EC_strings(void); + # define EC_F_O2I_ECPUBLICKEY 152 + # define EC_F_OLD_EC_PRIV_DECODE 222 + # define EC_F_OSSL_ECDH_COMPUTE_KEY 247 ++# define EC_F_OSSL_ECDSA_SIGN_SETUP 300 + # define EC_F_OSSL_ECDSA_SIGN_SIG 249 + # define EC_F_OSSL_ECDSA_VERIFY_SIG 250 + # define EC_F_PKEY_ECD_CTRL 271 +@@ -196,6 +202,12 @@ int ERR_load_EC_strings(void); + # define EC_F_PKEY_EC_KEYGEN 199 + # define EC_F_PKEY_EC_PARAMGEN 219 + # define EC_F_PKEY_EC_SIGN 218 ++# define EC_F_S390X_PKEY_ECD_DIGESTSIGN25519 320 ++# define EC_F_S390X_PKEY_ECD_DIGESTSIGN448 321 ++# define EC_F_S390X_PKEY_ECD_KEYGEN25519 322 ++# define EC_F_S390X_PKEY_ECD_KEYGEN448 323 ++# define EC_F_S390X_PKEY_ECX_KEYGEN25519 324 ++# define EC_F_S390X_PKEY_ECX_KEYGEN448 325 + # define EC_F_VALIDATE_ECX_DERIVE 278 + + /* +@@ -208,6 +220,7 @@ int ERR_load_EC_strings(void); + # define EC_R_CANNOT_INVERT 165 + # define EC_R_COORDINATES_OUT_OF_RANGE 146 + # define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 ++# define EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA 170 + # define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 + # define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 + # define EC_R_DECODE_ERROR 142 +diff -up openssl-1.1.1c/test/recipes/30-test_evp_data/evppkey.txt.s390x-ecc openssl-1.1.1c/test/recipes/30-test_evp_data/evppkey.txt +--- openssl-1.1.1c/test/recipes/30-test_evp_data/evppkey.txt.s390x-ecc 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/test/recipes/30-test_evp_data/evppkey.txt 2019-11-20 11:36:02.203860223 +0100 +@@ -814,6 +814,8 @@ PublicKeyRaw=Bob-448-PUBLIC-Raw:X448:3eb + + PrivPubKeyPair = Bob-448-Raw:Bob-448-PUBLIC-Raw + ++PublicKeyRaw=Bob-448-PUBLIC-Raw-NonCanonical:X448:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++ + Derive=Alice-448 + PeerKey=Bob-448-PUBLIC + SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d +@@ -830,6 +832,11 @@ Derive=Bob-448-Raw + PeerKey=Alice-448-PUBLIC-Raw + SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d + ++# Self-generated non-canonical ++Derive=Alice-448-Raw ++PeerKey=Bob-448-PUBLIC-Raw-NonCanonical ++SharedSecret=66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee63660eabd54934f3382061d17607f581a90bdac917a064959fb ++ + # Illegal sign/verify operations with X448 key + + Sign=Alice-448 diff --git a/SOURCES/openssl-1.1.1-s390x-sigill.patch b/SOURCES/openssl-1.1.1-s390x-sigill.patch new file mode 100644 index 0000000..f44405a --- /dev/null +++ b/SOURCES/openssl-1.1.1-s390x-sigill.patch @@ -0,0 +1,40 @@ +diff -up openssl-1.1.1c/crypto/s390xcap.c.s390x-sigill openssl-1.1.1c/crypto/s390xcap.c +--- openssl-1.1.1c/crypto/s390xcap.c.s390x-sigill 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/crypto/s390xcap.c 2020-02-12 17:05:54.566258533 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright 2010-2017 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2010-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -29,7 +29,7 @@ struct OPENSSL_s390xcap_st OPENSSL_s390x + void OPENSSL_cpuid_setup(void) + { + sigset_t oset; +- struct sigaction ill_act, oact; ++ struct sigaction ill_act, oact_ill, oact_fpe; + + if (OPENSSL_s390xcap_P.stfle[0]) + return; +@@ -44,8 +44,8 @@ void OPENSSL_cpuid_setup(void) + sigdelset(&ill_act.sa_mask, SIGFPE); + sigdelset(&ill_act.sa_mask, SIGTRAP); + sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); +- sigaction(SIGILL, &ill_act, &oact); +- sigaction(SIGFPE, &ill_act, &oact); ++ sigaction(SIGILL, &ill_act, &oact_ill); ++ sigaction(SIGFPE, &ill_act, &oact_fpe); + + /* protection against missing store-facility-list-extended */ + if (sigsetjmp(ill_jmp, 1) == 0) +@@ -61,7 +61,7 @@ void OPENSSL_cpuid_setup(void) + | S390X_CAPBIT(S390X_VXE)); + } + +- sigaction(SIGFPE, &oact, NULL); +- sigaction(SIGILL, &oact, NULL); ++ sigaction(SIGFPE, &oact_fpe, NULL); ++ sigaction(SIGILL, &oact_ill, NULL); + sigprocmask(SIG_SETMASK, &oset, NULL); + } diff --git a/SOURCES/openssl-1.1.1-tls-compliance.patch b/SOURCES/openssl-1.1.1-tls-compliance.patch new file mode 100644 index 0000000..e10b53e --- /dev/null +++ b/SOURCES/openssl-1.1.1-tls-compliance.patch @@ -0,0 +1,26 @@ +diff -up openssl-1.1.1c/ssl/record/ssl3_record.c.compliance openssl-1.1.1c/ssl/record/ssl3_record.c +--- openssl-1.1.1c/ssl/record/ssl3_record.c.compliance 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/ssl/record/ssl3_record.c 2019-11-25 13:10:53.890637381 +0100 +@@ -559,7 +559,7 @@ int ssl3_get_record(SSL *s) + RECORD_LAYER_reset_read_sequence(&s->rlayer); + return 1; + } +- SSLfatal(s, SSL_AD_DECRYPTION_FAILED, SSL_F_SSL3_GET_RECORD, ++ SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD, + SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + return -1; + } +diff -up openssl-1.1.1c/ssl/statem/extensions_srvr.c.compliance openssl-1.1.1c/ssl/statem/extensions_srvr.c +--- openssl-1.1.1c/ssl/statem/extensions_srvr.c.compliance 2019-05-28 15:12:21.000000000 +0200 ++++ openssl-1.1.1c/ssl/statem/extensions_srvr.c 2019-11-25 13:12:59.329459528 +0100 +@@ -1487,6 +1487,10 @@ EXT_RETURN tls_construct_stoc_status_req + unsigned int context, X509 *x, + size_t chainidx) + { ++ /* We don't currently support this extension inside a CertificateRequest */ ++ if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) ++ return EXT_RETURN_NOT_SENT; ++ + if (!s->ext.status_expected) + return EXT_RETURN_NOT_SENT; + diff --git a/SPECS/openssl.spec b/SPECS/openssl.spec index c38e67d..a1b35d7 100644 --- a/SPECS/openssl.spec +++ b/SPECS/openssl.spec @@ -22,7 +22,7 @@ Summary: Utilities from the general purpose cryptography library with TLS implementation Name: openssl Version: 1.1.1c -Release: 2%{?dist}.1 +Release: 15%{?dist} Epoch: 1 # We have to remove certain patented algorithms from the openssl source # tarball with the hobble-openssl script which is included below. @@ -62,12 +62,22 @@ Patch47: openssl-1.1.1-ts-sha256-default.patch Patch48: openssl-1.1.1-fips-post-rand.patch Patch49: openssl-1.1.1-evp-kdf.patch Patch50: openssl-1.1.1-ssh-kdf.patch +Patch60: openssl-1.1.1-krb5-kdf.patch +Patch61: openssl-1.1.1-edk2-build.patch +Patch62: openssl-1.1.1-fips-curves.patch Patch65: openssl-1.1.1-fips-drbg-selftest.patch # Backported fixes including security fixes Patch51: openssl-1.1.1-upstream-sync.patch Patch52: openssl-1.1.1-s390x-update.patch Patch53: openssl-1.1.1-fips-crng-test.patch Patch54: openssl-1.1.1-regression-fixes.patch +Patch55: openssl-1.1.1-arm-update.patch +Patch56: openssl-1.1.1-s390x-ecc.patch +Patch57: openssl-1.1.1-cve-2019-1547.patch +Patch58: openssl-1.1.1-cve-2019-1563.patch +Patch59: openssl-1.1.1-cve-2019-1549.patch +Patch63: openssl-1.1.1-tls-compliance.patch +Patch64: openssl-1.1.1-s390x-sigill.patch License: OpenSSL Group: System Environment/Libraries @@ -178,9 +188,18 @@ cp %{SOURCE13} test/ %patch52 -p1 -b .s390x-update %patch53 -p1 -b .crng-test %patch54 -p1 -b .regression +%patch55 -p1 -b .arm-update +%patch56 -p1 -b .s390x-ecc +%patch57 -p1 -b .compute-cofactor +%patch58 -p1 -b .cms-padding-oracle +%patch59 -p1 -b .fork-safety +%patch60 -p1 -b .krb5-kdf +%patch61 -p1 -b .edk2-build +%patch62 -p1 -b .fips-curves +%patch63 -p1 -b .compliance +%patch64 -p1 -b .s390x-sigill %patch65 -p1 -b .drbg-selftest - %build # Figure out which flags we want to use. # default @@ -463,9 +482,43 @@ export LD_LIBRARY_PATH %postun libs -p /sbin/ldconfig %changelog -* Thu Mar 5 2020 Tomáš Mráz 1.1.1c-2.1 +* Thu Mar 5 2020 Tomáš Mráz 1.1.1c-15 - add selftest of the RAND_DRBG implementation + +* Wed Feb 19 2020 Tomáš Mráz 1.1.1c-14 - fix incorrect error return value from FIPS_selftest_dsa +- S390x: properly restore SIGILL signal handler + +* Wed Dec 4 2019 Tomáš Mráz 1.1.1c-12 +- additional fix for the edk2 build + +* Tue Nov 26 2019 Tomáš Mráz 1.1.1c-9 +- disallow use of SHA-1 signatures in TLS in FIPS mode + +* Mon Nov 25 2019 Tomáš Mráz 1.1.1c-8 +- fix CVE-2019-1547 - side-channel weak encryption vulnerability +- fix CVE-2019-1563 - padding oracle in CMS API +- fix CVE-2019-1549 - ensure fork safety of the DRBG +- fix handling of non-FIPS allowed EC curves in FIPS mode +- fix TLS compliance issues + +* Thu Nov 21 2019 Tomáš Mráz 1.1.1c-7 +- backported ARM performance fixes from master + +* Wed Nov 20 2019 Tomáš Mráz 1.1.1c-6 +- backport of S390x ECC CPACF enhancements from master +- FIPS mode: properly disable 1024 bit DSA key generation +- FIPS mode: skip ED25519 and ED448 algorithms in openssl speed +- FIPS mode: allow AES-CCM ciphersuites + +* Tue Nov 19 2019 Tomáš Mráz 1.1.1c-5 +- make the code suitable for edk2 build + +* Thu Nov 14 2019 Tomáš Mráz 1.1.1c-4 +- backport of SSKDF from master + +* Wed Nov 13 2019 Tomáš Mráz 1.1.1c-3 +- backport of KBKDF and KRB5KDF from master * Mon Jun 24 2019 Tomáš Mráz 1.1.1c-2 - do not try to use EC groups disallowed in FIPS mode