Latest update

This commit is contained in:
2019-04-01 00:21:15 +09:00
parent c03e0c45f8
commit 48ec086472
209 changed files with 7552 additions and 2495 deletions
+2 -2
View File
@@ -1829,7 +1829,7 @@ Lctr32_enc8x_three:
stvx_u $out1,$x10,$out
stvx_u $out2,$x20,$out
addi $out,$out,0x30
b Lcbc_dec8x_done
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_two:
@@ -1841,7 +1841,7 @@ Lctr32_enc8x_two:
stvx_u $out0,$x00,$out
stvx_u $out1,$x10,$out
addi $out,$out,0x20
b Lcbc_dec8x_done
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_one:
+6
View File
@@ -22,6 +22,12 @@ NON_EMPTY_TRANSLATION_UNIT
# ifndef OPENSSL_NO_RC4
# define ASN1_BROKEN_SEQUENCE(tname) \
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
ASN1_SEQUENCE(tname)
# define static_ASN1_BROKEN_SEQUENCE_END(stname) \
static_ASN1_SEQUENCE_END_ref(stname, stname)
typedef struct netscape_pkey_st {
int32_t version;
X509_ALGOR *algor;
+1 -1
View File
@@ -88,7 +88,7 @@ if ($flavour =~ /64|n32/i) {
$SZREG=4;
$REG_S="sw";
$REG_L="lw";
$code=".set mips2\n";
$code="#if !(defined (__mips_isa_rev) && (__mips_isa_rev >= 6))\n.set mips2\n#endif\n";
}
# Below is N32/64 register layout used in the original module.
+1
View File
@@ -258,6 +258,7 @@ $data=<<EOF;
# .text section
.machine "any"
.text
#
# NOTE: The following label name should be changed to
+2
View File
@@ -184,6 +184,8 @@ void BN_CTX_start(BN_CTX *ctx)
void BN_CTX_end(BN_CTX *ctx)
{
if (ctx == NULL)
return;
CTXDBG("ENTER BN_CTX_end()", ctx);
if (ctx->err_stack)
ctx->err_stack--;
+2
View File
@@ -338,6 +338,8 @@ void BN_swap(BIGNUM *a, BIGNUM *b)
void BN_clear(BIGNUM *a)
{
if (a == NULL)
return;
bn_check_top(a);
if (a->d != NULL)
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
+1 -2
View File
@@ -170,8 +170,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
found = 1;
err:
OPENSSL_free(mods);
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
bn_check_top(ret);
return found;
+1 -1
View File
@@ -9,7 +9,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
LIBS=../libcrypto
# The Core
SOURCE[../libcrypto]=provider_core.c core_fetch.c
SOURCE[../libcrypto]=provider_core.c provider_predefined.c core_fetch.c
# Central utilities
SOURCE[../libcrypto]=\
+292
View File
@@ -0,0 +1,292 @@
#!/usr/bin/env perl
#
# ====================================================================
# Written by Andy Polyakov, @dot-asm, initially for use with OpenSSL.
# ====================================================================
#
# ChaCha20 for Itanium.
#
# March 2019
#
# Itanium 9xxx, which has pair of shifters, manages to process one byte
# in 9.3 cycles. This aligns perfectly with theoretical estimate.
# On the other hand, pre-9000 CPU has single shifter and each extr/dep
# pairs below takes additional cycle. Then final input->xor->output
# pass runs slower than expected... Overall result is 15.6 cpb, two
# cycles more than theoretical estimate.
$output = pop;
open STDOUT, ">$output" if $output;
my @k = map("r$_",(16..31));
my @x = map("r$_",(38..53));
my @y = map("r$_",(8..11));
my @z = map("r$_",(15,35..37));
my ($out,$inp,$len,$key,$counter) = map("r$_",(32..36));
$code.=<<___;
#if defined(_HPUX_SOURCE)
# if !defined(_LP64)
# define ADDP addp4
# else
# define ADDP add
# endif
#else
# define ADDP add
#endif
.text
.global ChaCha20_ctr32#
.proc ChaCha20_ctr32#
.align 32
ChaCha20_ctr32:
.prologue
.save ar.pfs,r2
{ .mmi; alloc r2=ar.pfs,5,17,0,0
ADDP @k[11]=4,$key
.save ar.lc,r3
mov r3=ar.lc }
{ .mmi; ADDP $key=0,$key
ADDP $counter=0,$counter
.save pr,r14
mov r14=pr };;
.body
{ .mlx; ld4 @k[4]=[$key],8
movl @k[0]=0x61707865 }
{ .mlx; ld4 @k[5]=[@k[11]],8
movl @k[1]=0x3320646e };;
{ .mlx; ld4 @k[6]=[$key],8
movl @k[2]=0x79622d32 }
{ .mlx; ld4 @k[7]=[@k[11]],8
movl @k[3]=0x6b206574 };;
{ .mmi; ld4 @k[8]=[$key],8
ld4 @k[9]=[@k[11]],8
add @k[15]=4,$counter };;
{ .mmi; ld4 @k[10]=[$key]
ld4 @k[11]=[@k[11]]
mov @x[0]=@k[0] };;
{ .mmi; ld4 @k[12]=[$counter],8
ld4 @k[13]=[@k[15]],8
mov @x[1]=@k[1] };;
{ .mmi; ld4 @k[14]=[$counter]
ld4 @k[15]=[@k[15]]
mov @x[2]=@k[2] }
{ .mmi; mov @x[3]=@k[3]
mov @x[4]=@k[4]
mov @x[5]=@k[5] };;
{ .mmi; mov @x[6]=@k[6]
mov @x[7]=@k[7]
mov @x[8]=@k[8] }
{ .mmi; mov @x[9]=@k[9]
mov @x[10]=@k[10]
mov @x[11]=@k[11] }
{ .mmi; mov @x[12]=@k[12]
mov @x[13]=@k[13]
mov @x[14]=@k[14] };;
.Loop_outer:
{ .mii; mov @x[15]=@k[15]
mov ar.lc=9
mov ar.ec=1 }
{ .mmb; cmp.geu p6,p0=64,$len
sub @z[1]=64,$len
brp.loop.imp .Loop_top,.Loop_end-16 };;
.Loop_top:
___
sub 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));
$code.=<<___;
{ .mmi; add @x[$a0]=@x[$a0],@x[$b0]
add @x[$a1]=@x[$a1],@x[$b1]
add @x[$a2]=@x[$a2],@x[$b2] };;
{ .mmi; add @x[$a3]=@x[$a3],@x[$b3]
xor @x[$d0]=@x[$d0],@x[$a0]
xor @x[$d1]=@x[$d1],@x[$a1] };;
{ .mmi; xor @x[$d2]=@x[$d2],@x[$a2]
xor @x[$d3]=@x[$d3],@x[$a3]
extr.u @y[0]=@x[$d0],16,16 };;
{ .mii; extr.u @y[1]=@x[$d1],16,16
dep @x[$d0]=@x[$d0],@y[0],16,16 };;
{ .mii; add @x[$c0]=@x[$c0],@x[$d0]
extr.u @y[2]=@x[$d2],16,16
dep @x[$d1]=@x[$d1],@y[1],16,16 };;
{ .mii; add @x[$c1]=@x[$c1],@x[$d1]
xor @x[$b0]=@x[$b0],@x[$c0]
extr.u @y[3]=@x[$d3],16,16 };;
{ .mii; xor @x[$b1]=@x[$b1],@x[$c1]
dep @x[$d2]=@x[$d2],@y[2],16,16
dep @x[$d3]=@x[$d3],@y[3],16,16 };;
{ .mmi; add @x[$c2]=@x[$c2],@x[$d2]
add @x[$c3]=@x[$c3],@x[$d3]
extr.u @y[0]=@x[$b0],20,12 };;
{ .mmi; xor @x[$b2]=@x[$b2],@x[$c2]
xor @x[$b3]=@x[$b3],@x[$c3]
dep.z @x[$b0]=@x[$b0],12,20 };;
{ .mii; or @x[$b0]=@x[$b0],@y[0]
extr.u @y[1]=@x[$b1],20,12
dep.z @x[$b1]=@x[$b1],12,20 };;
{ .mii; add @x[$a0]=@x[$a0],@x[$b0]
extr.u @y[2]=@x[$b2],20,12
extr.u @y[3]=@x[$b3],20,12 }
{ .mii; or @x[$b1]=@x[$b1],@y[1]
dep.z @x[$b2]=@x[$b2],12,20
dep.z @x[$b3]=@x[$b3],12,20 };;
{ .mmi; or @x[$b2]=@x[$b2],@y[2]
or @x[$b3]=@x[$b3],@y[3]
add @x[$a1]=@x[$a1],@x[$b1] };;
{ .mmi; add @x[$a2]=@x[$a2],@x[$b2]
add @x[$a3]=@x[$a3],@x[$b3]
xor @x[$d0]=@x[$d0],@x[$a0] };;
{ .mii; xor @x[$d1]=@x[$d1],@x[$a1]
extr.u @y[0]=@x[$d0],24,8
dep.z @x[$d0]=@x[$d0],8,24 };;
{ .mii; or @x[$d0]=@x[$d0],@y[0]
extr.u @y[1]=@x[$d1],24,8
dep.z @x[$d1]=@x[$d1],8,24 };;
{ .mmi; or @x[$d1]=@x[$d1],@y[1]
xor @x[$d2]=@x[$d2],@x[$a2]
xor @x[$d3]=@x[$d3],@x[$a3] };;
{ .mii; add @x[$c0]=@x[$c0],@x[$d0]
extr.u @y[2]=@x[$d2],24,8
dep.z @x[$d2]=@x[$d2],8,24 };;
{ .mii; xor @x[$b0]=@x[$b0],@x[$c0]
extr.u @y[3]=@x[$d3],24,8
dep.z @x[$d3]=@x[$d3],8,24 };;
{ .mmi; or @x[$d2]=@x[$d2],@y[2]
or @x[$d3]=@x[$d3],@y[3]
extr.u @y[0]=@x[$b0],25,7 };;
{ .mmi; add @x[$c1]=@x[$c1],@x[$d1]
add @x[$c2]=@x[$c2],@x[$d2]
dep.z @x[$b0]=@x[$b0],7,25 };;
{ .mmi; xor @x[$b1]=@x[$b1],@x[$c1]
xor @x[$b2]=@x[$b2],@x[$c2]
add @x[$c3]=@x[$c3],@x[$d3] };;
{ .mii; xor @x[$b3]=@x[$b3],@x[$c3]
extr.u @y[1]=@x[$b1],25,7
dep.z @x[$b1]=@x[$b1],7,25 };;
{ .mii; or @x[$b0]=@x[$b0],@y[0]
extr.u @y[2]=@x[$b2],25,7
dep.z @x[$b2]=@x[$b2],7,25 };;
{ .mii; or @x[$b1]=@x[$b1],@y[1]
extr.u @y[3]=@x[$b3],25,7
dep.z @x[$b3]=@x[$b3],7,25 };;
___
$code.=<<___ if ($d0 == 12);
{ .mmi; or @x[$b2]=@x[$b2],@y[2]
or @x[$b3]=@x[$b3],@y[3]
mov @z[0]=-1 };;
___
$code.=<<___ if ($d0 == 15);
{ .mmb; or @x[$b2]=@x[$b2],@y[2]
or @x[$b3]=@x[$b3],@y[3]
br.ctop.sptk .Loop_top };;
___
}
&ROUND(0, 4, 8, 12);
&ROUND(0, 5, 10, 15);
$code.=<<___;
.Loop_end:
{ .mmi; add @x[0]=@x[0],@k[0]
add @x[1]=@x[1],@k[1]
(p6) shr.u @z[0]=@z[0],@z[1] }
{ .mmb; add @x[2]=@x[2],@k[2]
add @x[3]=@x[3],@k[3]
clrrrb.pr };;
{ .mmi; add @x[4]=@x[4],@k[4]
add @x[5]=@x[5],@k[5]
add @x[6]=@x[6],@k[6] }
{ .mmi; add @x[7]=@x[7],@k[7]
add @x[8]=@x[8],@k[8]
add @x[9]=@x[9],@k[9] }
{ .mmi; add @x[10]=@x[10],@k[10]
add @x[11]=@x[11],@k[11]
add @x[12]=@x[12],@k[12] }
{ .mmi; add @x[13]=@x[13],@k[13]
add @x[14]=@x[14],@k[14]
add @x[15]=@x[15],@k[15] }
{ .mmi; add @k[12]=1,@k[12] // next counter
mov pr=@z[0],0x1ffff };;
//////////////////////////////////////////////////////////////////
// Each predicate bit corresponds to byte to be processed. Note
// that p0 is wired to 1, but it works out, because there always
// is at least one byte to process...
{ .mmi; (p0) ld1 @z[0]=[$inp],1
shr.u @y[1]=@x[0],8 };;
{ .mmi; (p1) ld1 @z[1]=[$inp],1
(p2) shr.u @y[2]=@x[0],16 };;
{ .mmi; (p2) ld1 @z[2]=[$inp],1
(p0) xor @z[0]=@z[0],@x[0]
(p3) shr.u @y[3]=@x[0],24 };;
___
for(my $i0=0; $i0<60; $i0+=4) {
my ($i1, $i2, $i3, $i4, $i5, $i6, $i7) = map($i0+$_,(1..7));
my $k = $i0/4+1;
$code.=<<___;
{ .mmi; (p$i3) ld1 @z[3]=[$inp],1
(p$i0) st1 [$out]=@z[0],1
(p$i1) xor @z[1]=@z[1],@y[1] };;
{ .mmi; (p$i4) ld1 @z[0]=[$inp],1
(p$i5) shr.u @y[1]=@x[$k],8 }
{ .mmi; (p$i1) st1 [$out]=@z[1],1
(p$i2) xor @z[2]=@z[2],@y[2]
(p1) mov @x[$k-1]=@k[$k-1] };;
{ .mfi; (p$i5) ld1 @z[1]=[$inp],1
(p$i6) shr.u @y[2]=@x[$k],16 }
{ .mfi; (p$i2) st1 [$out]=@z[2],1
(p$i3) xor @z[3]=@z[3],@y[3] };;
{ .mfi; (p$i6) ld1 @z[2]=[$inp],1
(p$i7) shr.u @y[3]=@x[$k],24 }
___
$code.=<<___ if ($i0==0); # p1,p2 are available for reuse in first round
{ .mmi; (p$i3) st1 [$out]=@z[3],1
(p$i4) xor @z[0]=@z[0],@x[$k]
cmp.ltu p1,p2=64,$len };;
___
$code.=<<___ if ($i0>0);
{ .mfi; (p$i3) st1 [$out]=@z[3],1
(p$i4) xor @z[0]=@z[0],@x[$k] };;
___
}
$code.=<<___;
{ .mmi; (p63) ld1 @z[3]=[$inp],1
(p60) st1 [$out]=@z[0],1
(p61) xor @z[1]=@z[1],@y[1] };;
{ .mmi; (p61) st1 [$out]=@z[1],1
(p62) xor @z[2]=@z[2],@y[2] };;
{ .mmi; (p62) st1 [$out]=@z[2],1
(p63) xor @z[3]=@z[3],@y[3]
(p2) mov ar.lc=r3 };;
{ .mib; (p63) st1 [$out]=@z[3],1
(p1) add $len=-64,$len
(p1) br.dptk.many .Loop_outer };;
{ .mmi; mov @k[4]=0 // wipe key material
mov @k[5]=0
mov @k[6]=0 }
{ .mmi; mov @k[7]=0
mov @k[8]=0
mov @k[9]=0 }
{ .mmi; mov @k[10]=0
mov @k[11]=0
mov @k[12]=0 }
{ .mmi; mov @k[13]=0
mov @k[14]=0
mov @k[15]=0 }
{ .mib; mov pr=r14,0x1ffff
br.ret.sptk.many b0 };;
.endp ChaCha20_ctr32#
stringz "ChaCha20 for IA64, CRYPTOGAMS by \@dot-asm"
___
print $code;
close STDOUT;
+1
View File
@@ -12,3 +12,4 @@ INCLUDE[chacha-armv8.o]=..
INCLUDE[chacha-s390x.o]=..
GENERATE[chacha-c64xplus.S]=asm/chacha-c64xplus.pl $(PERLASM_SCHEME)
GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl $(PERLASM_SCHEME)
GENERATE[chacha-ia64.S]=asm/chacha-ia64.pl $(PERLASM_SCHEME)
+1 -1
View File
@@ -669,7 +669,7 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
char **dirpath)
{
struct stat st = { 0 };
struct stat st;
BIO *next;
if (stat(include, &st) < 0) {
+1
View File
@@ -35,6 +35,7 @@ void OPENSSL_config(const char *appname)
memset(&settings, 0, sizeof(settings));
if (appname != NULL)
settings.appname = strdup(appname);
settings.flags = DEFAULT_CONF_MFLAGS;
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings);
}
#endif
+20 -12
View File
@@ -39,25 +39,33 @@ static int ossl_method_construct_this(OSSL_PROVIDER *provider, void *cbdata)
data->mcm_data)) == NULL)
continue;
/*
* Note regarding putting the method in stores:
*
* we don't need to care if it actually got in or not here.
* If it didn't get in, it will simply not be available when
* ossl_method_construct() tries to get it from the store.
*
* It is *expected* that the put function increments the refcnt
* of the passed method.
*/
if (data->force_store || !no_store) {
/*
* If we haven't been told not to store,
* add to the global store
*/
if (!data->mcm->put(data->libctx, NULL,
thismap->property_definition,
method, data->mcm_data)) {
data->mcm->destruct(method);
continue;
}
data->mcm->put(data->libctx, NULL,
thismap->property_definition,
method, data->mcm_data);
}
if (!data->mcm->put(data->libctx, data->store,
thismap->property_definition,
method, data->mcm_data)) {
data->mcm->destruct(method);
continue;
}
data->mcm->put(data->libctx, data->store,
thismap->property_definition,
method, data->mcm_data);
/* refcnt-- because we're dropping the reference */
data->mcm->destruct(method, data->mcm_data);
}
return 1;
+5
View File
@@ -57,6 +57,11 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
"pkey_poly1305_init"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PKEY_SIPHASH_INIT, 0),
"pkey_siphash_init"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_ACTIVATE, 0),
"provider_activate"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_NEW, 0), "provider_new"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_STORE_NEW, 0),
"provider_store_new"},
{ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_SK_RESERVE, 0), "sk_reserve"},
{0, NULL}
};
+1 -1
View File
@@ -3,7 +3,7 @@
* Copyright Nokia 2007-2018
* Copyright Siemens AG 2015-2018
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+1 -1
View File
@@ -2,7 +2,7 @@
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+1 -1
View File
@@ -3,7 +3,7 @@
* Copyright Nokia 2007-2018
* Copyright Siemens AG 2015-2018
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+1 -1
View File
@@ -3,7 +3,7 @@
* Copyright Nokia 2007-2018
* Copyright Siemens AG 2015-2018
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+1 -1
View File
@@ -3,7 +3,7 @@
* Copyright Nokia 2007-2018
* Copyright Siemens AG 2015-2018
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
+11 -15
View File
@@ -12,6 +12,8 @@
#include <openssl/bn.h>
#include "dh_locl.h"
# define DH_NUMBER_ITERATIONS_FOR_PRIME 64
/*-
* Check that p and g are suitable enough
*
@@ -58,10 +60,8 @@ int DH_check_params(const DH *dh, int *ret)
ok = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
@@ -127,7 +127,7 @@ int DH_check(const DH *dh, int *ret)
if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR;
}
r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -155,7 +155,7 @@ int DH_check(const DH *dh, int *ret)
} else
*ret |= DH_UNABLE_TO_CHECK_GENERATOR;
r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -163,7 +163,7 @@ int DH_check(const DH *dh, int *ret)
else if (!dh->q) {
if (!BN_rshift1(t1, dh->p))
goto err;
r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
r = BN_is_prime_ex(t1, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
@@ -171,10 +171,8 @@ int DH_check(const DH *dh, int *ret)
}
ok = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
@@ -225,9 +223,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
ok = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
+2 -4
View File
@@ -122,9 +122,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
ok = 0;
}
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
+2 -4
View File
@@ -205,10 +205,8 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
ret = BN_bn2bin(tmp, key);
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ret;
}
+2
View File
@@ -458,6 +458,8 @@ static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
DSA_SIG_free(dsa_sig);
return rv;
}
if (BIO_puts(bp, "\n") <= 0)
return 0;
return X509_signature_dump(bp, sig, indent);
}
+2 -4
View File
@@ -292,8 +292,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
if (seed_out)
memcpy(seed_out, seed, qsize);
}
if (ctx)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
return ok;
@@ -607,8 +606,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
OPENSSL_free(seed);
if (seed_out != seed_tmp)
OPENSSL_free(seed_tmp);
if (ctx)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
EVP_MD_CTX_free(mctx);
+107 -1
View File
@@ -64,6 +64,7 @@ static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
static char *win32_name_converter(DSO *dso, const char *filename);
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int win32_pathbyaddr(void *addr, char *path, int sz);
static void *win32_globallookup(const char *name);
static const char *openssl_strnchr(const char *string, int c, size_t len);
@@ -78,7 +79,7 @@ static DSO_METHOD dso_meth_win32 = {
win32_merger,
NULL, /* init */
NULL, /* finish */
NULL, /* pathbyaddr */
win32_pathbyaddr, /* pathbyaddr */
win32_globallookup
};
@@ -500,6 +501,111 @@ typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
static int win32_pathbyaddr(void *addr, char *path, int sz)
{
HMODULE dll;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
CREATETOOLHELP32SNAPSHOT create_snap;
CLOSETOOLHELP32SNAPSHOT close_snap;
MODULE32 module_first, module_next;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
win32_pathbyaddr
};
addr = t.p;
}
dll = LoadLibrary(TEXT(DLLNAME));
if (dll == NULL) {
DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
return -1;
}
create_snap = (CREATETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CreateToolhelp32Snapshot");
if (create_snap == NULL) {
FreeLibrary(dll);
DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
return -1;
}
/* We take the rest for granted... */
# ifdef _WIN32_WCE
close_snap = (CLOSETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CloseToolhelp32Snapshot");
# else
close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
# endif
module_first = (MODULE32) GetProcAddress(dll, "Module32First");
module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
/*
* Take a snapshot of current process which includes
* list of all involved modules.
*/
hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
if (hModuleSnap == INVALID_HANDLE_VALUE) {
FreeLibrary(dll);
DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
return -1;
}
me32.dwSize = sizeof(me32);
if (!(*module_first) (hModuleSnap, &me32)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_FAILURE);
return -1;
}
/* Enumerate the modules to find one which includes me. */
do {
if ((uintptr_t) addr >= (uintptr_t) me32.modBaseAddr &&
(uintptr_t) addr < (uintptr_t) (me32.modBaseAddr + me32.modBaseSize)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
# ifdef _WIN32_WCE
# if _WIN32_WCE >= 101
return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
path, sz, NULL, NULL);
# else
{
int i, len = (int)wcslen(me32.szExePath);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
for (i = 0; i < len; i++)
path[i] = (char)me32.szExePath[i];
path[len++] = '\0';
return len;
}
# endif
# else
{
int len = (int)strlen(me32.szExePath);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
memcpy(path, me32.szExePath, len);
path[len++] = '\0';
return len;
}
# endif
}
} while ((*module_next) (hModuleSnap, &me32));
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return 0;
}
static void *win32_globallookup(const char *name)
{
HMODULE dll;
+5 -4
View File
@@ -237,7 +237,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
BN_CTX *ctx)
{
point_conversion_form_t form;
int y_bit;
int y_bit, m;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *yxi;
size_t field_len, enc_len;
@@ -270,7 +270,8 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
return EC_POINT_set_to_infinity(group, point);
}
field_len = (EC_GROUP_get_degree(group) + 7) / 8;
m = EC_GROUP_get_degree(group);
field_len = (m + 7) / 8;
enc_len =
(form ==
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
@@ -295,7 +296,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
if (!BN_bin2bn(buf + 1, field_len, x))
goto err;
if (BN_ucmp(x, group->field) >= 0) {
if (BN_num_bits(x) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
@@ -306,7 +307,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
goto err;
if (BN_ucmp(y, group->field) >= 0) {
if (BN_num_bits(y) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
+1 -2
View File
@@ -204,8 +204,7 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
+1 -2
View File
@@ -1079,8 +1079,7 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
+2 -3
View File
@@ -378,7 +378,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
err:
EC_POINT_free(p);
EC_POINT_free(s);
EC_POINT_clear_free(s);
BN_CTX_end(ctx);
return ret;
@@ -948,8 +948,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_ec_pre_comp_free(pre_comp);
if (points) {
+2 -3
View File
@@ -112,9 +112,8 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
ret = 1;
err:
EC_POINT_free(tmp);
if (ctx)
BN_CTX_end(ctx);
EC_POINT_clear_free(tmp);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_free(buf);
return ret;
+3 -1
View File
@@ -676,7 +676,9 @@ static void felem_contract(felem out, const felem in)
*/
static void felem_neg(felem out, const felem in)
{
widefelem tmp = {0};
widefelem tmp;
memset(tmp, 0, sizeof(tmp));
felem_diff_128_64(tmp, in);
felem_reduce(out, tmp);
}
+1 -2
View File
@@ -888,8 +888,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_nistz256_pre_comp_free(pre_comp);
+2 -4
View File
@@ -307,8 +307,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
@@ -787,8 +786,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
ret = 1;
end:
if (ctx) /* otherwise we already called BN_CTX_end */
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
+23 -26
View File
@@ -525,8 +525,24 @@ static unsigned long get_error_values(int inc, int top, const char **file,
return ERR_R_INTERNAL_ERROR;
}
while (es->bottom != es->top) {
if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
err_clear(es, es->top);
es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
continue;
}
i = (es->bottom + 1) % ERR_NUM_ERRORS;
if (es->err_flags[i] & ERR_FLAG_CLEAR) {
es->bottom = i;
err_clear(es, es->bottom);
continue;
}
break;
}
if (es->bottom == es->top)
return 0;
if (top)
i = es->top; /* last error */
else
@@ -915,25 +931,6 @@ int ERR_clear_last_mark(void)
return 1;
}
#ifdef UINTPTR_T
# undef UINTPTR_T
#endif
/*
* uintptr_t is the answer, but unfortunately C89, current "least common
* denominator" doesn't define it. Most legacy platforms typedef it anyway,
* so that attempt to fill the gaps means that one would have to identify
* that track these gaps, which would be undesirable. Macro it is...
*/
#if defined(__VMS) && __INITIAL_POINTER_SIZE==64
/*
* But we can't use size_t on VMS, because it adheres to sizeof(size_t)==4
* even in 64-bit builds, which means that it won't work as mask.
*/
# define UINTPTR_T unsigned long long
#else
# define UINTPTR_T size_t
#endif
void err_clear_last_constant_time(int clear)
{
ERR_STATE *es;
@@ -945,11 +942,11 @@ void err_clear_last_constant_time(int clear)
top = es->top;
es->err_flags[top] &= ~(0 - clear);
es->err_buffer[top] &= ~(0UL - clear);
es->err_file[top] = (const char *)((UINTPTR_T)es->err_file[top] &
~((UINTPTR_T)0 - clear));
es->err_line[top] |= 0 - clear;
es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
/*
* Flag error as cleared but remove it elsewhere to avoid two errors
* accessing the same error stack location, revealing timing information.
*/
clear = constant_time_select_int(constant_time_eq_int(clear, 0),
0, ERR_FLAG_CLEAR);
es->err_flags[top] |= clear;
}
+15 -3
View File
@@ -396,6 +396,9 @@ CRYPTO_F_OSSL_PROVIDER_NEW:131:ossl_provider_new
CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init
CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init
CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init
CRYPTO_F_PROVIDER_ACTIVATE:134:provider_activate
CRYPTO_F_PROVIDER_NEW:135:provider_new
CRYPTO_F_PROVIDER_STORE_NEW:136:provider_store_new
CRYPTO_F_SK_RESERVE:129:sk_reserve
CT_F_CTLOG_NEW:117:CTLOG_new
CT_F_CTLOG_NEW_FROM_BASE64:118:CTLOG_new_from_base64
@@ -778,7 +781,9 @@ EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1
EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex
EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate
EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
EVP_F_EVP_DIGESTFINAL_EX:230:EVP_DigestFinal_ex
EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
EVP_F_EVP_DIGESTUPDATE:231:EVP_DigestUpdate
EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
@@ -898,6 +903,11 @@ KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
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_CTRL_STR:134:sskdf_ctrl_str
KDF_F_SSKDF_DERIVE:135:sskdf_derive
KDF_F_SSKDF_MAC2CTRL:136:sskdf_mac2ctrl
KDF_F_SSKDF_NEW:137:sskdf_new
KDF_F_SSKDF_SIZE:138: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
@@ -1215,7 +1225,6 @@ SSL_F_DO_DTLS1_WRITE:245:do_dtls1_write
SSL_F_DO_SSL3_WRITE:104:do_ssl3_write
SSL_F_DTLS1_BUFFER_RECORD:247:dtls1_buffer_record
SSL_F_DTLS1_CHECK_TIMEOUT_NUM:318:dtls1_check_timeout_num
SSL_F_DTLS1_HEARTBEAT:305:*
SSL_F_DTLS1_HM_FRAGMENT_NEW:623:dtls1_hm_fragment_new
SSL_F_DTLS1_PREPROCESS_FRAGMENT:288:dtls1_preprocess_fragment
SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS:424:dtls1_process_buffered_records
@@ -2348,6 +2357,7 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
EVP_R_FINAL_ERROR:188:final error
EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
@@ -2366,6 +2376,7 @@ EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
EVP_R_METHOD_NOT_SUPPORTED:144:method not supported
EVP_R_MISSING_PARAMETERS:103:missing parameters
EVP_R_NOT_ABLE_TO_COPY_CTX:190:not able to copy ctx
EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
@@ -2399,9 +2410,11 @@ EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds
EVP_R_UNSUPPORTED_PRF:125:unsupported prf
EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm
EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type
EVP_R_UPDATE_ERROR:189:update error
EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
KDF_R_INVALID_DIGEST:100:invalid digest
KDF_R_INVALID_MAC_TYPE:116:invalid mac type
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
@@ -2414,6 +2427,7 @@ KDF_R_MISSING_SESSION_ID:113:missing session id
KDF_R_MISSING_TYPE:114:missing type
KDF_R_MISSING_XCGHASH:115:missing xcghash
KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
KDF_R_UNSUPPORTED_MAC_TYPE:117:unsupported mac type
KDF_R_VALUE_ERROR:108:value error
KDF_R_VALUE_MISSING:102:value missing
KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size
@@ -2961,8 +2975,6 @@ SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH:303:ssl session id has bad length
SSL_R_SSL_SESSION_ID_TOO_LONG:408:ssl session id too long
SSL_R_SSL_SESSION_VERSION_MISMATCH:210:ssl session version mismatch
SSL_R_STILL_IN_INIT:121:still in init
SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT:365:peer does not accept heartbeats
SSL_R_TLS_HEARTBEAT_PENDING:366:heartbeat request already pending
SSL_R_TLS_ILLEGAL_EXPORTER_LABEL:367:tls illegal exporter label
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST:157:tls invalid ecpointformat list
SSL_R_TOO_MANY_KEY_UPDATES:132:too many key updates
+4
View File
@@ -16,6 +16,10 @@ SOURCE[../../libcrypto]=\
e_chacha20_poly1305.c cmeth_lib.c \
mac_lib.c c_allm.c pkey_mac.c
# New design
SOURCE[../../libcrypto]=\
evp_fetch.c
INCLUDE[e_aes.o]=.. ../modes
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes
+292 -5
View File
@@ -13,6 +13,7 @@
#include <openssl/evp.h>
#include <openssl/engine.h>
#include "internal/evp_int.h"
#include "internal/provider.h"
#include "evp_locl.h"
/* This call frees resources associated with the context */
@@ -21,6 +22,24 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
if (ctx == NULL)
return 1;
if (ctx->digest == NULL || ctx->digest->prov == NULL)
goto legacy;
if (ctx->provctx != NULL) {
if (ctx->digest->freectx != NULL)
ctx->digest->freectx(ctx->provctx);
ctx->provctx = NULL;
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
if (ctx->pctx != NULL)
goto legacy;
return 1;
/* TODO(3.0): Remove legacy code below */
legacy:
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
@@ -53,6 +72,23 @@ EVP_MD_CTX *EVP_MD_CTX_new(void)
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->digest == NULL || ctx->digest->prov == NULL)
goto legacy;
EVP_MD_CTX_reset(ctx);
EVP_MD_meth_free(ctx->fetched_digest);
ctx->fetched_digest = NULL;
ctx->digest = NULL;
OPENSSL_free(ctx);
return;
/* TODO(3.0): Remove legacy code below */
legacy:
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
@@ -65,7 +101,12 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
EVP_MD *provmd;
ENGINE *tmpimpl = NULL;
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
/* TODO(3.0): Legacy work around code below. Remove this */
#ifndef OPENSSL_NO_ENGINE
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
@@ -76,6 +117,74 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
if (ctx->engine && ctx->digest &&
(type == NULL || (type->type == ctx->digest->type)))
goto skip_to_init;
if (type != NULL && impl == NULL)
tmpimpl = ENGINE_get_digest_engine(type->type);
#endif
/*
* If there are engines involved or if we're being used as part of
* EVP_DigestSignInit then we should use legacy handling for now.
*/
if (ctx->engine != NULL
|| impl != NULL
|| tmpimpl != NULL
|| ctx->pctx != NULL
|| (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
if (ctx->digest == ctx->fetched_digest)
ctx->digest = NULL;
EVP_MD_meth_free(ctx->fetched_digest);
ctx->fetched_digest = NULL;
goto legacy;
}
if (type->prov == NULL) {
switch(type->type) {
case NID_sha256:
break;
default:
goto legacy;
}
}
if (ctx->digest != NULL && ctx->digest->ctx_size > 0) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
ctx->md_data = NULL;
}
/* TODO(3.0): Start of non-legacy code below */
if (type->prov == NULL) {
provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
if (provmd == NULL) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
return 0;
}
type = provmd;
EVP_MD_meth_free(ctx->fetched_digest);
ctx->fetched_digest = provmd;
}
ctx->digest = type;
if (ctx->provctx == NULL) {
ctx->provctx = ctx->digest->newctx();
if (ctx->provctx == NULL) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
return 0;
}
}
if (ctx->digest->dinit == NULL) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
return 0;
}
return ctx->digest->dinit(ctx->provctx);
/* TODO(3.0): Remove legacy code below */
legacy:
#ifndef OPENSSL_NO_ENGINE
if (type) {
/*
* Ensure an ENGINE left lying around from last time is cleared (the
@@ -90,7 +199,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
}
} else {
/* Ask if an ENGINE is reserved for this job */
impl = ENGINE_get_digest_engine(type->type);
impl = tmpimpl;
}
if (impl != NULL) {
/* There's an ENGINE for this job ... (apparently) */
@@ -150,6 +259,20 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
if (count == 0)
return 1;
if (ctx->digest == NULL || ctx->digest->prov == NULL)
goto legacy;
if (ctx->digest->dupdate == NULL) {
EVPerr(EVP_F_EVP_DIGESTUPDATE, EVP_R_UPDATE_ERROR);
return 0;
}
return ctx->digest->dupdate(ctx->provctx, data, count);
/* TODO(3.0): Remove legacy code below */
legacy:
return ctx->update(ctx, data, count);
}
@@ -163,14 +286,40 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
}
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
{
int ret;
size_t size = 0;
if (ctx->digest == NULL || ctx->digest->prov == NULL)
goto legacy;
if (ctx->digest->dfinal == NULL) {
EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
return 0;
}
ret = ctx->digest->dfinal(ctx->provctx, md, &size);
if (isize != NULL) {
if (size <= UINT_MAX) {
*isize = (int)size;
} else {
EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
ret = 0;
}
}
EVP_MD_CTX_reset(ctx);
return ret;
/* TODO(3.0): Remove legacy code below */
legacy:
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret = ctx->digest->final(ctx, md);
if (size != NULL)
*size = ctx->digest->md_size;
if (isize != NULL)
*isize = ctx->digest->md_size;
if (ctx->digest->cleanup) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
@@ -209,10 +358,52 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
unsigned char *tmp_buf;
if ((in == NULL) || (in->digest == NULL)) {
if (in == NULL || in->digest == NULL) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED);
return 0;
}
if (in->digest->prov == NULL)
goto legacy;
if (in->digest->dupctx == NULL) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
return 0;
}
EVP_MD_CTX_reset(out);
if (out->fetched_digest != NULL)
EVP_MD_meth_free(out->fetched_digest);
*out = *in;
/* NULL out pointers in case of error */
out->pctx = NULL;
out->provctx = NULL;
if (in->fetched_digest != NULL)
EVP_MD_upref(in->fetched_digest);
out->provctx = in->digest->dupctx(in->provctx);
if (out->provctx == NULL) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
return 0;
}
/* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
if (in->pctx != NULL) {
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
if (out->pctx == NULL) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
EVP_MD_CTX_reset(out);
return 0;
}
}
return 1;
/* TODO(3.0): Remove legacy code below */
legacy:
#ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a digest context using an ENGINE */
if (in->engine && !ENGINE_init(in->engine)) {
@@ -296,3 +487,99 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
}
return 0;
}
static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov)
{
EVP_MD *md = NULL;
int fncnt = 0;
if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
return NULL;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_DIGEST_NEWCTX:
if (md->newctx != NULL)
break;
md->newctx = OSSL_get_OP_digest_newctx(fns);
fncnt++;
break;
case OSSL_FUNC_DIGEST_INIT:
if (md->dinit != NULL)
break;
md->dinit = OSSL_get_OP_digest_init(fns);
fncnt++;
break;
case OSSL_FUNC_DIGEST_UPDDATE:
if (md->dupdate != NULL)
break;
md->dupdate = OSSL_get_OP_digest_update(fns);
fncnt++;
break;
case OSSL_FUNC_DIGEST_FINAL:
if (md->dfinal != NULL)
break;
md->dfinal = OSSL_get_OP_digest_final(fns);
fncnt++;
break;
case OSSL_FUNC_DIGEST_DIGEST:
if (md->digest != NULL)
break;
md->digest = OSSL_get_OP_digest_digest(fns);
/* We don't increment fnct for this as it is stand alone */
break;
case OSSL_FUNC_DIGEST_FREECTX:
if (md->freectx != NULL)
break;
md->freectx = OSSL_get_OP_digest_freectx(fns);
fncnt++;
break;
case OSSL_FUNC_DIGEST_DUPCTX:
if (md->dupctx != NULL)
break;
md->dupctx = OSSL_get_OP_digest_dupctx(fns);
break;
case OSSL_FUNC_DIGEST_SIZE:
if (md->size != NULL)
break;
md->size = OSSL_get_OP_digest_size(fns);
break;
}
}
if ((fncnt != 0 && fncnt != 5)
|| (fncnt == 0 && md->digest == NULL)
|| md->size == NULL) {
/*
* In order to be a consistent set of functions we either need the
* whole set of init/update/final etc functions or none of them.
* The "digest" function can standalone. We at least need one way to
* generate digests.
*/
EVP_MD_meth_free(md);
return NULL;
}
md->prov = prov;
if (prov != NULL)
ossl_provider_upref(prov);
return md;
}
static int evp_md_upref(void *md)
{
return EVP_MD_upref(md);
}
static void evp_md_free(void *md)
{
EVP_MD_meth_free(md);
}
EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties)
{
return evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
evp_md_from_dispatch, evp_md_upref,
evp_md_free);
}
+13 -1
View File
@@ -486,6 +486,16 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 0;
}
static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx)
{
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx);
if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx))
OPENSSL_free(gctx->iv);
return 1;
}
static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
@@ -727,6 +737,8 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
}
#define aria_ccm_cleanup NULL
#define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
@@ -739,7 +751,7 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \
ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \
aria_##mode##_init_key, \
aria_##mode##_cipher, \
NULL, \
aria_##mode##_cleanup, \
sizeof(EVP_ARIA_##MODE##_CTX), \
NULL,NULL,aria_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
+6
View File
@@ -54,7 +54,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
"EVP_DecryptFinal_ex"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTUPDATE, 0), "EVP_DecryptUpdate"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINALXOF, 0), "EVP_DigestFinalXOF"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINAL_EX, 0), "EVP_DigestFinal_ex"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTINIT_EX, 0), "EVP_DigestInit_ex"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTUPDATE, 0), "EVP_DigestUpdate"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 0),
"evp_EncryptDecryptUpdate"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
@@ -219,6 +221,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"expecting a poly1305 key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY),
"expecting a siphash key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
"fips mode not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
@@ -246,6 +249,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED),
"method not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_ABLE_TO_COPY_CTX),
"not able to copy ctx"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH),
"not XOF or invalid length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
@@ -293,6 +298,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"unsupported private key algorithm"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE),
"unsupported salt type"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UPDATE_ERROR), "update error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED),
"wrap mode not allowed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH),
+197
View File
@@ -0,0 +1,197 @@
/*
* 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 <stddef.h>
#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#include <openssl/core.h>
#include "internal/cryptlib.h"
#include "internal/thread_once.h"
#include "internal/asn1_int.h"
#include "internal/property.h"
#include "internal/core.h"
#include "internal/evp_int.h" /* evp_locl.h needs it */
#include "evp_locl.h"
/* The OpenSSL library context index for the default method store */
static int default_method_store_index = -1;
static void default_method_store_free(void *vstore)
{
ossl_method_store_free(vstore);
}
static void *default_method_store_new(void)
{
return ossl_method_store_new();
}
static const OPENSSL_CTX_METHOD default_method_store_method = {
default_method_store_new,
default_method_store_free,
};
static int default_method_store_init(void)
{
default_method_store_index =
openssl_ctx_new_index(&default_method_store_method);
return default_method_store_index != -1;
}
static CRYPTO_ONCE default_method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_default_method_store_init)
{
return OPENSSL_init_crypto(0, NULL)
&& default_method_store_init();
}
/* Data to be passed through ossl_method_construct() */
struct method_data_st {
const char *name;
int nid;
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
void *(*method_from_dispatch)(int nid, const OSSL_DISPATCH *,
OSSL_PROVIDER *);
int (*refcnt_up_method)(void *method);
void (*destruct_method)(void *method);
};
/*
* Generic routines to fetch / create EVP methods with ossl_method_construct()
*/
static void *alloc_tmp_method_store(void)
{
return ossl_method_store_new();
}
static void dealloc_tmp_method_store(void *store)
{
if (store != NULL)
ossl_method_store_free(store);
}
static
struct OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)
{
if (!RUN_ONCE(&default_method_store_init_flag,
do_default_method_store_init))
return NULL;
return openssl_ctx_get_data(libctx, default_method_store_index);
}
static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
const char *propquery, void *data)
{
struct method_data_st *methdata = data;
void *method = NULL;
if (store == NULL
&& (store = get_default_method_store(libctx)) == NULL)
return NULL;
(void)ossl_method_store_fetch(store, methdata->nid, propquery, &method);
if (method != NULL
&& !methdata->refcnt_up_method(method)) {
method = NULL;
}
return method;
}
static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
const char *propdef, void *method,
void *data)
{
struct method_data_st *methdata = data;
if (store == NULL
&& (store = get_default_method_store(libctx)) == NULL)
return 0;
if (methdata->refcnt_up_method(method)
&& ossl_method_store_add(store, methdata->nid, propdef, method,
methdata->destruct_method))
return 1;
return 0;
}
static void *construct_method(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
void *data)
{
struct method_data_st *methdata = data;
void *method = NULL;
if (methdata->nid == NID_undef) {
/* Create a new NID for that name on the fly */
ASN1_OBJECT tmpobj;
/* This is the same as OBJ_create() but without requiring a OID */
tmpobj.nid = OBJ_new_nid(1);
tmpobj.sn = tmpobj.ln = methdata->name;
tmpobj.flags = ASN1_OBJECT_FLAG_DYNAMIC;
tmpobj.length = 0;
tmpobj.data = NULL;
methdata->nid = OBJ_add_object(&tmpobj);
}
if (methdata->nid == NID_undef)
return NULL;
method = methdata->method_from_dispatch(methdata->nid, fns, prov);
if (method == NULL)
return NULL;
return method;
}
static void destruct_method(void *method, void *data)
{
struct method_data_st *methdata = data;
methdata->destruct_method(method);
}
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
const char *algorithm, const char *properties,
void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov),
int (*upref_method)(void *),
void (*free_method)(void *))
{
int nid = OBJ_sn2nid(algorithm);
void *method = NULL;
if (nid == NID_undef
|| !ossl_method_store_cache_get(NULL, nid, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
alloc_tmp_method_store,
dealloc_tmp_method_store,
get_method_from_store,
put_method_in_store,
construct_method,
destruct_method
};
struct method_data_st mcmdata;
mcmdata.nid = nid;
mcmdata.mcm = &mcm;
mcmdata.method_from_dispatch = new_method;
mcmdata.destruct_method = free_method;
mcmdata.refcnt_up_method = upref_method;
mcmdata.destruct_method = free_method;
method = ossl_method_construct(libctx, operation_id, algorithm,
properties, 0 /* !force_cache */,
&mcm, &mcmdata);
ossl_method_store_cache_set(NULL, nid, properties, method);
}
return method;
}
+30 -1
View File
@@ -12,6 +12,7 @@
#include <openssl/evp.h>
#include <openssl/objects.h>
#include "internal/evp_int.h"
#include "internal/provider.h"
#include "evp_locl.h"
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
@@ -316,6 +317,10 @@ int EVP_MD_size(const EVP_MD *md)
EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL);
return -1;
}
if (md->prov != NULL && md->size != NULL)
return (int)md->size();
return md->md_size;
}
@@ -331,6 +336,12 @@ EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
if (md != NULL) {
md->type = md_type;
md->pkey_type = pkey_type;
md->lock = CRYPTO_THREAD_lock_new();
if (md->lock == NULL) {
OPENSSL_free(md);
return NULL;
}
md->refcnt = 1;
}
return md;
}
@@ -342,9 +353,27 @@ EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
memcpy(to, md, sizeof(*to));
return to;
}
int EVP_MD_upref(EVP_MD *md)
{
int ref = 0;
CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
return 1;
}
void EVP_MD_meth_free(EVP_MD *md)
{
OPENSSL_free(md);
if (md != NULL) {
int i;
CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
if (i > 0)
return;
ossl_provider_free(md->prov);
CRYPTO_THREAD_lock_free(md->lock);
OPENSSL_free(md);
}
}
int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize)
{
+15 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2000-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
@@ -19,6 +19,10 @@ struct evp_md_ctx_st {
EVP_PKEY_CTX *pctx;
/* Update function: usually copied from EVP_MD */
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
/* Provider ctx */
void *provctx;
EVP_MD *fetched_digest;
} /* EVP_MD_CTX */ ;
struct evp_cipher_ctx_st {
@@ -76,3 +80,13 @@ typedef struct evp_pbe_st EVP_PBE_CTL;
DEFINE_STACK_OF(EVP_PBE_CTL)
int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
#include <openssl/ossl_typ.h>
#include <openssl/core.h>
void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
const char *algorithm, const char *properties,
void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov),
int (*upref_method)(void *),
void (*free_method)(void *));
+1
View File
@@ -31,6 +31,7 @@ static const EVP_KDF_METHOD *standard_methods[] = {
&tls1_prf_kdf_meth,
&hkdf_kdf_meth,
&sshkdf_kdf_meth,
&ss_kdf_meth
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
+2
View File
@@ -82,6 +82,8 @@ int EVP_MAC_init(EVP_MAC_CTX *ctx)
int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
{
if (datalen == 0)
return 1;
return ctx->meth->update(ctx->data, data, datalen);
}
+5
View File
@@ -396,6 +396,11 @@ int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
pkey->pmeth_engine = e;
return 1;
}
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
{
return pkey->engine;
}
#endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
+4
View File
@@ -52,6 +52,10 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
pass = empty;
passlen = 0;
}
if (salt == NULL) {
salt = (const unsigned char *)empty;
saltlen = 0;
}
if (maxmem == 0)
maxmem = SCRYPT_MAX_MEM;
+6 -6
View File
@@ -231,9 +231,9 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
int rv;
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
ctx->engine)) < 0
ctx->engine)) <= 0
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
p2)) < 0
p2)) <= 0
|| !(rv = EVP_MAC_init(hctx->ctx)))
return rv;
}
@@ -275,7 +275,7 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 0;
break;
case MAC_TYPE_MAC:
if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
if (EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1) <= 0)
return 0;
break;
default:
@@ -296,11 +296,11 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
(ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
ctx->engine)) < 0
ctx->engine)) <= 0
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
hctx->raw_data.md)) < 0
hctx->raw_data.md)) <= 0
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
key->data, key->length)) < 0)
key->data, key->length)) <= 0)
return rv;
}
break;
+7
View File
@@ -35,6 +35,13 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
return 0;
}
/*
* The HMAC construction is not allowed to be used with the
* extendable-output functions (XOF) shake128 and shake256.
*/
if ((EVP_MD_meth_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
return 0;
if (key != NULL) {
reset = 1;
j = EVP_MD_block_size(md);
-4
View File
@@ -110,8 +110,4 @@ int bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
const BIGNUM *r1, const BIGNUM *r2, int nlen,
const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
#ifdef __cplusplus
}
#endif
#endif
+21
View File
@@ -8,6 +8,7 @@
*/
#include <openssl/evp.h>
#include <openssl/core_numbers.h>
#include "internal/refcount.h"
/*
@@ -169,9 +170,14 @@ extern const EVP_KDF_METHOD scrypt_kdf_meth;
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 ss_kdf_meth;
struct evp_md_st {
/* nid */
int type;
/* Legacy structure members */
/* TODO(3.0): Remove these */
int pkey_type;
int md_size;
unsigned long flags;
@@ -184,6 +190,21 @@ struct evp_md_st {
int ctx_size; /* how big does the ctx->md_data need to be */
/* control function */
int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
/* New structure members */
/* TODO(3.0): Remove above comment when legacy has gone */
OSSL_PROVIDER *prov;
CRYPTO_REF_COUNT refcnt;
CRYPTO_RWLOCK *lock;
OSSL_OP_digest_newctx_fn *newctx;
OSSL_OP_digest_init_fn *dinit;
OSSL_OP_digest_update_fn *dupdate;
OSSL_OP_digest_final_fn *dfinal;
OSSL_OP_digest_digest_fn *digest;
OSSL_OP_digest_freectx_fn *freectx;
OSSL_OP_digest_dupctx_fn *dupctx;
OSSL_OP_digest_size_fn *size;
} /* EVP_MD */ ;
struct evp_cipher_st {
+8
View File
@@ -49,6 +49,14 @@ size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout);
void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out);
/* CRNG test entropy filter callbacks. */
size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len,
int prediction_resistance);
void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
/*
* RAND_POOL functions
*/
+2 -2
View File
@@ -163,7 +163,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
#if !defined(OPENSSL_NO_DSO) \
&& !defined(OPENSSL_USE_NODELETE) \
&& !defined(OPENSSL_NO_PINSHARED)
# ifdef DSO_WIN32
# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
@@ -743,7 +743,7 @@ int OPENSSL_atexit(void (*handler)(void))
} handlersym;
handlersym.func = handler;
# ifdef DSO_WIN32
# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
+2 -1
View File
@@ -1,3 +1,4 @@
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 \
sskdf.c
+8
View File
@@ -59,12 +59,18 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
"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_CTRL_STR, 0), "sskdf_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_DERIVE, 0), "sskdf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_MAC2CTRL, 0), "sskdf_mac2ctrl"},
{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_INVALID_DIGEST), "invalid digest"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_MAC_TYPE), "invalid mac type"},
{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"},
@@ -80,6 +86,8 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_XCGHASH), "missing xcghash"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE),
"unknown parameter type"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNSUPPORTED_MAC_TYPE),
"unsupported mac 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_OUTPUT_BUFFER_SIZE),
+484
View File
@@ -0,0 +1,484 @@
/*
* 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.
* 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 <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "kdf_local.h"
struct evp_kdf_impl_st {
const EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */
const EVP_MD *md; /* H(x) = hash OR when H(x) = HMAC_hash */
unsigned char *secret;
size_t secret_len;
unsigned char *info;
size_t info_len;
unsigned char *salt;
size_t salt_len;
size_t out_len; /* optional KMAC parameter */
};
#define SSKDF_MAX_INLEN (1<<30)
#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4)
#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4)
/* KMAC uses a Customisation string of 'KDF' */
static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
/*
* 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 int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
size_t custom_len, size_t kmac_out_len,
size_t derived_key_len, unsigned char **out)
{
/* Only KMAC has custom data - so return if not KMAC */
if (custom == NULL)
return 1;
if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, custom, custom_len) <= 0)
return 0;
/* By default only do one iteration if kmac_out_len is not specified */
if (kmac_out_len == 0)
kmac_out_len = derived_key_len;
/* otherwise check the size is valid */
else if (!(kmac_out_len == derived_key_len
|| kmac_out_len == 20
|| kmac_out_len == 28
|| kmac_out_len == 32
|| kmac_out_len == 48
|| kmac_out_len == 64))
return 0;
if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SIZE, kmac_out_len) <= 0)
return 0;
/*
* For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so
* alloc a buffer for this case.
*/
if (kmac_out_len > EVP_MAX_MD_SIZE) {
*out = OPENSSL_zalloc(kmac_out_len);
if (*out == NULL)
return 0;
}
return 1;
}
/*
* Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
* Section 4. One-Step Key Derivation using MAC: i.e either
* H(x) = HMAC-hash(salt, x) OR
* H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
*/
static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
const unsigned char *kmac_custom,
size_t kmac_custom_len, size_t kmac_out_len,
const unsigned char *salt, size_t salt_len,
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;
size_t counter, out_len, len;
unsigned char c[4];
unsigned char mac_buf[EVP_MAX_MD_SIZE];
unsigned char *out = derived_key;
EVP_MAC_CTX *ctx = NULL, *ctx_init = NULL;
unsigned char *mac = mac_buf, *kmac_buffer = NULL;
if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
|| derived_key_len > SSKDF_MAX_INLEN
|| derived_key_len == 0)
return 0;
ctx = EVP_MAC_CTX_new(kdf_mac);
ctx_init = EVP_MAC_CTX_new(kdf_mac);
if (ctx == NULL || ctx_init == NULL)
goto end;
if (hmac_md != NULL &&
EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, hmac_md) <= 0)
goto end;
if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, salt, salt_len) <= 0)
goto end;
if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
derived_key_len, &kmac_buffer))
goto end;
if (kmac_buffer != NULL)
mac = kmac_buffer;
if (!EVP_MAC_init(ctx_init))
goto end;
out_len = EVP_MAC_size(ctx_init); /* output size */
if (out_len <= 0)
goto end;
len = derived_key_len;
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_MAC_CTX_copy(ctx, ctx_init)
&& EVP_MAC_update(ctx, c, sizeof(c))
&& EVP_MAC_update(ctx, z, z_len)
&& EVP_MAC_update(ctx, info, info_len)))
goto end;
if (len >= out_len) {
if (!EVP_MAC_final(ctx, out, NULL))
goto end;
out += out_len;
len -= out_len;
if (len == 0)
break;
} else {
if (!EVP_MAC_final(ctx, mac, NULL))
goto end;
memcpy(out, mac, len);
break;
}
}
ret = 1;
end:
if (kmac_buffer != NULL)
OPENSSL_clear_free(kmac_buffer, kmac_out_len);
else
OPENSSL_cleanse(mac_buf, sizeof(mac_buf));
EVP_MAC_CTX_free(ctx);
EVP_MAC_CTX_free(ctx_init);
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);
OPENSSL_clear_free(impl->salt, impl->salt_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);
if (len == 0 || p == NULL)
return 1;
OPENSSL_free(*out);
*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;
const EVP_MAC *mac;
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;
case EVP_KDF_CTRL_SET_MAC:
mac = va_arg(args, const EVP_MAC *);
if (mac == NULL)
return 0;
impl->mac = mac;
return 1;
case EVP_KDF_CTRL_SET_SALT:
return sskdf_set_buffer(args, &impl->salt, &impl->salt_len);
case EVP_KDF_CTRL_SET_MAC_SIZE:
impl->out_len = va_arg(args, size_t);
return 1;
default:
return -2;
}
}
/* Pass a mac to a ctrl */
static int sskdf_mac2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *mac_name)
{
const EVP_MAC *mac;
if (mac_name == NULL || (mac = EVP_get_macbyname(mac_name)) == NULL) {
KDFerr(KDF_F_SSKDF_MAC2CTRL, KDF_R_INVALID_MAC_TYPE);
return 0;
}
return call_ctrl(ctrl, impl, cmd, mac);
}
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);
if (strcmp(type, "mac") == 0)
return sskdf_mac2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value);
if (strcmp(type, "salt") == 0)
return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "hexsalt") == 0)
return kdf_hex2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "maclen") == 0) {
int val = atoi(value);
if (val < 0) {
KDFerr(KDF_F_SSKDF_CTRL_STR, KDF_R_VALUE_ERROR);
return 0;
}
return call_ctrl(sskdf_ctrl, impl, EVP_KDF_CTRL_SET_MAC_SIZE,
(size_t)val);
}
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;
}
if (impl->mac != NULL) {
/* H(x) = KMAC or H(x) = HMAC */
int ret;
const unsigned char *custom = NULL;
size_t custom_len = 0;
int nid;
int default_salt_len;
nid = EVP_MAC_nid(impl->mac);
if (nid == EVP_MAC_HMAC) {
/* H(x) = HMAC(x, salt, hash) */
if (impl->md == NULL) {
KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
default_salt_len = EVP_MD_block_size(impl->md);
if (default_salt_len <= 0)
return 0;
} else if (nid == EVP_MAC_KMAC128 || nid == EVP_MAC_KMAC256) {
/* H(x) = KMACzzz(x, salt, custom) */
custom = kmac_custom_str;
custom_len = sizeof(kmac_custom_str);
if (nid == EVP_MAC_KMAC128)
default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
else
default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;
} else {
KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_UNSUPPORTED_MAC_TYPE);
return 0;
}
/* If no salt is set then use a default_salt of zeros */
if (impl->salt == NULL || impl->salt_len <= 0) {
impl->salt = OPENSSL_zalloc(default_salt_len);
if (impl->salt == NULL) {
KDFerr(KDF_F_SSKDF_DERIVE, ERR_R_MALLOC_FAILURE);
return 0;
}
impl->salt_len = default_salt_len;
}
ret = SSKDF_mac_kdm(impl->mac, impl->md,
custom, custom_len, impl->out_len,
impl->salt, impl->salt_len,
impl->secret, impl->secret_len,
impl->info, impl->info_len, key, keylen);
return ret;
} else {
/* 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
};
+1 -1
View File
@@ -11,7 +11,7 @@
# define __MIPS_ARCH_H__
# if (defined(__mips_smartmips) || defined(_MIPS_ARCH_MIPS32R3) || \
defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6))
defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) \
&& !defined(_MIPS_ARCH_MIPS32R2)
# define _MIPS_ARCH_MIPS32R2
# endif
+2 -2
View File
@@ -166,8 +166,8 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
|| (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL
|| (ctx->mac_ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_CMAC)) == NULL
|| (ctx->mac_ctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC)) == NULL
|| !EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_CIPHER, cbc)
|| !EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_KEY, key, klen)
|| EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_CIPHER, cbc) <= 0
|| EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_KEY, key, klen) <= 0
|| !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL)
|| !EVP_MAC_CTX_copy(ctx->mac_ctx, ctx->mac_ctx_init)
|| !EVP_MAC_update(ctx->mac_ctx, zero, sizeof(zero))
+8 -5
View File
@@ -1080,7 +1080,7 @@ static const unsigned char so[7775] = {
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7766] OBJ_SM2_with_SM3 */
};
#define NUM_NID 1206
#define NUM_NID 1207
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2287,10 +2287,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"BLAKE2SMAC", "blake2smac", NID_blake2smac},
{"SSHKDF", "sshkdf", NID_sshkdf},
{"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7766]},
{"SSKDF", "sskdf", NID_sskdf},
{"ChaCha20-Poly1305-D", "chacha20-poly1305-draft", NID_chacha20_poly1305_draft},
};
#define NUM_SN 1197
#define NUM_SN 1198
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@@ -2413,7 +2414,7 @@ static const unsigned int sn_objs[NUM_SN] = {
417, /* "CSPName" */
1019, /* "ChaCha20" */
1018, /* "ChaCha20-Poly1305" */
1205, /* "ChaCha20-Poly1305-D" */
1206, /* "ChaCha20-Poly1305-D" */
367, /* "CrlID" */
391, /* "DC" */
31, /* "DES-CBC" */
@@ -2579,6 +2580,7 @@ static const unsigned int sn_objs[NUM_SN] = {
100, /* "SN" */
1006, /* "SNILS" */
1203, /* "SSHKDF" */
1205, /* "SSKDF" */
16, /* "ST" */
143, /* "SXNetID" */
1062, /* "SipHash" */
@@ -3491,7 +3493,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
#define NUM_LN 1197
#define NUM_LN 1198
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@@ -3876,7 +3878,7 @@ static const unsigned int ln_objs[NUM_LN] = {
883, /* "certificateRevocationList" */
1019, /* "chacha20" */
1018, /* "chacha20-poly1305" */
1205, /* "chacha20-poly1305-draft" */
1206, /* "chacha20-poly1305-draft" */
54, /* "challengePassword" */
407, /* "characteristic-two-field" */
395, /* "clearance" */
@@ -4644,6 +4646,7 @@ static const unsigned int ln_objs[NUM_LN] = {
1133, /* "sm4-ecb" */
1135, /* "sm4-ofb" */
1203, /* "sshkdf" */
1205, /* "sskdf" */
16, /* "stateOrProvinceName" */
660, /* "streetAddress" */
498, /* "subtreeMaximumQuality" */
+2 -1
View File
@@ -1202,4 +1202,5 @@ blake2bmac 1201
blake2smac 1202
sshkdf 1203
SM2_with_SM3 1204
chacha20_poly1305_draft 1205
sskdf 1205
chacha20_poly1305_draft 1206
+3
View File
@@ -1615,6 +1615,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
# NID for SSHKDF
: SSHKDF : sshkdf
# NID for SSKDF
: SSKDF : sskdf
# RFC 4556
1 3 6 1 5 2 3 : id-pkinit
id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth
+2 -2
View File
@@ -88,7 +88,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
return NULL;
}
int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm);
@@ -100,7 +100,7 @@ int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash);
}
int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OCSP_id_issuer_cmp(a, b);
+30 -175
View File
@@ -41,50 +41,22 @@ static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
{
if (val == NULL || p == NULL || p->data_type != OSSL_PARAM_INTEGER)
return 0;
switch (p->data_size) {
switch (sizeof(int)) {
case sizeof(int32_t):
if (sizeof(int) >= sizeof(int32_t)) {
*val = (int)*(const int32_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_int32(p, (int32_t *)val);
case sizeof(int64_t):
if (sizeof(int) >= sizeof(int64_t)) {
*val = (int)*(const int64_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_int64(p, (int64_t *)val);
}
return 0;
}
int OSSL_PARAM_set_int(const OSSL_PARAM *p, int val)
{
if (p == NULL)
return 0;
SET_RETURN_SIZE(p, 0);
if (p->data_type != OSSL_PARAM_INTEGER)
return 0;
SET_RETURN_SIZE(p, sizeof(int)); /* Minimum expected size */
switch (p->data_size) {
switch (sizeof(int)) {
case sizeof(int32_t):
if (sizeof(int32_t) >= sizeof(int)) {
SET_RETURN_SIZE(p, sizeof(int32_t));
*(int32_t *)p->data = (int32_t)val;
return 1;
}
break;
return OSSL_PARAM_set_int32(p, (int32_t)val);
case sizeof(int64_t):
if (sizeof(int64_t) >= sizeof(int)) {
SET_RETURN_SIZE(p, sizeof(int64_t));
*(int64_t *)p->data = (int64_t)val;
return 1;
}
break;
return OSSL_PARAM_set_int64(p, (int64_t)val);
}
return 0;
}
@@ -97,52 +69,22 @@ OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf, size_t *rsize)
int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
{
if (val == NULL
|| p == NULL
|| (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
return 0;
switch (p->data_size) {
switch (sizeof(unsigned int)) {
case sizeof(uint32_t):
if (sizeof(unsigned int) >= sizeof(uint32_t)) {
*val = (unsigned int)*(const uint32_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
case sizeof(uint64_t):
if (sizeof(unsigned int) >= sizeof(uint64_t)) {
*val = (unsigned int)*(const uint64_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
}
return 0;
}
int OSSL_PARAM_set_uint(const OSSL_PARAM *p, unsigned int val)
{
if (p == NULL)
return 0;
SET_RETURN_SIZE(p, 0);
if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
SET_RETURN_SIZE(p, sizeof(unsigned int)); /* Minimum expected size */
switch (p->data_size) {
switch (sizeof(unsigned int)) {
case sizeof(uint32_t):
if (sizeof(uint32_t) >= sizeof(unsigned int)) {
SET_RETURN_SIZE(p, sizeof(uint32_t));
*(uint32_t *)p->data = (uint32_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint32(p, (uint32_t)val);
case sizeof(uint64_t):
if (sizeof(uint64_t) >= sizeof(unsigned int)) {
SET_RETURN_SIZE(p, sizeof(uint64_t));
*(uint64_t *)p->data = (uint64_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint64(p, (uint64_t)val);
}
return 0;
}
@@ -156,49 +98,22 @@ OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf,
int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
{
if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
return 0;
switch (p->data_size) {
switch (sizeof(long int)) {
case sizeof(int32_t):
if (sizeof(long int) >= sizeof(int32_t)) {
*val = (long int)*(const int32_t *)p->data;
return 1;
} break;
return OSSL_PARAM_get_int32(p, (int32_t *)val);
case sizeof(int64_t):
if (sizeof(long int) >= sizeof(int64_t)) {
*val = (long int)*(const int64_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_int64(p, (int64_t *)val);
}
return 0;
}
int OSSL_PARAM_set_long(const OSSL_PARAM *p, long int val)
{
if (p == NULL)
return 0;
SET_RETURN_SIZE(p, 0);
if (p->data_type != OSSL_PARAM_INTEGER)
return 0;
SET_RETURN_SIZE(p, sizeof(long int)); /* Minimum expected size */
switch (p->data_size) {
switch (sizeof(long int)) {
case sizeof(int32_t):
if (sizeof(int32_t) >= sizeof(long int)) {
SET_RETURN_SIZE(p, sizeof(int32_t));
*(int32_t *)p->data = (int32_t)val;
return 1;
}
break;
return OSSL_PARAM_set_int32(p, (int32_t)val);
case sizeof(int64_t):
if (sizeof(int64_t) >= sizeof(long int)) {
SET_RETURN_SIZE(p, sizeof(int64_t));
*(int64_t *)p->data = (int64_t)val;
return 1;
}
break;
return OSSL_PARAM_set_int64(p, (int64_t)val);
}
return 0;
}
@@ -212,52 +127,22 @@ OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf,
int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
{
if (val == NULL
|| p == NULL
|| (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
return 0;
switch (p->data_size) {
switch (sizeof(unsigned long int)) {
case sizeof(uint32_t):
if (sizeof(unsigned long int) >= sizeof(uint32_t)) {
*val = (unsigned long int)*(const uint32_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
case sizeof(uint64_t):
if (sizeof(unsigned long int) >= sizeof(uint64_t)) {
*val = (unsigned long int)*(const uint64_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
}
return 0;
}
int OSSL_PARAM_set_ulong(const OSSL_PARAM *p, unsigned long int val)
{
if (p == NULL)
return 0;
SET_RETURN_SIZE(p, 0);
if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
SET_RETURN_SIZE(p, sizeof(unsigned long int)); /* Minimum exp size */
switch (p->data_size) {
switch (sizeof(unsigned long int)) {
case sizeof(uint32_t):
if (sizeof(uint32_t) >= sizeof(unsigned long int)) {
SET_RETURN_SIZE(p, sizeof(uint32_t));
*(uint32_t *)p->data = (uint32_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint32(p, (uint32_t)val);
case sizeof(uint64_t):
if (sizeof(uint64_t) >= sizeof(unsigned long int)) {
SET_RETURN_SIZE(p, sizeof(uint64_t));
*(uint64_t *)p->data = (uint64_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint64(p, (uint64_t)val);
}
return 0;
}
@@ -437,52 +322,22 @@ OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf,
int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
{
if (val == NULL
|| p == NULL
|| p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
switch (p->data_size) {
switch (sizeof(size_t)) {
case sizeof(uint32_t):
if (sizeof(size_t) >= sizeof(uint32_t)) {
*val = (size_t)*(const uint32_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
case sizeof(uint64_t):
if (sizeof(size_t) >= sizeof(uint64_t)) {
*val = (size_t)*(const uint64_t *)p->data;
return 1;
}
break;
return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
}
return 0;
}
int OSSL_PARAM_set_size_t(const OSSL_PARAM *p, size_t val)
{
if (p == NULL)
return 0;
SET_RETURN_SIZE(p, 0);
if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
return 0;
SET_RETURN_SIZE(p, sizeof(size_t)); /* Minimum expected size */
switch (p->data_size) {
switch (sizeof(size_t)) {
case sizeof(uint32_t):
if (sizeof(uint32_t) >= sizeof(size_t)) {
SET_RETURN_SIZE(p, sizeof(uint32_t));
*(uint32_t *)p->data = (uint32_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint32(p, (uint32_t)val);
case sizeof(uint64_t):
SET_RETURN_SIZE(p, sizeof(uint64_t));
if (sizeof(uint64_t) >= sizeof(size_t)) {
*(uint64_t *)p->data = (uint64_t)val;
return 1;
}
break;
return OSSL_PARAM_set_uint64(p, (uint64_t)val);
}
return 0;
}
+365
View File
@@ -0,0 +1,365 @@
// ====================================================================
// Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
// project.
// ====================================================================
//
// Poly1305 for Itanium.
//
// January 2019
//
// Performance was reported to be ~2.1 cycles per byte on Itanium 2.
// With exception for processors in 95xx family, which have higher
// floating-point instructions' latencies and deliver ~2.6 cpb.
// Comparison to compiler-generated code is not exactly fair, because
// of different radixes. But just for reference, it was observed to be
// >3x faster. Originally it was argued that floating-point base 2^32
// implementation would be optimal. Upon closer look estimate for below
// integer base 2^64 implementation turned to be approximately same on
// Itanium 2. But floating-point code would be larger, and have higher
// overhead, which would negatively affect small-block performance...
#if defined(_HPUX_SOURCE)
# if !defined(_LP64)
# define ADDP addp4
# else
# define ADDP add
# endif
# define RUM rum
# define SUM sum
#else
# define ADDP add
# define RUM nop
# define SUM nop
#endif
.text
.explicit
.global poly1305_init#
.proc poly1305_init#
.align 64
poly1305_init:
.prologue
.save ar.pfs,r2
{ .mmi; alloc r2=ar.pfs,2,0,0,0
cmp.eq p6,p7=0,r33 } // key == NULL?
{ .mmi; ADDP r9=8,r32
ADDP r10=16,r32
ADDP r32=0,r32 };;
.body
{ .mmi; st8 [r32]=r0,24 // ctx->h0 = 0
st8 [r9]=r0 // ctx->h1 = 0
(p7) ADDP r8=0,r33 }
{ .mib; st8 [r10]=r0 // ctx->h2 = 0
(p6) mov r8=0
(p6) br.ret.spnt b0 };;
{ .mmi; ADDP r9=1,r33
ADDP r10=2,r33
ADDP r11=3,r33 };;
{ .mmi; ld1 r16=[r8],4 // load key, little-endian
ld1 r17=[r9],4 }
{ .mmi; ld1 r18=[r10],4
ld1 r19=[r11],4 };;
{ .mmi; ld1 r20=[r8],4
ld1 r21=[r9],4 }
{ .mmi; ld1 r22=[r10],4
ld1 r23=[r11],4
and r19=15,r19 };;
{ .mmi; ld1 r24=[r8],4
ld1 r25=[r9],4
and r20=-4,r20 }
{ .mmi; ld1 r26=[r10],4
ld1 r27=[r11],4
and r23=15,r23 };;
{ .mmi; ld1 r28=[r8],4
ld1 r29=[r9],4
and r24=-4,r24 }
{ .mmi; ld1 r30=[r10],4
ld1 r31=[r11],4
and r27=15,r27 };;
{ .mii; and r28=-4,r28
dep r16=r17,r16,8,8
dep r18=r19,r18,8,8 };;
{ .mii; and r31=15,r31
dep r16=r18,r16,16,16
dep r20=r21,r20,8,8 };;
{ .mii; dep r16=r20,r16,32,16
dep r22=r23,r22,8,8 };;
{ .mii; dep r16=r22,r16,48,16
dep r24=r25,r24,8,8 };;
{ .mii; dep r26=r27,r26,8,8
dep r28=r29,r28,8,8 };;
{ .mii; dep r24=r26,r24,16,16
dep r30=r31,r30,8,8 };;
{ .mii; st8 [r32]=r16,8 // ctx->r0
dep r24=r28,r24,32,16;;
dep r24=r30,r24,48,16 };;
{ .mii; st8 [r32]=r24,8 // ctx->r1
shr.u r25=r24,2;;
add r25=r25,r24 };;
{ .mib; st8 [r32]=r25 // ctx->s1
mov r8=0
br.ret.sptk b0 };;
.endp poly1305_init#
h0=r17; h1=r18; h2=r19;
i0=r20; i1=r21;
HF0=f8; HF1=f9; HF2=f10;
RF0=f11; RF1=f12; SF1=f13;
.global poly1305_blocks#
.proc poly1305_blocks#
.align 64
poly1305_blocks:
.prologue
.save ar.pfs,r2
{ .mii; alloc r2=ar.pfs,4,1,0,0
.save ar.lc,r3
mov r3=ar.lc
.save pr,r36
mov r36=pr }
.body
{ .mmi; ADDP r8=0,r32
ADDP r9=8,r32
and r29=7,r33 };;
{ .mmi; ld8 h0=[r8],16
ld8 h1=[r9],16
and r33=-8,r33 };;
{ .mmi; ld8 h2=[r8],16
ldf8 RF0=[r9],16
shr.u r34=r34,4 };;
{ .mmi; ldf8 RF1=[r8],-32
ldf8 SF1=[r9],-32
cmp.ltu p16,p17=1,r34 };;
{ .mmi;
(p16) add r34=-2,r34
(p17) mov r34=0
ADDP r10=0,r33 }
{ .mii; ADDP r11=8,r33
(p16) mov ar.ec=2
(p17) mov ar.ec=1 };;
{ .mib; RUM 1<<1 // go little-endian
mov ar.lc=r34
brp.loop.imp .Loop,.Lcend-16 }
{ .mmi; cmp.eq p8,p7=0,r29
cmp.eq p9,p0=1,r29
cmp.eq p10,p0=2,r29 }
{ .mmi; cmp.eq p11,p0=3,r29
cmp.eq p12,p0=4,r29
cmp.eq p13,p0=5,r29 }
{ .mmi; cmp.eq p14,p0=6,r29
cmp.eq p15,p0=7,r29
add r16=16,r10 };;
{ .mmb;
(p8) ld8 i0=[r10],16 // aligned input
(p8) ld8 i1=[r11],16
(p8) br.cond.sptk .Loop };;
// align first block
.pred.rel "mutex",p8,p9,p10,p11,p12,p13,p14,p15
{ .mmi; (p7) ld8 r14=[r10],24
(p7) ld8 r15=[r11],24 }
{ .mii; (p7) ld8 r16=[r16]
nop.i 0;;
(p15) shrp i0=r15,r14,56 }
{ .mii; (p15) shrp i1=r16,r15,56
(p14) shrp i0=r15,r14,48 }
{ .mii; (p14) shrp i1=r16,r15,48
(p13) shrp i0=r15,r14,40 }
{ .mii; (p13) shrp i1=r16,r15,40
(p12) shrp i0=r15,r14,32 }
{ .mii; (p12) shrp i1=r16,r15,32
(p11) shrp i0=r15,r14,24 }
{ .mii; (p11) shrp i1=r16,r15,24
(p10) shrp i0=r15,r14,16 }
{ .mii; (p10) shrp i1=r16,r15,16
(p9) shrp i0=r15,r14,8 }
{ .mii; (p9) shrp i1=r16,r15,8
mov r14=r16 };;
.Loop:
.pred.rel "mutex",p8,p9,p10,p11,p12,p13,p14,p15
{ .mmi; add h0=h0,i0
add h1=h1,i1
add h2=h2,r35 };;
{ .mmi; setf.sig HF0=h0
cmp.ltu p6,p0=h0,i0
cmp.ltu p7,p0=h1,i1 };;
{ .mmi; (p6) add h1=1,h1;;
setf.sig HF1=h1
(p6) cmp.eq.or p7,p0=0,h1 };;
{ .mmi; (p7) add h2=1,h2;;
setf.sig HF2=h2 };;
{ .mfi; (p16) ld8 r15=[r10],16
xmpy.lu f32=HF0,RF0 }
{ .mfi; (p16) ld8 r16=[r11],16
xmpy.hu f33=HF0,RF0 }
{ .mfi; xmpy.lu f36=HF0,RF1 }
{ .mfi; xmpy.hu f37=HF0,RF1 };;
{ .mfi; xmpy.lu f34=HF1,SF1
(p15) shrp i0=r15,r14,56 }
{ .mfi; xmpy.hu f35=HF1,SF1 }
{ .mfi; xmpy.lu f38=HF1,RF0
(p15) shrp i1=r16,r15,56 }
{ .mfi; xmpy.hu f39=HF1,RF0 }
{ .mfi; xmpy.lu f40=HF2,SF1
(p14) shrp i0=r15,r14,48 }
{ .mfi; xmpy.lu f41=HF2,RF0 };;
{ .mmi; getf.sig r22=f32
getf.sig r23=f33
(p14) shrp i1=r16,r15,48 }
{ .mmi; getf.sig r24=f34
getf.sig r25=f35
(p13) shrp i0=r15,r14,40 }
{ .mmi; getf.sig r26=f36
getf.sig r27=f37
(p13) shrp i1=r16,r15,40 }
{ .mmi; getf.sig r28=f38
getf.sig r29=f39
(p12) shrp i0=r15,r14,32 }
{ .mmi; getf.sig r30=f40
getf.sig r31=f41 };;
{ .mmi; add h0=r22,r24
add r23=r23,r25
(p12) shrp i1=r16,r15,32 }
{ .mmi; add h1=r26,r28
add r27=r27,r29
(p11) shrp i0=r15,r14,24 };;
{ .mmi; cmp.ltu p6,p0=h0,r24
cmp.ltu p7,p0=h1,r28
add r23=r23,r30 };;
{ .mmi; (p6) add r23=1,r23
(p7) add r27=1,r27
(p11) shrp i1=r16,r15,24 };;
{ .mmi; add h1=h1,r23;;
cmp.ltu p6,p7=h1,r23
(p10) shrp i0=r15,r14,16 };;
{ .mmi; (p6) add h2=r31,r27,1
(p7) add h2=r31,r27
(p10) shrp i1=r16,r15,16 };;
{ .mmi; (p8) mov i0=r15
and r22=-4,h2
shr.u r23=h2,2 };;
{ .mmi; add r22=r22,r23
and h2=3,h2
(p9) shrp i0=r15,r14,8 };;
{ .mmi; add h0=h0,r22;;
cmp.ltu p6,p0=h0,r22
(p9) shrp i1=r16,r15,8 };;
{ .mmi; (p8) mov i1=r16
(p6) cmp.eq.unc p7,p0=-1,h1
(p6) add h1=1,h1 };;
{ .mmb; (p7) add h2=1,h2
mov r14=r16
br.ctop.sptk .Loop };;
.Lcend:
{ .mii; SUM 1<<1 // back to big-endian
mov ar.lc=r3 };;
{ .mmi; st8 [r8]=h0,16
st8 [r9]=h1
mov pr=r36,0x1ffff };;
{ .mmb; st8 [r8]=h2
rum 1<<5
br.ret.sptk b0 };;
.endp poly1305_blocks#
.global poly1305_emit#
.proc poly1305_emit#
.align 64
poly1305_emit:
.prologue
.save ar.pfs,r2
{ .mmi; alloc r2=ar.pfs,3,0,0,0
ADDP r8=0,r32
ADDP r9=8,r32 };;
.body
{ .mmi; ld8 r16=[r8],16 // load hash
ld8 r17=[r9]
ADDP r10=0,r34 };;
{ .mmi; ld8 r18=[r8]
ld4 r24=[r10],8 // load nonce
ADDP r11=4,r34 };;
{ .mmi; ld4 r25=[r11],8
ld4 r26=[r10]
add r20=5,r16 };;
{ .mmi; ld4 r27=[r11]
cmp.ltu p6,p7=r20,r16
shl r25=r25,32 };;
{ .mmi;
(p6) add r21=1,r17
(p7) add r21=0,r17
(p6) cmp.eq.or.andcm p6,p7=-1,r17 };;
{ .mmi;
(p6) add r22=1,r18
(p7) add r22=0,r18
shl r27=r27,32 };;
{ .mmi; or r24=r24,r25
or r26=r26,r27
cmp.leu p6,p7=4,r22 };;
{ .mmi;
(p6) add r16=r20,r24
(p7) add r16=r16,r24
(p6) add r17=r21,r26 };;
{ .mii;
(p7) add r17=r17,r26
cmp.ltu p6,p7=r16,r24;;
(p6) add r17=1,r17 };;
{ .mmi; ADDP r8=0,r33
ADDP r9=4,r33
shr.u r20=r16,32 }
{ .mmi; ADDP r10=8,r33
ADDP r11=12,r33
shr.u r21=r17,32 };;
{ .mmi; st1 [r8]=r16,1 // write mac, little-endian
st1 [r9]=r20,1
shr.u r16=r16,8 }
{ .mii; st1 [r10]=r17,1
shr.u r20=r20,8
shr.u r17=r17,8 }
{ .mmi; st1 [r11]=r21,1
shr.u r21=r21,8 };;
{ .mmi; st1 [r8]=r16,1
st1 [r9]=r20,1
shr.u r16=r16,8 }
{ .mii; st1 [r10]=r17,1
shr.u r20=r20,8
shr.u r17=r17,8 }
{ .mmi; st1 [r11]=r21,1
shr.u r21=r21,8 };;
{ .mmi; st1 [r8]=r16,1
st1 [r9]=r20,1
shr.u r16=r16,8 }
{ .mii; st1 [r10]=r17,1
shr.u r20=r20,8
shr.u r17=r17,8 }
{ .mmi; st1 [r11]=r21,1
shr.u r21=r21,8 };;
{ .mmi; st1 [r8]=r16
st1 [r9]=r20 }
{ .mmb; st1 [r10]=r17
st1 [r11]=r21
br.ret.sptk b0 };;
.endp poly1305_emit#
stringz "Poly1305 for IA64, CRYPTOGAMS by \@dot-asm"
+798 -657
View File
@@ -32,10 +32,20 @@
# Copyright IBM Corp. 2019
# Author: Patrick Steuer <patrick.steuer@de.ibm.com>
#
# January 2019
#
# Add vector base 2^26 implementation. It's problematic to accurately
# measure performance, because reference system is hardly idle. But
# it's sub-cycle, i.e. less than 1 cycle per processed byte, and it's
# >=20% faster than IBM's submission on long inputs, and much faster on
# short ones, because calculation of key powers is postponed till we
# know that input is long enough to justify the additional overhead.
use strict;
use FindBin qw($Bin);
use lib "$Bin/../..";
use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL);
use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE);
my $flavour = shift;
@@ -51,666 +61,98 @@ if ($flavour =~ /3[12]/) {
my $output;
while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
my $stdframe=16*$SIZE_T+4*8;
my $sp="%r15";
# novx code path ctx layout
# ---------------------------------
# var value base off
# ---------------------------------
# u64 h[3] hash 2^64 0
# u32 pad[2]
# u64 r[2] key 2^64 32
# vx code path ctx layout
# ---------------------------------
# var value base off
# ---------------------------------
# u32 acc1[5] r^2-acc 2^26 0
# u32 pad
# u32 acc2[5] r-acc 2^26 24
# u32 pad
# u32 r1[5] r 2^26 48
# u32 r15[5] 5*r 2^26 68
# u32 r2[5] r^2 2^26 88
# u32 r25[5] 5*r^2 2^26 108
# u32 r4[5] r^4 2^26 128
# u32 r45[5] 5*r^4 2^26 148
my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5));
PERLASM_BEGIN($output);
INCLUDE ("s390x_arch.h");
TEXT ();
################
# static void poly1305_init(void *ctx, const unsigned char key[16])
{
my ($ctx,$key)=map("%r$_",(2..3));
my ($r0,$r1,$r2)=map("%r$_",(9,11,13));
sub MUL_RKEY { # r*=key
my ($d0hi,$d0lo,$d1hi,$d1lo)=map("%r$_",(4..7));
my ($t0,$t1,$s1)=map("%r$_",(8,10,12));
lg ("%r0","32($ctx)");
lg ("%r1","40($ctx)");
srlg ($s1,"%r1",2);
algr ($s1,"%r1");
lgr ($d0lo,$r0);
lgr ($d1lo,$r1);
mlgr ($d0hi,"%r0");
lgr ($r1,$d1lo);
mlgr ($d1hi,$s1);
mlgr ($t0,"%r1");
mlgr ($t1,"%r0");
algr ($d0lo,$d1lo);
lgr ($d1lo,$r2);
alcgr ($d0hi,$d1hi);
lghi ($d1hi,0);
algr ($r1,$r0);
alcgr ($t1,$t0);
msgr ($d1lo,$s1);
msgr ($r2,"%r0");
algr ($r1,$d1lo);
alcgr ($t1,$d1hi);
algr ($r1,$d0hi);
alcgr ($r2,$t1);
lghi ($r0,-4);
ngr ($r0,$r2);
srlg ($t0,$r2,2);
algr ($r0,$t0);
lghi ($t1,3);
ngr ($r2,$t1);
algr ($r0,$d0lo);
alcgr ($r1,$d1hi);
alcgr ($r2,$d1hi);
}
sub ST_R5R { # store r,5*r -> base 2^26
my @d=map("%r$_",(4..8));
my @off=@_;
lgr (@d[2],$r0);
lr ("%r1",@d[2]);
nilh ("%r1",1023);
lgr (@d[3],$r1);
lr (@d[0],"%r1");
srlg ("%r1",@d[2],52);
lgr (@d[4],$r2);
srlg ("%r0",@d[2],26);
sll (@d[4],24);
lr (@d[2],@d[3]);
nilh ("%r0",1023);
sll (@d[2],12);
lr (@d[1],"%r0");
&or (@d[2],"%r1");
srlg ("%r1",@d[3],40);
nilh (@d[2],1023);
&or (@d[4],"%r1");
srlg (@d[3],@d[3],14);
nilh (@d[4],1023);
nilh (@d[3],1023);
stm (@d[0],@d[4],"@off[0]($ctx)");
mhi (@d[$_],5) for (0..4);
stm (@d[0],@d[4],"@off[1]($ctx)");
}
GLOBL ("poly1305_init");
TYPE ("poly1305_init","\@function");
ALIGN (16);
LABEL ("poly1305_init");
lghi ("%r0",0);
lghi ("%r1",-1);
stg ("%r0","0($ctx)"); # zero hash value / acc1
stg ("%r0","0($ctx)"); # zero hash value
stg ("%r0","8($ctx)");
stg ("%r0","16($ctx)");
st ("%r0","24($ctx)"); # clear is_base2_26
lgr ("%r5",$ctx); # reassign $ctx
lghi ("%r2",0);
&{$z? \&clgr:\&clr} ($key,"%r0");
je (".Ldone");
&{$z? \&clgr:\&clr} ($inp,"%r0");
je (".Lno_key");
lrvg ("%r4","0($key)"); # load little-endian key
lrvg ("%r5","8($key)");
lrvg ("%r2","0($inp)"); # load little-endian key
lrvg ("%r3","8($inp)");
nihl ("%r1",0xffc0); # 0xffffffc0ffffffff
srlg ("%r0","%r1",4); # 0x0ffffffc0fffffff
nihl ("%r1",0xffc0); # 0xffffffc0ffffffff
srlg ("%r0","%r1",4); # 0x0ffffffc0fffffff
srlg ("%r1","%r1",4);
nill ("%r1",0xfffc); # 0x0ffffffc0ffffffc
nill ("%r1",0xfffc); # 0x0ffffffc0ffffffc
ngr ("%r4","%r0");
ngr ("%r5","%r1");
ngr ("%r2","%r0");
ngr ("%r3","%r1");
stg ("%r4","32($ctx)");
stg ("%r5","40($ctx)");
stmg ("%r2","%r3","32(%r5)");
larl ("%r1","OPENSSL_s390xcap_P");
lg ("%r0","16(%r1)");
tmhh ("%r0",0x4000); # check for vector facility
jz (".Ldone");
larl ("%r4","poly1305_blocks_vx");
larl ("%r5","poly1305_emit_vx");
&{$z? \&stmg:\&stm} ("%r6","%r13","6*$SIZE_T($sp)");
&{$z? \&stmg:\&stm} ("%r4","%r5","4*$z+228($ctx)");
lg ($r0,"32($ctx)");
lg ($r1,"40($ctx)");
lghi ($r2,0);
ST_R5R (48,68); # store r,5*r
MUL_RKEY();
ST_R5R (88,108); # store r^2,5*r^2
MUL_RKEY();
MUL_RKEY();
ST_R5R (128,148); # store r^4,5*r^4
lghi ("%r0",0);
stg ("%r0","24($ctx)"); # zero acc2
stg ("%r0","32($ctx)");
stg ("%r0","40($ctx)");
&{$z? \&lmg:\&lm} ("%r6","%r13","6*$SIZE_T($sp)");
srlg ("%r0","%r0",62);
nill ("%r0",1); # extract vx bit
lcgr ("%r0","%r0");
larl ("%r1",".Lpoly1305_blocks");
larl ("%r2",".Lpoly1305_blocks_vx");
larl ("%r3",".Lpoly1305_emit");
&{$z? \&xgr:\&xr} ("%r2","%r1"); # select between scalar and vector
&{$z? \&ngr:\&nr} ("%r2","%r0");
&{$z? \&xgr:\&xr} ("%r2","%r1");
&{$z? \&stmg:\&stm} ("%r2","%r3","0(%r4)");
lghi ("%r2",1);
br ("%r14");
LABEL (".Ldone");
lghi ("%r2",0);
LABEL (".Lno_key");
br ("%r14");
SIZE ("poly1305_init",".-poly1305_init");
}
# VX CODE PATH
{
my $frame=8*16;
my @m01=map("%v$_",(0..4));
my @m23=map("%v$_",(5..9));
my @tmp=@m23;
my @acc=map("%v$_",(10..14));
my @r=map("%v$_",(15..19));
my @r5=map("%v$_",(20..24));
my $padvec="%v26";
my $mask4="%v27";
my @vperm=map("%v$_",(28..30));
my $mask="%v31";
sub REDUCE {
vesrlg (@tmp[0],@acc[0],26);
vesrlg (@tmp[3],@acc[3],26);
vn (@acc[0],@acc[0],$mask);
vn (@acc[3],@acc[3],$mask);
vag (@acc[1],@acc[1],@tmp[0]); # carry 0->1
vag (@acc[4],@acc[4],@tmp[3]); # carry 3->4
vesrlg (@tmp[1],@acc[1],26);
vesrlg (@tmp[4],@acc[4],26);
vn (@acc[1],@acc[1],$mask);
vn (@acc[4],@acc[4],$mask);
veslg (@tmp[0],@tmp[4],2);
vag (@tmp[4],@tmp[4],@tmp[0]); # h[4]*=5
vag (@acc[2],@acc[2],@tmp[1]); # carry 1->2
vag (@acc[0],@acc[0],@tmp[4]); # carry 4->0
vesrlg (@tmp[2],@acc[2],26);
vesrlg (@tmp[0],@acc[0],26);
vn (@acc[2],@acc[2],$mask);
vn (@acc[0],@acc[0],$mask);
vag (@acc[3],@acc[3],@tmp[2]); # carry 2->3
vag (@acc[1],@acc[1],@tmp[0]); # carry 0->1
vesrlg (@tmp[3],@acc[3],26);
vn (@acc[3],@acc[3],$mask);
vag (@acc[4],@acc[4],@tmp[3]); # carry 3->4
}
################
# static void poly1305_blocks_vx(void *ctx, const unsigned char *inp,
# size_t len, u32 padbit)
# static void poly1305_blocks(void *ctx, const unsigned char *inp,
# size_t len, u32 padbit)
{
my ($ctx,$inp,$len) = map("%r$_",(2..4));
my $padbit="%r0";
GLOBL ("poly1305_blocks_vx");
TYPE ("poly1305_blocks_vx","\@function");
ALIGN (16);
LABEL ("poly1305_blocks_vx");
if ($z) {
aghi ($sp,-$frame);
vstm ("%v8","%v15","0($sp)");
} else {
std ("%f4","16*$SIZE_T+2*8($sp)");
std ("%f6","16*$SIZE_T+3*8($sp)");
llgfr ($len,$len);
}
llgfr ($padbit,"%r5");
vlef (@acc[$_],"4*$_($ctx)",1) for (0..4); # load acc1
larl ("%r5",".Lconst");
vlef (@acc[$_],"24+4*$_($ctx)",3) for (0..4); # load acc2
sllg ($padbit,$padbit,24);
vlm (@vperm[0],$mask,"0(%r5)"); # load vperm ops, mask
vgbm ($mask4,0x0707);
vlvgp ($padvec,$padbit,$padbit);
srlg ("%r1",$len,6);
ltgr ("%r1","%r1");
jz (".Lvx_4x_done");
ALIGN (16);
LABEL (".Lvx_4x");
vlm ("%v20","%v23","0($inp)"); # load m0,m1,m2,m3
# m01,m23 -> base 2^26
vperm (@m01[0],"%v20","%v21",@vperm[0]);
vperm (@m23[0],"%v22","%v23",@vperm[0]);
vperm (@m01[2],"%v20","%v21",@vperm[1]);
vperm (@m23[2],"%v22","%v23",@vperm[1]);
vperm (@m01[4],"%v20","%v21",@vperm[2]);
vperm (@m23[4],"%v22","%v23",@vperm[2]);
vesrlg (@m01[1],@m01[0],26);
vesrlg (@m23[1],@m23[0],26);
vesrlg (@m01[3],@m01[2],30);
vesrlg (@m23[3],@m23[2],30);
vesrlg (@m01[2],@m01[2],4);
vesrlg (@m23[2],@m23[2],4);
vn (@m01[4],@m01[4],$mask4);
vn (@m23[4],@m23[4],$mask4);
for (0..3) {
vn (@m01[$_],@m01[$_],$mask);
vn (@m23[$_],@m23[$_],$mask);
}
vaf (@m01[4],@m01[4],$padvec); # pad m01
vaf (@m23[4],@m23[4],$padvec); # pad m23
# acc = acc * r^4 + m01 * r^2 + m23
vlrepf (@r5[$_],"4*$_+108($ctx)") for (0..4); # load 5*r^2
vlrepf (@r[$_],"4*$_+88($ctx)") for (0..4); # load r^2
vmalof (@tmp[0],@m01[4],@r5[1],@m23[0]);
vmalof (@tmp[1],@m01[4],@r5[2],@m23[1]);
vmalof (@tmp[2],@m01[4],@r5[3],@m23[2]);
vmalof (@tmp[3],@m01[4],@r5[4],@m23[3]);
vmalof (@tmp[4],@m01[4],@r[0],@m23[4]);
vmalof (@tmp[0],@m01[3],@r5[2],@tmp[0]);
vmalof (@tmp[1],@m01[3],@r5[3],@tmp[1]);
vmalof (@tmp[2],@m01[3],@r5[4],@tmp[2]);
vmalof (@tmp[3],@m01[3],@r[0],@tmp[3]);
vmalof (@tmp[4],@m01[3],@r[1],@tmp[4]);
vmalof (@tmp[0],@m01[2],@r5[3],@tmp[0]);
vmalof (@tmp[1],@m01[2],@r5[4],@tmp[1]);
vmalof (@tmp[2],@m01[2],@r[0],@tmp[2]);
vmalof (@tmp[3],@m01[2],@r[1],@tmp[3]);
vmalof (@tmp[4],@m01[2],@r[2],@tmp[4]);
vmalof (@tmp[0],@m01[1],@r5[4],@tmp[0]);
vmalof (@tmp[1],@m01[1],@r[0],@tmp[1]);
vmalof (@tmp[2],@m01[1],@r[1],@tmp[2]);
vmalof (@tmp[3],@m01[1],@r[2],@tmp[3]);
vmalof (@tmp[4],@m01[1],@r[3],@tmp[4]);
vmalof (@tmp[0],@m01[0],@r[0],@tmp[0]);
vmalof (@tmp[1],@m01[0],@r[1],@tmp[1]);
vmalof (@tmp[2],@m01[0],@r[2],@tmp[2]);
vmalof (@tmp[3],@m01[0],@r[3],@tmp[3]);
vmalof (@tmp[4],@m01[0],@r[4],@tmp[4]);
vlrepf (@r5[$_],"4*$_+148($ctx)") for (0..4); # load 5*r^4
vlrepf (@r[$_],"4*$_+128($ctx)") for (0..4); # load r^4
vmalof (@tmp[0],@acc[4],@r5[1],@tmp[0]);
vmalof (@tmp[1],@acc[4],@r5[2],@tmp[1]);
vmalof (@tmp[2],@acc[4],@r5[3],@tmp[2]);
vmalof (@tmp[3],@acc[4],@r5[4],@tmp[3]);
vmalof (@tmp[4],@acc[4],@r[0],@tmp[4]);
vmalof (@tmp[0],@acc[3],@r5[2],@tmp[0]);
vmalof (@tmp[1],@acc[3],@r5[3],@tmp[1]);
vmalof (@tmp[2],@acc[3],@r5[4],@tmp[2]);
vmalof (@tmp[3],@acc[3],@r[0],@tmp[3]);
vmalof (@tmp[4],@acc[3],@r[1],@tmp[4]);
vmalof (@tmp[0],@acc[2],@r5[3],@tmp[0]);
vmalof (@tmp[1],@acc[2],@r5[4],@tmp[1]);
vmalof (@tmp[2],@acc[2],@r[0],@tmp[2]);
vmalof (@tmp[3],@acc[2],@r[1],@tmp[3]);
vmalof (@tmp[4],@acc[2],@r[2],@tmp[4]);
vmalof (@tmp[0],@acc[1],@r5[4],@tmp[0]);
vmalof (@tmp[1],@acc[1],@r[0],@tmp[1]);
vmalof (@tmp[2],@acc[1],@r[1],@tmp[2]);
vmalof (@tmp[3],@acc[1],@r[2],@tmp[3]);
vmalof (@tmp[4],@acc[1],@r[3],@tmp[4]);
vmalof (@acc[1],@acc[0],@r[1],@tmp[1]);
vmalof (@acc[2],@acc[0],@r[2],@tmp[2]);
vmalof (@acc[3],@acc[0],@r[3],@tmp[3]);
vmalof (@acc[4],@acc[0],@r[4],@tmp[4]);
vmalof (@acc[0],@acc[0],@r[0],@tmp[0]);
REDUCE ();
la ($inp,"64($inp)");
brctg ("%r1",".Lvx_4x");
ALIGN (16);
LABEL (".Lvx_4x_done");
tml ($len,32);
jz (".Lvx_2x_done");
vlm ("%v20","%v21","0($inp)"); # load m0,m1
# m01 -> base 2^26
vperm (@m01[0],"%v20","%v21",@vperm[0]);
vperm (@m01[2],"%v20","%v21",@vperm[1]);
vperm (@m01[4],"%v20","%v21",@vperm[2]);
vesrlg (@m01[1],@m01[0],26);
vesrlg (@m01[3],@m01[2],30);
vesrlg (@m01[2],@m01[2],4);
vn (@m01[4],@m01[4],$mask4);
vn (@m01[$_],@m01[$_],$mask) for (0..3);
vaf (@m01[4],@m01[4],$padvec); # pad m01
# acc = acc * r^2+ m01
vlrepf (@r5[$_],"4*$_+108($ctx)") for (0..4); # load 5*r^2
vlrepf (@r[$_],"4*$_+88($ctx)") for (0..4); # load r^2
vmalof (@tmp[0],@acc[4],@r5[1],@m01[0]);
vmalof (@tmp[1],@acc[4],@r5[2],@m01[1]);
vmalof (@tmp[2],@acc[4],@r5[3],@m01[2]);
vmalof (@tmp[3],@acc[4],@r5[4],@m01[3]);
vmalof (@tmp[4],@acc[4],@r[0],@m01[4]);
vmalof (@tmp[0],@acc[3],@r5[2],@tmp[0]);
vmalof (@tmp[1],@acc[3],@r5[3],@tmp[1]);
vmalof (@tmp[2],@acc[3],@r5[4],@tmp[2]);
vmalof (@tmp[3],@acc[3],@r[0],@tmp[3]);
vmalof (@tmp[4],@acc[3],@r[1],@tmp[4]);
vmalof (@tmp[0],@acc[2],@r5[3],@tmp[0]);
vmalof (@tmp[1],@acc[2],@r5[4],@tmp[1]);
vmalof (@tmp[2],@acc[2],@r[0],@tmp[2]);
vmalof (@tmp[3],@acc[2],@r[1],@tmp[3]);
vmalof (@tmp[4],@acc[2],@r[2],@tmp[4]);
vmalof (@tmp[0],@acc[1],@r5[4],@tmp[0]);
vmalof (@tmp[1],@acc[1],@r[0],@tmp[1]);
vmalof (@tmp[2],@acc[1],@r[1],@tmp[2]);
vmalof (@tmp[3],@acc[1],@r[2],@tmp[3]);
vmalof (@tmp[4],@acc[1],@r[3],@tmp[4]);
vmalof (@acc[1],@acc[0],@r[1],@tmp[1]);
vmalof (@acc[2],@acc[0],@r[2],@tmp[2]);
vmalof (@acc[3],@acc[0],@r[3],@tmp[3]);
vmalof (@acc[4],@acc[0],@r[4],@tmp[4]);
vmalof (@acc[0],@acc[0],@r[0],@tmp[0]);
REDUCE ();
la ($inp,"32($inp)");
ALIGN (16);
LABEL (".Lvx_2x_done");
tml ($len,16);
jz (".Lvx_done");
vleig ($padvec,0,0);
vzero ("%v20");
vl ("%v21","0($inp)"); # load m0
# m0 -> base 2^26
vperm (@m01[0],"%v20","%v21",@vperm[0]);
vperm (@m01[2],"%v20","%v21",@vperm[1]);
vperm (@m01[4],"%v20","%v21",@vperm[2]);
vesrlg (@m01[1],@m01[0],26);
vesrlg (@m01[3],@m01[2],30);
vesrlg (@m01[2],@m01[2],4);
vn (@m01[4],@m01[4],$mask4);
vn (@m01[$_],@m01[$_],$mask) for (0..3);
vaf (@m01[4],@m01[4],$padvec); # pad m0
# acc = acc * r + m01
vlrepf (@r5[$_],"4*$_+68($ctx)") for (0..4); # load 5*r
vlrepf (@r[$_],"4*$_+48($ctx)") for (0..4); # load r
vmalof (@tmp[0],@acc[4],@r5[1],@m01[0]);
vmalof (@tmp[1],@acc[4],@r5[2],@m01[1]);
vmalof (@tmp[2],@acc[4],@r5[3],@m01[2]);
vmalof (@tmp[3],@acc[4],@r5[4],@m01[3]);
vmalof (@tmp[4],@acc[4],@r[0],@m01[4]);
vmalof (@tmp[0],@acc[3],@r5[2],@tmp[0]);
vmalof (@tmp[1],@acc[3],@r5[3],@tmp[1]);
vmalof (@tmp[2],@acc[3],@r5[4],@tmp[2]);
vmalof (@tmp[3],@acc[3],@r[0],@tmp[3]);
vmalof (@tmp[4],@acc[3],@r[1],@tmp[4]);
vmalof (@tmp[0],@acc[2],@r5[3],@tmp[0]);
vmalof (@tmp[1],@acc[2],@r5[4],@tmp[1]);
vmalof (@tmp[2],@acc[2],@r[0],@tmp[2]);
vmalof (@tmp[3],@acc[2],@r[1],@tmp[3]);
vmalof (@tmp[4],@acc[2],@r[2],@tmp[4]);
vmalof (@tmp[0],@acc[1],@r5[4],@tmp[0]);
vmalof (@tmp[1],@acc[1],@r[0],@tmp[1]);
vmalof (@tmp[2],@acc[1],@r[1],@tmp[2]);
vmalof (@tmp[3],@acc[1],@r[2],@tmp[3]);
vmalof (@tmp[4],@acc[1],@r[3],@tmp[4]);
vmalof (@acc[1],@acc[0],@r[1],@tmp[1]);
vmalof (@acc[2],@acc[0],@r[2],@tmp[2]);
vmalof (@acc[3],@acc[0],@r[3],@tmp[3]);
vmalof (@acc[4],@acc[0],@r[4],@tmp[4]);
vmalof (@acc[0],@acc[0],@r[0],@tmp[0]);
REDUCE ();
ALIGN (16);
LABEL (".Lvx_done");
vstef (@acc[$_],"4*$_($ctx)",1) for (0..4); # store acc
vstef (@acc[$_],"24+4*$_($ctx)",3) for (0..4);
if ($z) {
vlm ("%v8","%v15","0($sp)");
la ($sp,"$frame($sp)");
} else {
ld ("%f4","16*$SIZE_T+2*8($sp)");
ld ("%f6","16*$SIZE_T+3*8($sp)");
}
br ("%r14");
SIZE ("poly1305_blocks_vx",".-poly1305_blocks_vx");
}
################
# static void poly1305_emit_vx(void *ctx, unsigned char mac[16],
# const u32 nonce[4])
{
my ($ctx,$mac,$nonce) = map("%r$_",(2..4));
GLOBL ("poly1305_emit_vx");
TYPE ("poly1305_emit_vx","\@function");
ALIGN (16);
LABEL ("poly1305_emit_vx");
if ($z) {
aghi ($sp,-$frame);
vstm ("%v8","%v15","0($sp)");
} else {
std ("%f4","16*$SIZE_T+2*8($sp)");
std ("%f6","16*$SIZE_T+3*8($sp)");
}
larl ("%r5",".Lconst");
vlef (@acc[$_],"4*$_($ctx)",1) for (0..4); # load acc1
vlef (@acc[$_],"24+4*$_($ctx)",3) for (0..4); # load acc2
vlef (@r5[$_],"108+4*$_($ctx)",1) for (0..4); # load 5*r^2
vlef (@r[$_],"88+4*$_($ctx)",1) for (0..4); # load r^2
vlef (@r5[$_],"68+4*$_($ctx)",3) for (0..4); # load 5*r
vlef (@r[$_],"48+4*$_($ctx)",3) for (0..4); # load r
vl ($mask,"48(%r5)"); # load mask
# acc = acc1 * r^2 + acc2 * r
vmlof (@tmp[0],@acc[4],@r5[1]);
vmlof (@tmp[1],@acc[4],@r5[2]);
vmlof (@tmp[2],@acc[4],@r5[3]);
vmlof (@tmp[3],@acc[4],@r5[4]);
vmlof (@tmp[4],@acc[4],@r[0]);
vmalof (@tmp[0],@acc[3],@r5[2],@tmp[0]);
vmalof (@tmp[1],@acc[3],@r5[3],@tmp[1]);
vmalof (@tmp[2],@acc[3],@r5[4],@tmp[2]);
vmalof (@tmp[3],@acc[3],@r[0],@tmp[3]);
vmalof (@tmp[4],@acc[3],@r[1],@tmp[4]);
vmalof (@tmp[0],@acc[2],@r5[3],@tmp[0]);
vmalof (@tmp[1],@acc[2],@r5[4],@tmp[1]);
vmalof (@tmp[2],@acc[2],@r[0],@tmp[2]);
vmalof (@tmp[3],@acc[2],@r[1],@tmp[3]);
vmalof (@tmp[4],@acc[2],@r[2],@tmp[4]);
vmalof (@tmp[0],@acc[1],@r5[4],@tmp[0]);
vmalof (@tmp[1],@acc[1],@r[0],@tmp[1]);
vmalof (@tmp[2],@acc[1],@r[1],@tmp[2]);
vmalof (@tmp[3],@acc[1],@r[2],@tmp[3]);
vmalof (@tmp[4],@acc[1],@r[3],@tmp[4]);
vmalof (@acc[1],@acc[0],@r[1],@tmp[1]);
vmalof (@acc[2],@acc[0],@r[2],@tmp[2]);
vmalof (@acc[3],@acc[0],@r[3],@tmp[3]);
vmalof (@acc[4],@acc[0],@r[4],@tmp[4]);
vmalof (@acc[0],@acc[0],@r[0],@tmp[0]);
vzero ("%v27");
vsumqg (@acc[$_],@acc[$_],"%v27") for (0..4);
REDUCE ();
vesrlg (@tmp[1],@acc[1],26);
vn (@acc[1],@acc[1],$mask);
vag (@acc[2],@acc[2],@tmp[1]); # carry 1->2
vesrlg (@tmp[2],@acc[2],26);
vn (@acc[2],@acc[2],$mask);
vag (@acc[3],@acc[3],@tmp[2]); # carry 2->3
vesrlg (@tmp[3],@acc[3],26);
vn (@acc[3],@acc[3],$mask);
vag (@acc[4],@acc[4],@tmp[3]); # carry 3->4
# acc -> base 2^64
vleib ("%v30",6*8,7);
vleib ("%v29",13*8,7);
vleib ("%v28",3*8,7);
veslg (@acc[1],@acc[1],26);
veslg (@acc[3],@acc[3],26);
vo (@acc[0],@acc[0],@acc[1]);
vo (@acc[2],@acc[2],@acc[3]);
veslg (@acc[2],@acc[2],4);
vslb (@acc[2],@acc[2],"%v30"); # <<52
vo (@acc[0],@acc[0],@acc[2]);
vslb (@tmp[4],@acc[4],"%v29"); # <<104
vo (@acc[0],@acc[0],@tmp[4]);
vsrlb (@acc[1],@acc[4],"%v28"); # >>24
# acc %= 2^130-5
vone ("%v26");
vleig ("%v27",5,1);
vone ("%v29");
vleig ("%v26",-4,1);
vaq (@tmp[0],@acc[0],"%v27");
vaccq (@tmp[1],@acc[0],"%v27");
vaq (@tmp[1],@tmp[1],"%v26");
vaccq (@tmp[1],@tmp[1],@acc[1]);
vaq (@tmp[1],@tmp[1],"%v29");
vn (@tmp[2],@tmp[1],@acc[0]);
vnc (@tmp[3],@tmp[0],@tmp[1]);
vo (@acc[0],@tmp[2],@tmp[3]);
# acc += nonce
vl (@vperm[0],"64(%r5)");
vlef (@tmp[0],"4*$_($nonce)",3-$_) for (0..3);
vaq (@acc[0],@acc[0],@tmp[0]);
vperm (@acc[0],@acc[0],@acc[0],@vperm[0]);
vst (@acc[0],"0($mac)"); # store mac
if ($z) {
vlm ("%v8","%v15","0($sp)");
la ($sp,"$frame($sp)");
} else {
ld ("%f4","16*$SIZE_T+2*8($sp)");
ld ("%f6","16*$SIZE_T+3*8($sp)");
}
br ("%r14");
SIZE ("poly1305_emit_vx",".-poly1305_emit_vx");
}
}
# NOVX CODE PATH
{
################
# static void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
# u32 padbit)
{
my ($ctx,$inp,$len,$padbit) = map("%r$_",(2..5));
my ($d0hi,$d0lo,$d1hi,$d1lo,$t0,$h0,$t1,$h1,$h2) = map("%r$_",(6..14));
my ($r0,$r1,$s1) = map("%r$_",(0..2));
GLOBL ("poly1305_blocks");
TYPE ("poly1305_blocks","\@function");
ALIGN (16);
LABEL ("poly1305_blocks");
$z? srlg ($len,$len,4) :srl ($len,4);
lghi ("%r0",0);
&{$z? \&clgr:\&clr} ($len,"%r0");
je (".Lno_data");
LABEL (".Lpoly1305_blocks");
&{$z? \&ltgr:\&ltr} ("%r0",$len);
jz (".Lno_data");
&{$z? \&stmg:\&stm} ("%r6","%r14","6*$SIZE_T($sp)");
llgfr ($padbit,$padbit); # clear upper half, much needed with
# non-64-bit ABI
lg ($r0,"32($ctx)"); # load key
lg ($r1,"40($ctx)");
lg ($h0,"0($ctx)"); # load hash value
lg ($h0,"0($ctx)"); # load hash value
lg ($h1,"8($ctx)");
lg ($h2,"16($ctx)");
LABEL (".Lpoly1305_blocks_entry");
if ($z) {
srlg ($len,$len,4);
} else {
srl ($len,4);
}
llgfr ($padbit,$padbit); # clear upper half, much needed with
# non-64-bit ABI
lg ($r0,"32($ctx)"); # load key
lg ($r1,"40($ctx)");
&{$z? \&stg:\&st} ($ctx,"2*$SIZE_T($sp)"); # off-load $ctx
srlg ($s1,$r1,2);
algr ($s1,$r1); # s1 = r1 + r1>>2
@@ -718,21 +160,21 @@ $z? srlg ($len,$len,4) :srl ($len,4);
ALIGN (16);
LABEL (".Loop");
lrvg ($d0lo,"0($inp)"); # load little-endian input
lrvg ($d0lo,"0($inp)"); # load little-endian input
lrvg ($d1lo,"8($inp)");
la ($inp,"16($inp)");
algr ($d0lo,$h0); # accumulate input
algr ($d0lo,$h0); # accumulate input
alcgr ($d1lo,$h1);
alcgr ($h2,$padbit);
lgr ($h0,$d0lo);
mlgr ($d0hi,$r0); # h0*r0 -> $d0hi:$d0lo
mlgr ($d0hi,$r0); # h0*r0 -> $d0hi:$d0lo
lgr ($h1,$d1lo);
mlgr ($d1hi,$s1); # h1*5*r1 -> $d1hi:$d1lo
mlgr ($d1hi,$s1); # h1*5*r1 -> $d1hi:$d1lo
mlgr ($t0,$r1); # h0*r1 -> $t0:$h0
mlgr ($t1,$r0); # h1*r0 -> $t1:$h1
alcgr ($h2,$padbit);
mlgr ($t0,$r1); # h0*r1 -> $t0:$h0
mlgr ($t1,$r0); # h1*r0 -> $t1:$h1
algr ($d0lo,$d1lo);
lgr ($d1lo,$h2);
@@ -742,16 +184,16 @@ LABEL (".Loop");
algr ($h1,$h0);
alcgr ($t1,$t0);
msgr ($d1lo,$s1); # h2*s1
msgr ($h2,$r0); # h2*r0
msgr ($d1lo,$s1); # h2*s1
msgr ($h2,$r0); # h2*r0
algr ($h1,$d1lo);
alcgr ($t1,$d1hi); # $d1hi is zero
alcgr ($t1,$d1hi); # $d1hi is zero
algr ($h1,$d0hi);
alcgr ($h2,$t1);
lghi ($h0,-4); # final reduction step
lghi ($h0,-4); # final reduction step
ngr ($h0,$h2);
srlg ($t0,$h2,2);
algr ($h0,$t0);
@@ -759,14 +201,14 @@ LABEL (".Loop");
ngr ($h2,$t1);
algr ($h0,$d0lo);
alcgr ($h1,$d1hi); # $d1hi is still zero
alcgr ($h2,$d1hi); # $d1hi is still zero
alcgr ($h1,$d1hi); # $d1hi is still zero
alcgr ($h2,$d1hi); # $d1hi is still zero
&{$z? \&brctg:\&brct} ($len,".Loop");
&{$z? \&lg:\&l} ($ctx,"2*$SIZE_T($sp)");# restore $ctx
stg ($h0,"0($ctx)"); # store hash value
stg ($h0,"0($ctx)"); # store hash value
stg ($h1,"8($ctx)");
stg ($h2,"16($ctx)");
@@ -776,68 +218,767 @@ LABEL (".Lno_data");
SIZE ("poly1305_blocks",".-poly1305_blocks");
}
################
# static void poly1305_blocks_vx(void *ctx, const unsigned char *inp,
# size_t len, u32 padbit)
{
my ($H0, $H1, $H2, $H3, $H4) = map("%v$_",(0..4));
my ($I0, $I1, $I2, $I3, $I4) = map("%v$_",(5..9));
my ($R0, $R1, $S1, $R2, $S2) = map("%v$_",(10..14));
my ($R3, $S3, $R4, $S4) = map("%v$_",(15..18));
my ($ACC0, $ACC1, $ACC2, $ACC3, $ACC4) = map("%v$_",(19..23));
my ($T1, $T2, $T3, $T4) = map("%v$_",(24..27));
my ($mask26,$bswaplo,$bswaphi,$bswapmi) = map("%v$_",(28..31));
my ($d2,$d0,$h0,$d1,$h1,$h2)=map("%r$_",(9..14));
TYPE ("poly1305_blocks_vx","\@function");
ALIGN (16);
LABEL ("poly1305_blocks_vx");
LABEL (".Lpoly1305_blocks_vx");
&{$z? \&clgfi:\&clfi} ($len,128);
jhe ("__poly1305_blocks_vx");
&{$z? \&stmg:\&stm} ("%r6","%r14","6*$SIZE_T($sp)");
lg ($d0,"0($ctx)");
lg ($d1,"8($ctx)");
lg ($d2,"16($ctx)");
llgfr ("%r0",$d0); # base 2^26 -> base 2^64
srlg ($h0,$d0,32);
llgfr ("%r1",$d1);
srlg ($h1,$d1,32);
srlg ($h2,$d2,32);
sllg ("%r0","%r0",26);
algr ($h0,"%r0");
sllg ("%r0",$h1,52);
srlg ($h1,$h1,12);
sllg ("%r1","%r1",14);
algr ($h0,"%r0");
alcgr ($h1,"%r1");
sllg ("%r0",$h2,40);
srlg ($h2,$h2,24);
lghi ("%r1",0);
algr ($h1,"%r0");
alcgr ($h2,"%r1");
llgf ("%r0","24($ctx)"); # is_base2_26
lcgr ("%r0","%r0");
xgr ($h0,$d0); # choose between radixes
xgr ($h1,$d1);
xgr ($h2,$d2);
ngr ($h0,"%r0");
ngr ($h1,"%r0");
ngr ($h2,"%r0");
xgr ($h0,$d0);
xgr ($h1,$d1);
xgr ($h2,$d2);
lhi ("%r0",0);
st ("%r0","24($ctx)"); # clear is_base2_26
j (".Lpoly1305_blocks_entry");
SIZE ("poly1305_blocks_vx",".-poly1305_blocks_vx");
TYPE ("__poly1305_mul","\@function");
ALIGN (16);
LABEL ("__poly1305_mul");
vmlof ($ACC0,$H0,$R0);
vmlof ($ACC1,$H0,$R1);
vmlof ($ACC2,$H0,$R2);
vmlof ($ACC3,$H0,$R3);
vmlof ($ACC4,$H0,$R4);
vmalof ($ACC0,$H1,$S4,$ACC0);
vmalof ($ACC1,$H1,$R0,$ACC1);
vmalof ($ACC2,$H1,$R1,$ACC2);
vmalof ($ACC3,$H1,$R2,$ACC3);
vmalof ($ACC4,$H1,$R3,$ACC4);
vmalof ($ACC0,$H2,$S3,$ACC0);
vmalof ($ACC1,$H2,$S4,$ACC1);
vmalof ($ACC2,$H2,$R0,$ACC2);
vmalof ($ACC3,$H2,$R1,$ACC3);
vmalof ($ACC4,$H2,$R2,$ACC4);
vmalof ($ACC0,$H3,$S2,$ACC0);
vmalof ($ACC1,$H3,$S3,$ACC1);
vmalof ($ACC2,$H3,$S4,$ACC2);
vmalof ($ACC3,$H3,$R0,$ACC3);
vmalof ($ACC4,$H3,$R1,$ACC4);
vmalof ($ACC0,$H4,$S1,$ACC0);
vmalof ($ACC1,$H4,$S2,$ACC1);
vmalof ($ACC2,$H4,$S3,$ACC2);
vmalof ($ACC3,$H4,$S4,$ACC3);
vmalof ($ACC4,$H4,$R0,$ACC4);
################################################################
# lazy reduction
vesrlg ($H4,$ACC3,26);
vesrlg ($H1,$ACC0,26);
vn ($H3,$ACC3,$mask26);
vn ($H0,$ACC0,$mask26);
vag ($H4,$H4,$ACC4); # h3 -> h4
vag ($H1,$H1,$ACC1); # h0 -> h1
vesrlg ($ACC4,$H4,26);
vesrlg ($ACC1,$H1,26);
vn ($H4,$H4,$mask26);
vn ($H1,$H1,$mask26);
vag ($H0,$H0,$ACC4);
vag ($H2,$ACC2,$ACC1); # h1 -> h2
veslg ($ACC4,$ACC4,2); # <<2
vesrlg ($ACC2,$H2,26);
vn ($H2,$H2,$mask26);
vag ($H0,$H0,$ACC4); # h4 -> h0
vag ($H3,$H3,$ACC2); # h2 -> h3
vesrlg ($ACC0,$H0,26);
vesrlg ($ACC3,$H3,26);
vn ($H0,$H0,$mask26);
vn ($H3,$H3,$mask26);
vag ($H1,$H1,$ACC0); # h0 -> h1
vag ($H4,$H4,$ACC3); # h3 -> h4
br ("%r14");
SIZE ("__poly1305_mul",".-__poly1305_mul");
TYPE ("__poly1305_blocks_vx","\@function");
ALIGN (16);
LABEL ("__poly1305_blocks_vx");
&{$z? \&lgr:\&lr} ("%r0",$sp);
&{$z? \&stmg:\&stm} ("%r10","%r15","10*$SIZE_T($sp)");
if (!$z) {
std ("%f4","16*$SIZE_T+2*8($sp)");
std ("%f6","16*$SIZE_T+3*8($sp)");
ahi ($sp,-$stdframe);
st ("%r0","0($sp)"); # back-chain
llgfr ($len,$len); # so that srlg works on $len
} else {
aghi ($sp,"-($stdframe+8*8)");
stg ("%r0","0($sp)"); # back-chain
std ("%f8","$stdframe+0*8($sp)");
std ("%f9","$stdframe+1*8($sp)");
std ("%f10","$stdframe+2*8($sp)");
std ("%f11","$stdframe+3*8($sp)");
std ("%f12","$stdframe+4*8($sp)");
std ("%f13","$stdframe+5*8($sp)");
std ("%f14","$stdframe+6*8($sp)");
std ("%f15","$stdframe+7*8($sp)");
}
larl ("%r1",".Lconst");
vgmg ($mask26,38,63);
vlm ($bswaplo,$bswapmi,"16(%r1)");
&lt ("%r0","24($ctx)"); # is_base2_26?
jnz (".Lskip_init");
lg ($h0,"32($ctx)"); # load key base 2^64
lg ($h1,"40($ctx)");
risbg ($d0,$h0,38,0x80+63,38); # base 2^64 -> 2^26
srlg ($d1,$h0,52);
risbg ($h0,$h0,38,0x80+63,0);
vlvgg ($R0,$h0,0);
risbg ($d1,$h1,38,51,12);
vlvgg ($R1,$d0,0);
risbg ($d0,$h1,38,63,50);
vlvgg ($R2,$d1,0);
srlg ($d1,$h1,40);
vlvgg ($R3,$d0,0);
vlvgg ($R4,$d1,0);
veslg ($S1,$R1,2);
veslg ($S2,$R2,2);
veslg ($S3,$R3,2);
veslg ($S4,$R4,2);
vlr ($H0,$R0);
vlr ($H1,$R1);
vlr ($H2,$R2);
vlr ($H3,$R3);
vlr ($H4,$R4);
vag ($S1,$S1,$R1); # * 5
vag ($S2,$S2,$R2);
vag ($S3,$S3,$R3);
vag ($S4,$S4,$R4);
brasl ("%r14","__poly1305_mul"); # r^1:- * r^1:-
vpdi ($R0,$H0,$R0,0); # r^2:r^1
vpdi ($R1,$H1,$R1,0);
vpdi ($R2,$H2,$R2,0);
vpdi ($R3,$H3,$R3,0);
vpdi ($R4,$H4,$R4,0);
vpdi ($H0,$H0,$H0,0); # r^2:r^2
vpdi ($H1,$H1,$H1,0);
vpdi ($H2,$H2,$H2,0);
vpdi ($H3,$H3,$H3,0);
vpdi ($H4,$H4,$H4,0);
veslg ($S1,$R1,2);
veslg ($S2,$R2,2);
veslg ($S3,$R3,2);
veslg ($S4,$R4,2);
vag ($S1,$S1,$R1); # * 5
vag ($S2,$S2,$R2);
vag ($S3,$S3,$R3);
vag ($S4,$S4,$R4);
brasl ("%r14,__poly1305_mul"); # r^2:r^2 * r^2:r^1
vl ($I0,"0(%r1)"); # borrow $I0
vperm ($R0,$R0,$H0,$I0); # r^2:r^4:r^1:r^3
vperm ($R1,$R1,$H1,$I0);
vperm ($R2,$R2,$H2,$I0);
vperm ($R3,$R3,$H3,$I0);
vperm ($R4,$R4,$H4,$I0);
veslf ($S1,$R1,2);
veslf ($S2,$R2,2);
veslf ($S3,$R3,2);
veslf ($S4,$R4,2);
vaf ($S1,$S1,$R1); # * 5
vaf ($S2,$S2,$R2);
vaf ($S3,$S3,$R3);
vaf ($S4,$S4,$R4);
lg ($h0,"0($ctx)"); # load hash base 2^64
lg ($h1,"8($ctx)");
lg ($h2,"16($ctx)");
vzero ($H0);
vzero ($H1);
vzero ($H2);
vzero ($H3);
vzero ($H4);
risbg ($d0,$h0,38,0x80+63,38); # base 2^64 -> 2^26
srlg ($d1,$h0,52);
risbg ($h0,$h0,38,0x80+63,0);
vlvgg ($H0,$h0,0);
risbg ($d1,$h1,38,51,12);
vlvgg ($H1,$d0,0);
risbg ($d0,$h1,38,63,50);
vlvgg ($H2,$d1,0);
srlg ($d1,$h1,40);
vlvgg ($H3,$d0,0);
risbg ($d1,$h2,37,39,24);
vlvgg ($H4,$d1,0);
lhi ("%r0",1);
st ("%r0","24($ctx)"); # set is_base2_26
vstm ($R0,$S4,"48($ctx)"); # save key schedule base 2^26
vpdi ($R0,$R0,$R0,0); # broadcast r^2:r^4
vpdi ($R1,$R1,$R1,0);
vpdi ($S1,$S1,$S1,0);
vpdi ($R2,$R2,$R2,0);
vpdi ($S2,$S2,$S2,0);
vpdi ($R3,$R3,$R3,0);
vpdi ($S3,$S3,$S3,0);
vpdi ($R4,$R4,$R4,0);
vpdi ($S4,$S4,$S4,0);
j (".Loaded_hash");
ALIGN (16);
LABEL (".Lskip_init");
vllezf ($H0,"0($ctx)"); # load hash base 2^26
vllezf ($H1,"4($ctx)");
vllezf ($H2,"8($ctx)");
vllezf ($H3,"12($ctx)");
vllezf ($H4,"16($ctx)");
vlrepg ($R0,"0x30($ctx)"); # broadcast r^2:r^4
vlrepg ($R1,"0x40($ctx)");
vlrepg ($S1,"0x50($ctx)");
vlrepg ($R2,"0x60($ctx)");
vlrepg ($S2,"0x70($ctx)");
vlrepg ($R3,"0x80($ctx)");
vlrepg ($S3,"0x90($ctx)");
vlrepg ($R4,"0xa0($ctx)");
vlrepg ($S4,"0xb0($ctx)");
LABEL (".Loaded_hash");
vzero ($I1);
vzero ($I3);
vlm ($T1,$T4,"0x00($inp)"); # load first input block
la ($inp,"0x40($inp)");
vgmg ($mask26,6,31);
vgmf ($I4,5,5); # padbit<<2
vperm ($I0,$T3,$T4,$bswaplo);
vperm ($I2,$T3,$T4,$bswapmi);
vperm ($T3,$T3,$T4,$bswaphi);
verimg ($I1,$I0,$mask26,6); # >>26
veslg ($I0,$I0,32);
veslg ($I2,$I2,28); # >>4
verimg ($I3,$T3,$mask26,18); # >>14
verimg ($I4,$T3,$mask26,58); # >>38
vn ($I0,$I0,$mask26);
vn ($I2,$I2,$mask26);
vesrlf ($I4,$I4,2); # >>2
vgmg ($mask26,38,63);
vperm ($T3,$T1,$T2,$bswaplo);
vperm ($T4,$T1,$T2,$bswaphi);
vperm ($T2,$T1,$T2,$bswapmi);
verimg ($I0,$T3,$mask26,0);
verimg ($I1,$T3,$mask26,38); # >>26
verimg ($I2,$T2,$mask26,60); # >>4
verimg ($I3,$T4,$mask26,50); # >>14
vesrlg ($T4,$T4,40);
vo ($I4,$I4,$T4);
srlg ("%r0",$len,6);
&{$z? \&aghi:\&ahi} ("%r0",-1);
ALIGN (16);
LABEL (".Loop_vx");
vmlef ($ACC0,$I0,$R0);
vmlef ($ACC1,$I0,$R1);
vmlef ($ACC2,$I0,$R2);
vmlef ($ACC3,$I0,$R3);
vmlef ($ACC4,$I0,$R4);
vmalef ($ACC0,$I1,$S4,$ACC0);
vmalef ($ACC1,$I1,$R0,$ACC1);
vmalef ($ACC2,$I1,$R1,$ACC2);
vmalef ($ACC3,$I1,$R2,$ACC3);
vmalef ($ACC4,$I1,$R3,$ACC4);
vaf ($H2,$H2,$I2);
vaf ($H0,$H0,$I0);
vaf ($H3,$H3,$I3);
vaf ($H1,$H1,$I1);
vaf ($H4,$H4,$I4);
vmalef ($ACC0,$I2,$S3,$ACC0);
vmalef ($ACC1,$I2,$S4,$ACC1);
vmalef ($ACC2,$I2,$R0,$ACC2);
vmalef ($ACC3,$I2,$R1,$ACC3);
vmalef ($ACC4,$I2,$R2,$ACC4);
vlm ($T1,$T4,"0x00($inp)"); # load next input block
la ($inp,"0x40($inp)");
vgmg ($mask26,6,31);
vmalef ($ACC0,$I3,$S2,$ACC0);
vmalef ($ACC1,$I3,$S3,$ACC1);
vmalef ($ACC2,$I3,$S4,$ACC2);
vmalef ($ACC3,$I3,$R0,$ACC3);
vmalef ($ACC4,$I3,$R1,$ACC4);
vperm ($I0,$T3,$T4,$bswaplo);
vperm ($I2,$T3,$T4,$bswapmi);
vperm ($T3,$T3,$T4,$bswaphi);
vmalef ($ACC0,$I4,$S1,$ACC0);
vmalef ($ACC1,$I4,$S2,$ACC1);
vmalef ($ACC2,$I4,$S3,$ACC2);
vmalef ($ACC3,$I4,$S4,$ACC3);
vmalef ($ACC4,$I4,$R0,$ACC4);
verimg ($I1,$I0,$mask26,6); # >>26
veslg ($I0,$I0,32);
veslg ($I2,$I2,28); # >>4
verimg ($I3,$T3,$mask26,18); # >>14
vmalof ($ACC0,$H0,$R0,$ACC0);
vmalof ($ACC1,$H0,$R1,$ACC1);
vmalof ($ACC2,$H0,$R2,$ACC2);
vmalof ($ACC3,$H0,$R3,$ACC3);
vmalof ($ACC4,$H0,$R4,$ACC4);
vgmf ($I4,5,5); # padbit<<2
verimg ($I4,$T3,$mask26,58); # >>38
vn ($I0,$I0,$mask26);
vn ($I2,$I2,$mask26);
vesrlf ($I4,$I4,2); # >>2
vmalof ($ACC0,$H1,$S4,$ACC0);
vmalof ($ACC1,$H1,$R0,$ACC1);
vmalof ($ACC2,$H1,$R1,$ACC2);
vmalof ($ACC3,$H1,$R2,$ACC3);
vmalof ($ACC4,$H1,$R3,$ACC4);
vgmg ($mask26,38,63);
vperm ($T3,$T1,$T2,$bswaplo);
vperm ($T4,$T1,$T2,$bswaphi);
vperm ($T2,$T1,$T2,$bswapmi);
vmalof ($ACC0,$H2,$S3,$ACC0);
vmalof ($ACC1,$H2,$S4,$ACC1);
vmalof ($ACC2,$H2,$R0,$ACC2);
vmalof ($ACC3,$H2,$R1,$ACC3);
vmalof ($ACC4,$H2,$R2,$ACC4);
verimg ($I0,$T3,$mask26,0);
verimg ($I1,$T3,$mask26,38); # >>26
verimg ($I2,$T2,$mask26,60); # >>4
vmalof ($ACC0,$H3,$S2,$ACC0);
vmalof ($ACC1,$H3,$S3,$ACC1);
vmalof ($ACC2,$H3,$S4,$ACC2);
vmalof ($ACC3,$H3,$R0,$ACC3);
vmalof ($ACC4,$H3,$R1,$ACC4);
verimg ($I3,$T4,$mask26,50); # >>14
vesrlg ($T4,$T4,40);
vo ($I4,$I4,$T4);
vmalof ($ACC0,$H4,$S1,$ACC0);
vmalof ($ACC1,$H4,$S2,$ACC1);
vmalof ($ACC2,$H4,$S3,$ACC2);
vmalof ($ACC3,$H4,$S4,$ACC3);
vmalof ($ACC4,$H4,$R0,$ACC4);
################################################################
# lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
# and P. Schwabe
vesrlg ($H4,$ACC3,26);
vesrlg ($H1,$ACC0,26);
vn ($H3,$ACC3,$mask26);
vn ($H0,$ACC0,$mask26);
vag ($H4,$H4,$ACC4); # h3 -> h4
vag ($H1,$H1,$ACC1); # h0 -> h1
vesrlg ($ACC4,$H4,26);
vesrlg ($ACC1,$H1,26);
vn ($H4,$H4,$mask26);
vn ($H1,$H1,$mask26);
vag ($H0,$H0,$ACC4);
vag ($H2,$ACC2,$ACC1); # h1 -> h2
veslg ($ACC4,$ACC4,2); # <<2
vesrlg ($ACC2,$H2,26);
vn ($H2,$H2,$mask26);
vag ($H0,$H0,$ACC4); # h4 -> h0
vag ($H3,$H3,$ACC2); # h2 -> h3
vesrlg ($ACC0,$H0,26);
vesrlg ($ACC3,$H3,26);
vn ($H0,$H0,$mask26);
vn ($H3,$H3,$mask26);
vag ($H1,$H1,$ACC0); # h0 -> h1
vag ($H4,$H4,$ACC3); # h3 -> h4
&{$z? \&brctg:\&brct} ("%r0",".Loop_vx");
vlm ($R0,$S4,"48($ctx)"); # load all powers
lghi ("%r0",0x30);
&{$z? \&lcgr:\&lcr} ($len,$len);
&{$z? \&ngr:\&nr} ($len,"%r0");
&{$z? \&slgr:\&slr} ($inp,$len);
LABEL (".Last");
vmlef ($ACC0,$I0,$R0);
vmlef ($ACC1,$I0,$R1);
vmlef ($ACC2,$I0,$R2);
vmlef ($ACC3,$I0,$R3);
vmlef ($ACC4,$I0,$R4);
vmalef ($ACC0,$I1,$S4,$ACC0);
vmalef ($ACC1,$I1,$R0,$ACC1);
vmalef ($ACC2,$I1,$R1,$ACC2);
vmalef ($ACC3,$I1,$R2,$ACC3);
vmalef ($ACC4,$I1,$R3,$ACC4);
vaf ($H0,$H0,$I0);
vaf ($H1,$H1,$I1);
vaf ($H2,$H2,$I2);
vaf ($H3,$H3,$I3);
vaf ($H4,$H4,$I4);
vmalef ($ACC0,$I2,$S3,$ACC0);
vmalef ($ACC1,$I2,$S4,$ACC1);
vmalef ($ACC2,$I2,$R0,$ACC2);
vmalef ($ACC3,$I2,$R1,$ACC3);
vmalef ($ACC4,$I2,$R2,$ACC4);
vmalef ($ACC0,$I3,$S2,$ACC0);
vmalef ($ACC1,$I3,$S3,$ACC1);
vmalef ($ACC2,$I3,$S4,$ACC2);
vmalef ($ACC3,$I3,$R0,$ACC3);
vmalef ($ACC4,$I3,$R1,$ACC4);
vmalef ($ACC0,$I4,$S1,$ACC0);
vmalef ($ACC1,$I4,$S2,$ACC1);
vmalef ($ACC2,$I4,$S3,$ACC2);
vmalef ($ACC3,$I4,$S4,$ACC3);
vmalef ($ACC4,$I4,$R0,$ACC4);
vmalof ($ACC0,$H0,$R0,$ACC0);
vmalof ($ACC1,$H0,$R1,$ACC1);
vmalof ($ACC2,$H0,$R2,$ACC2);
vmalof ($ACC3,$H0,$R3,$ACC3);
vmalof ($ACC4,$H0,$R4,$ACC4);
vmalof ($ACC0,$H1,$S4,$ACC0);
vmalof ($ACC1,$H1,$R0,$ACC1);
vmalof ($ACC2,$H1,$R1,$ACC2);
vmalof ($ACC3,$H1,$R2,$ACC3);
vmalof ($ACC4,$H1,$R3,$ACC4);
vmalof ($ACC0,$H2,$S3,$ACC0);
vmalof ($ACC1,$H2,$S4,$ACC1);
vmalof ($ACC2,$H2,$R0,$ACC2);
vmalof ($ACC3,$H2,$R1,$ACC3);
vmalof ($ACC4,$H2,$R2,$ACC4);
vmalof ($ACC0,$H3,$S2,$ACC0);
vmalof ($ACC1,$H3,$S3,$ACC1);
vmalof ($ACC2,$H3,$S4,$ACC2);
vmalof ($ACC3,$H3,$R0,$ACC3);
vmalof ($ACC4,$H3,$R1,$ACC4);
vmalof ($ACC0,$H4,$S1,$ACC0);
vmalof ($ACC1,$H4,$S2,$ACC1);
vmalof ($ACC2,$H4,$S3,$ACC2);
vmalof ($ACC3,$H4,$S4,$ACC3);
vmalof ($ACC4,$H4,$R0,$ACC4);
################################################################
# horizontal addition
vzero ($H0);
vsumqg ($ACC0,$ACC0,$H0);
vsumqg ($ACC1,$ACC1,$H0);
vsumqg ($ACC2,$ACC2,$H0);
vsumqg ($ACC3,$ACC3,$H0);
vsumqg ($ACC4,$ACC4,$H0);
################################################################
# lazy reduction
vesrlg ($H4,$ACC3,26);
vesrlg ($H1,$ACC0,26);
vn ($H3,$ACC3,$mask26);
vn ($H0,$ACC0,$mask26);
vag ($H4,$H4,$ACC4); # h3 -> h4
vag ($H1,$H1,$ACC1); # h0 -> h1
vesrlg ($ACC4,$H4,26);
vesrlg ($ACC1,$H1,26);
vn ($H4,$H4,$mask26);
vn ($H1,$H1,$mask26);
vag ($H0,$H0,$ACC4);
vag ($H2,$ACC2,$ACC1); # h1 -> h2
veslg ($ACC4,$ACC4,2); # <<2
vesrlg ($ACC2,$H2,26);
vn ($H2,$H2,$mask26);
vag ($H0,$H0,$ACC4); # h4 -> h0
vag ($H3,$H3,$ACC2); # h2 -> h3
vesrlg ($ACC0,$H0,26);
vesrlg ($ACC3,$H3,26);
vn ($H0,$H0,$mask26);
vn ($H3,$H3,$mask26);
vag ($H1,$H1,$ACC0); # h0 -> h1
vag ($H4,$H4,$ACC3); # h3 -> h4
&{$z? \&clgfi:\&clfi} ($len,0);
je (".Ldone");
vlm ($T1,$T4,"0x00($inp)"); # load last partial block
vgmg ($mask26,6,31);
vgmf ($I4,5,5); # padbit<<2
vperm ($I0,$T3,$T4,$bswaplo);
vperm ($I2,$T3,$T4,$bswapmi);
vperm ($T3,$T3,$T4,$bswaphi);
vl ($ACC0,"0x30($len,%r1)"); # borrow $ACC0,1
vl ($ACC1,"0x60($len,%r1)");
verimg ($I1,$I0,$mask26,6); # >>26
veslg ($I0,$I0,32);
veslg ($I2,$I2,28); # >>4
verimg ($I3,$T3,$mask26,18); # >>14
verimg ($I4,$T3,$mask26,58); # >>38
vn ($I0,$I0,$mask26);
vn ($I2,$I2,$mask26);
vesrlf ($I4,$I4,2); # >>2
vgmg ($mask26,38,63);
vperm ($T3,$T1,$T2,$bswaplo);
vperm ($T4,$T1,$T2,$bswaphi);
vperm ($T2,$T1,$T2,$bswapmi);
verimg ($I0,$T3,$mask26,0);
verimg ($I1,$T3,$mask26,38); # >>26
verimg ($I2,$T2,$mask26,60); # >>4
verimg ($I3,$T4,$mask26,50); # >>14
vesrlg ($T4,$T4,40);
vo ($I4,$I4,$T4);
vperm ($H0,$H0,$H0,$ACC0); # move hash to right lane
vn ($I0,$I0,$ACC1); # mask redundant lane[s]
vperm ($H1,$H1,$H1,$ACC0);
vn ($I1,$I1,$ACC1);
vperm ($H2,$H2,$H2,$ACC0);
vn ($I2,$I2,$ACC1);
vperm ($H3,$H3,$H3,$ACC0);
vn ($I3,$I3,$ACC1);
vperm ($H4,$H4,$H4,$ACC0);
vn ($I4,$I4,$ACC1);
vaf ($I0,$I0,$H0); # accumulate hash
vzero ($H0); # wipe hash value
vaf ($I1,$I1,$H1);
vzero ($H1);
vaf ($I2,$I2,$H2);
vzero ($H2);
vaf ($I3,$I3,$H3);
vzero ($H3);
vaf ($I4,$I4,$H4);
vzero ($H4);
&{$z? \&lghi:\&lhi} ($len,0);
j (".Last");
# I don't bother to tell apart cases when only one multiplication
# pass is sufficient, because I argue that mispredicted branch
# penalties are comparable to overhead of sometimes redundant
# multiplication pass...
LABEL (".Ldone");
vstef ($H0,"0($ctx)",3); # store hash base 2^26
vstef ($H1,"4($ctx)",3);
vstef ($H2,"8($ctx)",3);
vstef ($H3,"12($ctx)",3);
vstef ($H4,"16($ctx)",3);
if ($z) {
ld ("%f8","$stdframe+0*8($sp)");
ld ("%f9","$stdframe+1*8($sp)");
ld ("%f10","$stdframe+2*8($sp)");
ld ("%f11","$stdframe+3*8($sp)");
ld ("%f12","$stdframe+4*8($sp)");
ld ("%f13","$stdframe+5*8($sp)");
ld ("%f14","$stdframe+6*8($sp)");
ld ("%f15","$stdframe+7*8($sp)");
&{$z? \&lmg:\&lm} ("%r10","%r15","$stdframe+8*8+10*$SIZE_T($sp)");
} else {
ld ("%f4","$stdframe+16*$SIZE_T+2*8($sp)");
ld ("%f6","$stdframe+16*$SIZE_T+3*8($sp)");
&{$z? \&lmg:\&lm} ("%r10","%r15","$stdframe+10*$SIZE_T($sp)");
}
br ("%r14");
SIZE ("__poly1305_blocks_vx",".-__poly1305_blocks_vx");
}
################
# static void poly1305_emit(void *ctx, unsigned char mac[16],
# const u32 nonce[4])
{
my ($ctx,$mac,$nonce) = map("%r$_",(2..4));
my ($h0,$h1,$h2,$d0,$d1)=map("%r$_",(5..9));
my ($mac,$nonce)=($inp,$len);
my ($h0,$h1,$h2,$d0,$d1,$d2)=map("%r$_",(5..10));
GLOBL ("poly1305_emit");
TYPE ("poly1305_emit","\@function");
ALIGN (16);
LABEL ("poly1305_emit");
&{$z? \&stmg:\&stm} ("%r6","%r9","6*$SIZE_T($sp)");
LABEL (".Lpoly1305_emit");
&{$z? \&stmg:\&stm} ("%r6","%r10","6*$SIZE_T($sp)");
lg ($h0,"0($ctx)");
lg ($h1,"8($ctx)");
lg ($h2,"16($ctx)");
lg ($d0,"0($ctx)");
lg ($d1,"8($ctx)");
lg ($d2,"16($ctx)");
llgfr ("%r0",$d0); # base 2^26 -> base 2^64
srlg ($h0,$d0,32);
llgfr ("%r1",$d1);
srlg ($h1,$d1,32);
srlg ($h2,$d2,32);
sllg ("%r0","%r0",26);
algr ($h0,"%r0");
sllg ("%r0",$h1,52);
srlg ($h1,$h1,12);
sllg ("%r1","%r1",14);
algr ($h0,"%r0");
alcgr ($h1,"%r1");
sllg ("%r0",$h2,40);
srlg ($h2,$h2,24);
lghi ("%r1",0);
algr ($h1,"%r0");
alcgr ($h2,"%r1");
llgf ("%r0","24($ctx)"); # is_base2_26
lcgr ("%r0","%r0");
xgr ($h0,$d0); # choose between radixes
xgr ($h1,$d1);
xgr ($h2,$d2);
ngr ($h0,"%r0");
ngr ($h1,"%r0");
ngr ($h2,"%r0");
xgr ($h0,$d0);
xgr ($h1,$d1);
xgr ($h2,$d2);
lghi ("%r0",5);
lghi ("%r1",0);
lgr ($d0,$h0);
lgr ($d1,$h1);
algr ($h0,"%r0"); # compare to modulus
algr ($h0,"%r0"); # compare to modulus
alcgr ($h1,"%r1");
alcgr ($h2,"%r1");
srlg ($h2,$h2,2); # did it borrow/carry?
slgr ("%r1",$h2); # 0-$h2>>2
lg ($h2,"0($nonce)"); # load nonce
lghi ("%r0",-1);
srlg ($h2,$h2,2); # did it borrow/carry?
slgr ("%r1",$h2); # 0-$h2>>2
lg ($d2,"0($nonce)"); # load nonce
lg ($ctx,"8($nonce)");
xgr ("%r0","%r1"); # ~%r1
xgr ($h0,$d0);
xgr ($h1,$d1);
ngr ($h0,"%r1");
ngr ($d0,"%r0");
ngr ($h1,"%r1");
ngr ($d1,"%r0");
ogr ($h0,$d0);
rllg ($d0,$h2,32); # flip nonce words
ogr ($h1,$d1);
xgr ($h0,$d0);
rllg ($d0,$d2,32); # flip nonce words
xgr ($h1,$d1);
rllg ($d1,$ctx,32);
algr ($h0,$d0); # accumulate nonce
algr ($h0,$d0); # accumulate nonce
alcgr ($h1,$d1);
strvg ($h0,"0($mac)"); # write little-endian result
strvg ($h0,"0($mac)"); # write little-endian result
strvg ($h1,"8($mac)");
&{$z? \&lmg:\&lm} ("%r6","%r9","6*$SIZE_T($sp)");
&{$z? \&lmg:\&lm} ("%r6","%r10","6*$SIZE_T($sp)");
br ("%r14");
SIZE ("poly1305_emit",".-poly1305_emit");
}
}
################
ALIGN (128);
ALIGN (16);
LABEL (".Lconst");
LONG (0x00060504,0x03020100,0x00161514,0x13121110); # vperm op[m[1],m[0]]
LONG (0x000c0b0a,0x09080706,0x001c1b1a,0x19181716); # vperm op[m[3],m[2]]
LONG (0x00000000,0x000f0e0d,0x00000000,0x001f1e1d); # vperm op[ - ,m[4]]
LONG (0x00000000,0x03ffffff,0x00000000,0x03ffffff); # [0,2^26-1,0,2^26-1]
LONG (0x0f0e0d0c,0x0b0a0908,0x07060504,0x03020100); # vperm op endian
LONG (0x04050607,0x14151617,0x0c0d0e0f,0x1c1d1e1f); # merge odd
LONG (0x07060504,0x03020100,0x17161514,0x13121110); # byte swap masks
LONG (0x0f0e0d0c,0x0b0a0908,0x1f1e1d1c,0x1b1a1918);
LONG (0x00000000,0x09080706,0x00000000,0x19181716);
LONG (0x00000000,0x00000000,0x00000000,0x0c0d0e0f); # magic tail masks
LONG (0x0c0d0e0f,0x00000000,0x00000000,0x00000000);
LONG (0x00000000,0x00000000,0x0c0d0e0f,0x00000000);
LONG (0xffffffff,0x00000000,0xffffffff,0xffffffff);
LONG (0xffffffff,0x00000000,0xffffffff,0x00000000);
LONG (0x00000000,0x00000000,0xffffffff,0x00000000);
STRING ("\"Poly1305 for s390x, CRYPTOGAMS by <appro\@openssl.org>\"");
PERLASM_END();
+1
View File
@@ -18,4 +18,5 @@ INCLUDE[poly1305-armv8.o]=..
GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-mips.o]=..
GENERATE[poly1305-c64xplus.S]=asm/poly1305-c64xplus.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-s390x.o]=..
GENERATE[poly1305-s390x.S]=asm/poly1305-s390x.pl $(PERLASM_SCHEME)
+175 -37
View File
@@ -11,9 +11,14 @@
#include <openssl/core_numbers.h>
#include <openssl/opensslv.h>
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include "internal/thread_once.h"
#include "internal/provider.h"
#include "internal/refcount.h"
#include "provider_local.h"
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function);
/*-
* Provider Object structure
@@ -25,6 +30,7 @@ struct provider_store_st; /* Forward declaration */
struct ossl_provider_st {
/* Flag bits */
unsigned int flag_initialized:1;
unsigned int flag_fallback:1;
/* OpenSSL library side data */
CRYPTO_REF_COUNT refcnt;
@@ -32,6 +38,7 @@ struct ossl_provider_st {
char *name;
DSO *module;
OSSL_provider_init_fn *init_function;
struct provider_store_st *store; /* The store this instance belongs to */
/* Provider side functions */
OSSL_provider_teardown_fn *teardown;
@@ -58,6 +65,7 @@ static int ossl_provider_cmp(const OSSL_PROVIDER * const *a,
struct provider_store_st {
STACK_OF(OSSL_PROVIDER) *providers;
CRYPTO_RWLOCK *lock;
unsigned int use_fallbacks:1;
};
static int provider_store_index = -1;
@@ -75,13 +83,37 @@ static void provider_store_free(void *vstore)
static void *provider_store_new(void)
{
struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
const struct predefined_providers_st *p = NULL;
if (store == NULL
|| (store->providers = sk_OSSL_PROVIDER_new(ossl_provider_cmp)) == NULL
|| (store->lock = CRYPTO_THREAD_lock_new()) == NULL) {
provider_store_free(store);
store = NULL;
return NULL;
}
store->use_fallbacks = 1;
for (p = predefined_providers; p->name != NULL; p++) {
OSSL_PROVIDER *prov = NULL;
/*
* We use the internal constructor directly here,
* otherwise we get a call loop
*/
prov = provider_new(p->name, p->init);
if (prov == NULL
|| sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
ossl_provider_free(prov);
provider_store_free(store);
CRYPTOerr(CRYPTO_F_PROVIDER_STORE_NEW, ERR_R_INTERNAL_ERROR);
return NULL;
}
prov->store = store;
if(p->is_fallback)
ossl_provider_set_fallback(prov);
}
return store;
}
@@ -112,20 +144,6 @@ static struct provider_store_st *get_provider_store(OPENSSL_CTX *libctx)
return store;
}
/*-
* Provider Object methods
* =======================
*/
int ossl_provider_upref(OSSL_PROVIDER *prov)
{
int ref = 0;
CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
return ref;
}
/* Finder, constructor and destructor */
OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
{
struct provider_store_st *store = NULL;
@@ -147,6 +165,39 @@ OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
return prov;
}
/*-
* Provider Object methods
* =======================
*/
static OSSL_PROVIDER *provider_new(const char *name,
OSSL_provider_init_fn *init_function)
{
OSSL_PROVIDER *prov = NULL;
if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
#ifndef HAVE_ATOMICS
|| (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
#endif
|| !ossl_provider_upref(prov) /* +1 One reference to be returned */
|| (prov->name = OPENSSL_strdup(name)) == NULL) {
ossl_provider_free(prov);
CRYPTOerr(CRYPTO_F_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
prov->init_function = init_function;
return prov;
}
int ossl_provider_upref(OSSL_PROVIDER *prov)
{
int ref = 0;
CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
return ref;
}
OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
OSSL_provider_init_fn *init_function)
{
@@ -164,18 +215,9 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
return NULL;
}
if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
#ifndef HAVE_ATOMICS
|| (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
#endif
|| !ossl_provider_upref(prov) /* +1 One reference to be returned */
|| (prov->name = OPENSSL_strdup(name)) == NULL) {
ossl_provider_free(prov);
CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
/* provider_new() generates an error, so no need here */
if ((prov = provider_new(name, init_function)) == NULL)
return NULL;
}
prov->init_function = init_function;
CRYPTO_THREAD_write_lock(store->lock);
if (!ossl_provider_upref(prov)) { /* +1 One reference for the store */
@@ -185,6 +227,8 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
ossl_provider_free(prov); /* -1 Store reference */
ossl_provider_free(prov); /* -1 Reference that was to be returned */
prov = NULL;
} else {
prov->store = store;
}
CRYPTO_THREAD_unlock(store->lock);
@@ -207,11 +251,13 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock);
/*
* When the refcount drops down to one, there is only one reference,
* the store.
* When the refcount drops below two, the store is the only
* possible reference, or it has already been taken away from
* the store (this may happen if a provider was activated
* because it's a fallback, but isn't currently used)
* When that happens, the provider is inactivated.
*/
if (ref == 1 && prov->flag_initialized) {
if (ref < 2 && prov->flag_initialized) {
if (prov->teardown != NULL)
prov->teardown();
prov->flag_initialized = 0;
@@ -246,7 +292,12 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
*/
static const OSSL_DISPATCH *core_dispatch; /* Define further down */
int ossl_provider_activate(OSSL_PROVIDER *prov)
/*
* Internal version that doesn't affect the store flags, and thereby avoid
* locking. Direct callers must remember to set the store flags when
* appropriate
*/
static int provider_activate(OSSL_PROVIDER *prov)
{
const OSSL_DISPATCH *provider_dispatch = NULL;
@@ -295,7 +346,7 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
if (prov->init_function == NULL
|| !prov->init_function(prov, core_dispatch, &provider_dispatch)) {
CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
ERR_add_error_data(2, "name=", prov->name);
DSO_free(prov->module);
prov->module = NULL;
@@ -329,6 +380,46 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
return 1;
}
int ossl_provider_activate(OSSL_PROVIDER *prov)
{
if (provider_activate(prov)) {
CRYPTO_THREAD_write_lock(prov->store->lock);
prov->store->use_fallbacks = 0;
CRYPTO_THREAD_unlock(prov->store->lock);
return 1;
}
return 0;
}
static int provider_forall_loaded(struct provider_store_st *store,
int *found_activated,
int (*cb)(OSSL_PROVIDER *provider,
void *cbdata),
void *cbdata)
{
int i;
int ret = 1;
int num_provs = sk_OSSL_PROVIDER_num(store->providers);
if (found_activated != NULL)
*found_activated = 0;
for (i = 0; i < num_provs; i++) {
OSSL_PROVIDER *prov =
sk_OSSL_PROVIDER_value(store->providers, i);
if (prov->flag_initialized) {
if (found_activated != NULL)
*found_activated = 1;
if (!(ret = cb(prov, cbdata)))
break;
}
}
return ret;
}
int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
int (*cb)(OSSL_PROVIDER *provider,
void *cbdata),
@@ -339,13 +430,50 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
struct provider_store_st *store = get_provider_store(ctx);
if (store != NULL) {
CRYPTO_THREAD_read_lock(store->lock);
for (i = 0; i < sk_OSSL_PROVIDER_num(store->providers); i++) {
OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(store->providers, i);
int found_activated = 0;
if (prov->flag_initialized
&& !(ret = cb(prov, cbdata)))
break;
CRYPTO_THREAD_read_lock(store->lock);
ret = provider_forall_loaded(store, &found_activated, cb, cbdata);
/*
* If there's nothing activated ever in this store, try to activate
* all fallbacks.
*/
if (!found_activated && store->use_fallbacks) {
int num_provs = sk_OSSL_PROVIDER_num(store->providers);
int activated_fallback_count = 0;
for (i = 0; i < num_provs; i++) {
OSSL_PROVIDER *prov =
sk_OSSL_PROVIDER_value(store->providers, i);
/*
* Note that we don't care if the activation succeeds or
* not. If it doesn't succeed, then the next loop will
* fail anyway.
*/
if (prov->flag_fallback) {
activated_fallback_count++;
provider_activate(prov);
}
}
if (activated_fallback_count > 0) {
/*
* We assume that all fallbacks have been added to the store
* before any fallback is activated.
* TODO: We may have to reconsider this, IF we find ourselves
* adding fallbacks after any previous fallback has been
* activated.
*/
store->use_fallbacks = 0;
/*
* Now that we've activated available fallbacks, try a
* second sweep
*/
ret = provider_forall_loaded(store, NULL, cb, cbdata);
}
}
CRYPTO_THREAD_unlock(store->lock);
}
@@ -353,6 +481,16 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
return ret;
}
/* Setters of Provider Object data */
int ossl_provider_set_fallback(OSSL_PROVIDER *prov)
{
if (prov == NULL)
return 0;
prov->flag_fallback = 1;
return 1;
}
/* Getters of Provider Object data */
const char *ossl_provider_name(OSSL_PROVIDER *prov)
{
+18
View File
@@ -0,0 +1,18 @@
/*
* 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 <openssl/core.h>
struct predefined_providers_st {
const char *name;
OSSL_provider_init_fn *init;
unsigned int is_fallback:1;
};
extern const struct predefined_providers_st predefined_providers[];
+18
View File
@@ -0,0 +1,18 @@
/*
* 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 <openssl/core.h>
#include "provider_local.h"
OSSL_provider_init_fn ossl_default_provider_init;
const struct predefined_providers_st predefined_providers[] = {
{ "default", ossl_default_provider_init, 1 },
{ NULL, NULL, 0 }
};
+1 -1
View File
@@ -1,6 +1,6 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
randfile.c rand_lib.c rand_err.c rand_egd.c \
randfile.c rand_lib.c rand_err.c rand_crng_test.c rand_egd.c \
rand_win.c rand_unix.c rand_vms.c drbg_lib.c drbg_ctr.c \
drbg_hash.c drbg_hmac.c
+8 -3
View File
@@ -67,7 +67,7 @@ static CRYPTO_THREAD_LOCAL private_drbg;
/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG";
static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
@@ -241,8 +241,8 @@ static RAND_DRBG *rand_drbg_new(int secure,
unsigned int flags,
RAND_DRBG *parent)
{
RAND_DRBG *drbg = secure ?
OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg));
RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg))
: OPENSSL_zalloc(sizeof(*drbg));
if (drbg == NULL) {
RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
@@ -254,8 +254,13 @@ static RAND_DRBG *rand_drbg_new(int secure,
drbg->parent = parent;
if (parent == NULL) {
#ifdef FIPS_MODE
drbg->get_entropy = rand_crngt_get_entropy;
drbg->cleanup_entropy = rand_crngt_cleanup_entropy;
#else
drbg->get_entropy = rand_drbg_get_entropy;
drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
#endif
#ifndef RAND_DRBG_GET_RANDOM_NONCE
drbg->get_nonce = rand_drbg_get_nonce;
drbg->cleanup_nonce = rand_drbg_cleanup_nonce;
+109
View File
@@ -0,0 +1,109 @@
/*
* 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
*/
/*
* Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
*/
#include <string.h>
#include "internal/rand_int.h"
#include "internal/thread_once.h"
#include "rand_lcl.h"
static RAND_POOL *crngt_pool;
static unsigned char *crngt_prev;
int (*crngt_get_entropy)(unsigned char *) = &rand_crngt_get_entropy_cb;
int rand_crngt_get_entropy_cb(unsigned char *buf)
{
size_t n;
unsigned char *p;
while ((n = rand_pool_acquire_entropy(crngt_pool)) != 0)
if (n >= CRNGT_BUFSIZ) {
p = rand_pool_detach(crngt_pool);
memcpy(crngt_prev, p, CRNGT_BUFSIZ);
rand_pool_reattach(crngt_pool, p);
return 1;
}
return 0;
}
void rand_crngt_cleanup(void)
{
rand_pool_free(crngt_pool);
OPENSSL_secure_free(crngt_prev);
crngt_pool = NULL;
crngt_prev = NULL;
}
int rand_crngt_init(void)
{
if ((crngt_pool = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL)
return 0;
if ((crngt_prev = OPENSSL_secure_malloc(CRNGT_BUFSIZ)) != NULL
&& crngt_get_entropy(crngt_prev))
return 1;
rand_crngt_cleanup();
return 0;
}
static CRYPTO_ONCE rand_crngt_init_flag = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_rand_crngt_init)
{
return OPENSSL_init_crypto(0, NULL)
&& rand_crngt_init()
&& OPENSSL_atexit(&rand_crngt_cleanup);
}
int rand_crngt_single_init(void)
{
return RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init);
}
size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len,
int prediction_resistance)
{
unsigned char buf[CRNGT_BUFSIZ];
RAND_POOL *pool;
size_t q, r = 0, s, t = 0;
int attempts = 3;
if (!RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init))
return 0;
if ((pool = rand_pool_new(entropy, min_len, max_len)) == NULL)
return 0;
while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
s = q > sizeof(buf) ? sizeof(buf) : q;
if (!crngt_get_entropy(buf)
|| memcmp(crngt_prev, buf, CRNGT_BUFSIZ) == 0
|| !rand_pool_add(pool, buf, s, s * 8))
goto err;
memcpy(crngt_prev, buf, CRNGT_BUFSIZ);
t += s;
attempts++;
}
r = t;
*pout = rand_pool_detach(pool);
err:
rand_pool_free(pool);
return r;
}
void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen)
{
OPENSSL_secure_clear_free(out, outlen);
}
+27 -2
View File
@@ -33,7 +33,15 @@
# define MASTER_RESEED_TIME_INTERVAL (60*60) /* 1 hour */
# define SLAVE_RESEED_TIME_INTERVAL (7*60) /* 7 minutes */
/*
* The number of bytes that constitutes an atomic lump of entropy with respect
* to the FIPS 140-2 section 4.9.2 Conditional Tests. The size is somewhat
* arbitrary, the smaller the value, the less entropy is consumed on first
* read but the higher the probability of the test failing by accident.
*
* The value is in bytes.
*/
#define CRNGT_BUFSIZ 16
/*
* Maximum input size for the DRBG (entropy, nonce, personalization string)
@@ -44,7 +52,8 @@
*/
# define DRBG_MAX_LENGTH INT32_MAX
/* The default nonce */
# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG"
/*
* Maximum allocation size for RANDOM_POOL buffers
@@ -321,4 +330,20 @@ int drbg_ctr_init(RAND_DRBG *drbg);
int drbg_hash_init(RAND_DRBG *drbg);
int drbg_hmac_init(RAND_DRBG *drbg);
/*
* Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
* These need to be exposed for the unit tests.
*/
int rand_crngt_get_entropy_cb(unsigned char *buf);
extern int (*crngt_get_entropy)(unsigned char *);
int rand_crngt_init(void);
void rand_crngt_cleanup(void);
/*
* Expose the run once initialisation function for the unit tests because.
* they need to restart from scratch to validate the first block is skipped
* properly.
*/
int rand_crngt_single_init(void);
#endif
+6 -5
View File
@@ -137,7 +137,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
size_t entropy_available = 0;
RAND_POOL *pool;
if (drbg->parent && drbg->strength > drbg->parent->strength) {
if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
@@ -155,7 +155,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
return 0;
}
if (drbg->parent) {
if (drbg->parent != NULL) {
size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
@@ -235,8 +235,9 @@ size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
struct {
void * instance;
int count;
} data = { 0 };
} data;
memset(&data, 0, sizeof(data));
pool = rand_pool_new(0, min_len, max_len);
if (pool == NULL)
return 0;
@@ -402,7 +403,7 @@ int RAND_poll(void)
} else {
/* fill random pool and seed the current legacy RNG */
pool = rand_pool_new(RAND_DRBG_STRENGTH,
RAND_DRBG_STRENGTH / 8,
(RAND_DRBG_STRENGTH + 7) / 8,
RAND_POOL_MAX_LENGTH);
if (pool == NULL)
return 0;
@@ -689,7 +690,7 @@ unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
if (pool->buffer == NULL) {
RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR);
return 0;
return NULL;
}
return pool->buffer + pool->len;
+8 -2
View File
@@ -615,7 +615,10 @@ int rand_pool_add_nonce_data(RAND_POOL *pool)
pid_t pid;
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add process id, thread id, and a high resolution timestamp to
@@ -634,7 +637,10 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
struct {
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add some noise from the thread id and a high resolution timer.
+8 -2
View File
@@ -475,7 +475,10 @@ int rand_pool_add_nonce_data(RAND_POOL *pool)
pid_t pid;
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add process id, thread id, and a high resolution timestamp
@@ -499,7 +502,10 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
struct {
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add some noise from the thread id and a high resolution timer.
+8 -2
View File
@@ -125,7 +125,10 @@ int rand_pool_add_nonce_data(RAND_POOL *pool)
DWORD pid;
DWORD tid;
FILETIME time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add process id, thread id, and a high resolution timestamp to
@@ -144,7 +147,10 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
struct {
DWORD tid;
LARGE_INTEGER time;
} data = { 0 };
} data;
/* Erase the entire structure including any padding */
memset(&data, 0, sizeof(data));
/*
* Add some noise from the thread id and a high resolution timer.
+1 -1
View File
@@ -254,7 +254,7 @@ const char *RAND_file_name(char *buf, size_t size)
size_t len;
int use_randfile = 1;
#if defined(_WIN32) && defined(CP_UTF8)
#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
DWORD envlen;
WCHAR *var;
+1 -1
View File
@@ -447,7 +447,7 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
RSA_PSS_PARAMS_free(pss);
if (!rv)
return 0;
} else if (!sig && BIO_puts(bp, "\n") <= 0) {
} else if (BIO_puts(bp, "\n") <= 0) {
return 0;
}
if (sig)
+1 -2
View File
@@ -393,8 +393,7 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
ok = 0;
}
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
#endif /* FIPS_MODE */
+16 -16
View File
@@ -234,25 +234,25 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
good &= constant_time_ge(tlen, mlen);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
* Move the result in-place by |dblen|-|mdlen|-1-|mlen| bytes to the left.
* Then if |good| move |mlen| bytes from |db|+|mdlen|+1 to |to|.
* Otherwise leave |to| unchanged.
* Copy the memory back in a way that does not reveal the size of
* the data being copied via a timing side channel. This requires copying
* parts of the buffer multiple times based on the bits set in the real
* length. Clear bits do a non-copy with identical access pattern.
* The loop below has overall complexity of O(N*log(N)).
*/
tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen),
dblen - mdlen - 1, tlen);
msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
mlen = dblen - msg_index;
for (mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(msg_index, dblen);
msg_index -= tlen & equals; /* rewind at EOF */
mask &= ~equals; /* mask = 0 at EOF */
to[i] = constant_time_select_8(mask, db[msg_index++], to[i]);
for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) {
mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0);
for (i = mdlen + 1; i < dblen - msg_index; i++)
db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]);
}
for (i = 0; i < tlen; i++) {
mask = good & constant_time_lt(i, mlen);
to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]);
}
/*
+5 -9
View File
@@ -148,8 +148,7 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
*/
r = BN_bn2binpad(ret, to, num);
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -354,8 +353,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
*/
r = BN_bn2binpad(res, to, num);
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -481,11 +479,10 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
goto err;
}
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err_clear_last_constant_time(r >= 0);
err_clear_last_constant_time(1 & ~constant_time_msb(r));
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
@@ -581,8 +578,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err:
if (ctx != NULL)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
+16 -16
View File
@@ -226,25 +226,25 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
good &= constant_time_ge(tlen, mlen);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
* Move the result in-place by |num|-11-|mlen| bytes to the left.
* Then if |good| move |mlen| bytes from |em|+11 to |to|.
* Otherwise leave |to| unchanged.
* Copy the memory back in a way that does not reveal the size of
* the data being copied via a timing side channel. This requires copying
* parts of the buffer multiple times based on the bits set in the real
* length. Clear bits do a non-copy with identical access pattern.
* The loop below has overall complexity of O(N*log(N)).
*/
tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
num - 11, tlen);
msg_index = constant_time_select_int(good, msg_index, num - tlen);
mlen = num - msg_index;
for (mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(msg_index, num);
msg_index -= tlen & equals; /* rewind at EOF */
mask &= ~equals; /* mask = 0 at EOF */
to[i] = constant_time_select_8(mask, em[msg_index++], to[i]);
for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
for (i = 11; i < num - msg_index; i++)
em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
}
for (i = 0; i < tlen; i++) {
mask = good & constant_time_lt(i, mlen);
to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
+1 -1
View File
@@ -71,7 +71,7 @@ int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2,
if (!rsa_check_public_exponent(e)) {
RSAerr(RSA_F_RSA_FIPS186_4_GEN_PROB_PRIMES,
RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
goto err;
return 0;
}
/* (Step 3) Determine strength and check rand generator strength is ok -
+16 -16
View File
@@ -141,25 +141,25 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
* Move the result in-place by |num|-11-|mlen| bytes to the left.
* Then if |good| move |mlen| bytes from |em|+11 to |to|.
* Otherwise leave |to| unchanged.
* Copy the memory back in a way that does not reveal the size of
* the data being copied via a timing side channel. This requires copying
* parts of the buffer multiple times based on the bits set in the real
* length. Clear bits do a non-copy with identical access pattern.
* The loop below has overall complexity of O(N*log(N)).
*/
tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
num - 11, tlen);
msg_index = constant_time_select_int(good, msg_index, num - tlen);
mlen = num - msg_index;
for (mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(msg_index, num);
msg_index -= tlen & equals; /* rewind at EOF */
mask &= ~equals; /* mask = 0 at EOF */
to[i] = constant_time_select_8(mask, em[msg_index++], to[i]);
for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
for (i = 11; i < num - msg_index; i++)
em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
}
for (i = 0; i < tlen; i++) {
mask = good & constant_time_lt(i, mlen);
to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
+2 -4
View File
@@ -133,8 +133,7 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
ret = 1;
err:
if (ctx)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_CTX_free(ctx2);
@@ -188,8 +187,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
ok = 1;
error:
if (ctx)
BN_CTX_end(ctx);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
if (ok)
+4
View File
@@ -24,11 +24,15 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
return NULL;
}
#if !defined(_WIN32_WCE)
/* 0x400 is the spin count value suggested in the documentation */
if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) {
OPENSSL_free(lock);
return NULL;
}
#else
InitializeCriticalSection(lock);
#endif
return lock;
}
+19 -23
View File
@@ -119,7 +119,7 @@ struct trace_category_st {
#define TRACE_CATEGORY_(name) { #name, OSSL_TRACE_CATEGORY_##name }
static const struct trace_category_st trace_categories[] = {
TRACE_CATEGORY_(ANY),
TRACE_CATEGORY_(ALL),
TRACE_CATEGORY_(TRACE),
TRACE_CATEGORY_(INIT),
TRACE_CATEGORY_(TLS),
@@ -328,12 +328,11 @@ void ossl_trace_cleanup(void)
int OSSL_trace_set_channel(int category, BIO *channel)
{
#ifndef OPENSSL_NO_TRACE
if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM
|| !set_trace_data(category, SIMPLE_CHANNEL, &channel, NULL, NULL,
trace_attach_cb, trace_detach_cb))
return 0;
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, SIMPLE_CHANNEL, &channel, NULL, NULL,
trace_attach_cb, trace_detach_cb);
#endif
return 1;
return 0;
}
#ifndef OPENSSL_NO_TRACE
@@ -367,7 +366,7 @@ int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data)
struct trace_data_st *trace_data = NULL;
if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM)
goto err;
return 0;
if (callback != NULL) {
if ((channel = BIO_new(&trace_method)) == NULL
@@ -386,41 +385,34 @@ int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data)
trace_attach_w_callback_cb, trace_detach_cb))
goto err;
goto done;
return 1;
err:
BIO_free(channel);
OPENSSL_free(trace_data);
return 0;
done:
#endif
return 1;
return 0;
}
int OSSL_trace_set_prefix(int category, const char *prefix)
{
int rv = 1;
#ifndef OPENSSL_NO_TRACE
if (category >= 0 || category < OSSL_TRACE_CATEGORY_NUM)
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, 0, NULL, &prefix, NULL,
trace_attach_cb, trace_detach_cb);
rv = 0;
#endif
return rv;
return 0;
}
int OSSL_trace_set_suffix(int category, const char *suffix)
{
int rv = 1;
#ifndef OPENSSL_NO_TRACE
if (category >= 0 || category < OSSL_TRACE_CATEGORY_NUM)
if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM)
return set_trace_data(category, 0, NULL, NULL, &suffix,
trace_attach_cb, trace_detach_cb);
rv = 0;
#endif
return rv;
return 0;
}
#ifndef OPENSSL_NO_TRACE
@@ -430,7 +422,7 @@ static int ossl_trace_get_category(int category)
return -1;
if (trace_channels[category].bio != NULL)
return category;
return OSSL_TRACE_CATEGORY_ANY;
return OSSL_TRACE_CATEGORY_ALL;
}
#endif
@@ -439,7 +431,8 @@ int OSSL_trace_enabled(int category)
int ret = 0;
#ifndef OPENSSL_NO_TRACE
category = ossl_trace_get_category(category);
ret = trace_channels[category].bio != NULL;
if (category >= 0)
ret = trace_channels[category].bio != NULL;
#endif
return ret;
}
@@ -451,6 +444,9 @@ BIO *OSSL_trace_begin(int category)
char *prefix = NULL;
category = ossl_trace_get_category(category);
if (category < 0)
return NULL;
channel = trace_channels[category].bio;
prefix = trace_channels[category].prefix;
+9 -6
View File
@@ -284,7 +284,7 @@ int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
s = sig->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0) {
if (BIO_write(bp, "\n", 1) <= 0)
if (i > 0 && BIO_write(bp, "\n", 1) <= 0)
return 0;
if (BIO_indent(bp, indent, indent) <= 0)
return 0;
@@ -302,11 +302,14 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
const ASN1_STRING *sig)
{
int sig_nid;
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
int indent = 4;
if (BIO_printf(bp, "%*sSignature Algorithm: ", indent, "") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
if (sig && BIO_printf(bp, "\n%*sSignature Value:", indent, "") <= 0)
return 0;
sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid != NID_undef) {
int pkey_nid, dig_nid;
@@ -314,13 +317,13 @@ int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
if (ameth && ameth->sig_print)
return ameth->sig_print(bp, sigalg, sig, 9, 0);
return ameth->sig_print(bp, sigalg, sig, indent + 4, 0);
}
}
if (sig)
return X509_signature_dump(bp, sig, 9);
else if (BIO_puts(bp, "\n") <= 0)
if (BIO_write(bp, "\n", 1) != 1)
return 0;
if (sig)
return X509_signature_dump(bp, sig, indent + 4);
return 1;
}
+1 -1
View File
@@ -42,7 +42,7 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
char *tmp;
if (akeyid->keyid) {
tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length);
X509V3_add_value("keyid", tmp, &extlist);
X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL, tmp, &extlist);
OPENSSL_free(tmp);
}
if (akeyid->issuer)
-1
View File
@@ -183,7 +183,6 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
BIO_printf(out, ":%X", p[0] << 8 | p[1]);
p += 2;
}
BIO_puts(out, "\n");
} else {
BIO_printf(out, "IP Address:<invalid>");
break;
+14 -7
View File
@@ -403,12 +403,15 @@ static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
POLICYINFO *pinfo;
/* First print out the policy OIDs */
for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
if (i > 0)
BIO_puts(out, "\n");
pinfo = sk_POLICYINFO_value(pol, i);
BIO_printf(out, "%*sPolicy: ", indent, "");
i2a_ASN1_OBJECT(out, pinfo->policyid);
BIO_puts(out, "\n");
if (pinfo->qualifiers)
if (pinfo->qualifiers) {
BIO_puts(out, "\n");
print_qualifiers(out, pinfo->qualifiers, indent + 2);
}
}
return 1;
}
@@ -419,10 +422,12 @@ static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
POLICYQUALINFO *qualinfo;
int i;
for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
if (i > 0)
BIO_puts(out, "\n");
qualinfo = sk_POLICYQUALINFO_value(quals, i);
switch (OBJ_obj2nid(qualinfo->pqualid)) {
case NID_id_qt_cps:
BIO_printf(out, "%*sCPS: %s\n", indent, "",
BIO_printf(out, "%*sCPS: %s", indent, "",
qualinfo->d.cpsuri->data);
break;
@@ -435,7 +440,6 @@ static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
i2a_ASN1_OBJECT(out, qualinfo->pqualid);
BIO_puts(out, "\n");
break;
}
}
@@ -467,10 +471,11 @@ static void print_notice(BIO *out, USERNOTICE *notice, int indent)
OPENSSL_free(tmp);
}
}
BIO_puts(out, "\n");
if (notice->exptext)
BIO_puts(out, "\n");
}
if (notice->exptext)
BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
BIO_printf(out, "%*sExplicit Text: %s", indent, "",
notice->exptext->data);
}
@@ -484,8 +489,10 @@ void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
BIO_puts(out, "\n");
BIO_printf(out, "%*s%s\n", indent + 2, "",
node_data_critical(dat) ? "Critical" : "Non Critical");
if (dat->qualifier_set)
if (dat->qualifier_set) {
print_qualifiers(out, dat->qualifier_set, indent + 2);
BIO_puts(out, "\n");
}
else
BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
}
+4 -2
View File
@@ -410,9 +410,10 @@ static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
{
int i;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
if (i > 0)
BIO_puts(out, "\n");
BIO_printf(out, "%*s", indent + 2, "");
GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
BIO_puts(out, "\n");
}
return 1;
}
@@ -463,7 +464,8 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
DIST_POINT *point;
int i;
for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
BIO_puts(out, "\n");
if (i > 0)
BIO_puts(out, "\n");
point = sk_DIST_POINT_value(crld, i);
if (point->distpoint)
print_distpoint(out, point->distpoint, indent);
+4 -1
View File
@@ -158,6 +158,8 @@ static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
NAME_CONSTRAINTS *ncons = a;
do_i2r_name_constraints(method, ncons->permittedSubtrees,
bp, ind, "Permitted");
if (ncons->permittedSubtrees && ncons->excludedSubtrees)
BIO_puts(bp, "\n");
do_i2r_name_constraints(method, ncons->excludedSubtrees,
bp, ind, "Excluded");
return 1;
@@ -172,13 +174,14 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
if (sk_GENERAL_SUBTREE_num(trees) > 0)
BIO_printf(bp, "%*s%s:\n", ind, "", name);
for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
if (i > 0)
BIO_puts(bp, "\n");
tree = sk_GENERAL_SUBTREE_value(trees, i);
BIO_printf(bp, "%*s", ind + 2, "");
if (tree->base->type == GEN_IPADD)
print_nc_ipadd(bp, tree->base->d.ip);
else
GENERAL_NAME_print(bp, tree->base);
BIO_puts(bp, "\n");
}
return 1;
}
+1 -2
View File
@@ -75,9 +75,8 @@ static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
BIO_puts(out, "\n");
BIO_printf(out, "%*sPolicy Language: ", indent, "");
i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
BIO_puts(out, "\n");
if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
BIO_printf(out, "\n%*sPolicy Text: %s", indent, "",
pci->proxyPolicy->policy->data);
return 1;
}
+4 -3
View File
@@ -34,8 +34,11 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
BIO_puts(out, "<EMPTY>\n");
}
for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
if (ml)
if (ml) {
if (i > 0)
BIO_printf(out, "\n");
BIO_printf(out, "%*s", indent, "");
}
else if (i > 0)
BIO_printf(out, ", ");
nval = sk_CONF_VALUE_value(val, i);
@@ -59,8 +62,6 @@ void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
}
}
#endif
if (ml)
BIO_puts(out, "\n");
}
}