Latest update
This commit is contained in:
@@ -9,6 +9,17 @@
|
||||
|
||||
Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
|
||||
|
||||
*) Added command 'openssl kdf' that uses the EVP_KDF API.
|
||||
[Shane Lontis]
|
||||
|
||||
*) Added command 'openssl mac' that uses the EVP_MAC API.
|
||||
[Shane Lontis]
|
||||
|
||||
*) Added OPENSSL_info() to get diverse built-in OpenSSL data, such
|
||||
as default directories. Also added the command 'openssl info'
|
||||
for scripting purposes.
|
||||
[Richard Levitte]
|
||||
|
||||
*) The functions AES_ige_encrypt() and AES_bi_ige_encrypt() have been
|
||||
deprecated. These undocumented functions were never integrated into the EVP
|
||||
layer and implement the AES Infinite Garble Extension (IGE) mode and AES
|
||||
|
||||
@@ -32,7 +32,10 @@ my %shared_info;
|
||||
return {
|
||||
%{$shared_info{'gnu-shared'}},
|
||||
shared_defflag => '-Wl,--version-script=',
|
||||
dso_ldflags => '-z defs',
|
||||
dso_ldflags =>
|
||||
$disabled{asan} && $disabled{msan} && $disabled{ubsan}
|
||||
? '-z defs'
|
||||
: '',
|
||||
};
|
||||
},
|
||||
'bsd-gcc-shared' => sub { return $shared_info{'linux-shared'}; },
|
||||
|
||||
@@ -892,9 +892,6 @@ while (@argvcopy)
|
||||
elsif (/^-static$/)
|
||||
{
|
||||
push @{$useradd{LDFLAGS}}, $_;
|
||||
$disabled{"pic"} = "forced";
|
||||
$disabled{"shared"} = "forced";
|
||||
$disabled{"threads"} = "forced";
|
||||
}
|
||||
elsif (/^-D(.*)$/)
|
||||
{
|
||||
@@ -1006,20 +1003,30 @@ if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
|
||||
"***** any of asan, msan or ubsan\n";
|
||||
}
|
||||
|
||||
my @tocheckfor = (keys %disabled);
|
||||
while (@tocheckfor) {
|
||||
my %new_tocheckfor = ();
|
||||
my @cascade_copy = (@disable_cascades);
|
||||
while (@cascade_copy) {
|
||||
my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy);
|
||||
if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
|
||||
foreach(grep { !defined($disabled{$_}) } @$descendents) {
|
||||
$new_tocheckfor{$_} = 1; $disabled{$_} = "forced";
|
||||
sub disable {
|
||||
my $disable_type = shift;
|
||||
|
||||
for (@_) {
|
||||
$disabled{$_} = $disable_type;
|
||||
}
|
||||
|
||||
my @tocheckfor = (@_ ? @_ : keys %disabled);
|
||||
while (@tocheckfor) {
|
||||
my %new_tocheckfor = ();
|
||||
my @cascade_copy = (@disable_cascades);
|
||||
while (@cascade_copy) {
|
||||
my ($test, $descendents) =
|
||||
(shift @cascade_copy, shift @cascade_copy);
|
||||
if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
|
||||
foreach (grep { !defined($disabled{$_}) } @$descendents) {
|
||||
$new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
|
||||
}
|
||||
}
|
||||
}
|
||||
@tocheckfor = (keys %new_tocheckfor);
|
||||
}
|
||||
@tocheckfor = (keys %new_tocheckfor);
|
||||
}
|
||||
disable(); # First cascade run
|
||||
|
||||
our $die = sub { die @_; };
|
||||
if ($target eq "TABLE") {
|
||||
@@ -1144,6 +1151,8 @@ $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_l
|
||||
my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
|
||||
$config{conf_files} = [ sort keys %conf_files ];
|
||||
|
||||
# Using sub disable within these loops may prove fragile, so we run
|
||||
# a cascade afterwards
|
||||
foreach my $feature (@{$target{disable}}) {
|
||||
if (exists $deprecated_disablables{$feature}) {
|
||||
warn "***** config $target disables deprecated feature $feature\n";
|
||||
@@ -1162,6 +1171,7 @@ foreach my $feature (@{$target{enable}}) {
|
||||
delete $disabled{$feature};
|
||||
}
|
||||
}
|
||||
disable(); # Run a cascade now
|
||||
|
||||
$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
|
||||
$target{cxxflags}//=$target{cflags} if $target{CXX};
|
||||
@@ -1202,6 +1212,22 @@ foreach (keys %user) {
|
||||
delete $config{$_} unless defined $config{$_};
|
||||
}
|
||||
|
||||
# Finish up %config by appending things the user gave us on the command line
|
||||
# apart from "make variables"
|
||||
foreach (keys %useradd) {
|
||||
# The must all be lists, so we assert that here
|
||||
die "internal error: \$useradd{$_} isn't an ARRAY\n"
|
||||
unless ref $useradd{$_} eq 'ARRAY';
|
||||
|
||||
if (defined $config{$_}) {
|
||||
push @{$config{$_}}, @{$useradd{$_}};
|
||||
} else {
|
||||
$config{$_} = [ @{$useradd{$_}} ];
|
||||
}
|
||||
}
|
||||
# At this point, we can forget everything about %user and %useradd,
|
||||
# because it's now all been merged into the corresponding $config entry
|
||||
|
||||
# Allow overriding the build file name
|
||||
$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
|
||||
|
||||
@@ -1281,8 +1307,7 @@ if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
|
||||
}
|
||||
|
||||
if ($target =~ /linux.*-mips/ && !$disabled{asm}
|
||||
&& !grep { $_ !~ /-m(ips|arch=)/ } (@{$user{CFLAGS}},
|
||||
@{$useradd{CFLAGS}})) {
|
||||
&& !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
|
||||
# minimally required architecture flags for assembly modules
|
||||
my $value;
|
||||
$value = '-mips2' if ($target =~ /mips32/);
|
||||
@@ -1296,7 +1321,7 @@ unless ($disabled{threads}) {
|
||||
if ($auto_threads) {
|
||||
# Enabled by default, disable it forcibly if unavailable
|
||||
if ($target{thread_scheme} eq "(unknown)") {
|
||||
$disabled{threads} = "unavailable";
|
||||
disable("unavailable", 'threads');
|
||||
}
|
||||
} else {
|
||||
# The user chose to enable threads explicitly, let's see
|
||||
@@ -1307,8 +1332,7 @@ unless ($disabled{threads}) {
|
||||
# system-dependent compiler options that are necessary. We
|
||||
# can't truly check that the given options are correct, but
|
||||
# we expect the user to know what [s]He is doing.
|
||||
if (!@{$user{CFLAGS}} && !@{$useradd{CFLAGS}}
|
||||
&& !@{$user{CPPDEFINES}} && !@{$useradd{CPPDEFINES}}) {
|
||||
if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
|
||||
die "You asked for multi-threading support, but didn't\n"
|
||||
,"provide any system-specific compiler options\n";
|
||||
}
|
||||
@@ -1316,6 +1340,27 @@ unless ($disabled{threads}) {
|
||||
}
|
||||
}
|
||||
|
||||
# Find out if clang's sanitizers have been enabled with -fsanitize
|
||||
# flags and ensure that the corresponding %disabled elements area
|
||||
# removed to reflect that the sanitizers are indeed enabled.
|
||||
my %detected_sanitizers = ();
|
||||
foreach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) {
|
||||
(my $checks = $_) =~ s/^-fsanitize=//;
|
||||
foreach (split /,/, $checks) {
|
||||
my $d = { address => 'asan',
|
||||
undefined => 'ubsan',
|
||||
memory => 'msan' } -> {$_};
|
||||
next unless defined $d;
|
||||
|
||||
$detected_sanitizers{$d} = 1;
|
||||
if (defined $disabled{$d}) {
|
||||
die "***** Conflict between disabling $d and enabling $_ sanitizer"
|
||||
if $disabled{$d} ne "default";
|
||||
delete $disabled{$d};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If threads still aren't disabled, add a C macro to ensure the source
|
||||
# code knows about it. Any other flag is taken care of by the configs.
|
||||
unless($disabled{threads}) {
|
||||
@@ -1332,8 +1377,7 @@ if ($target{shared_target} eq "")
|
||||
{
|
||||
$no_shared_warn = 1
|
||||
if (!$disabled{shared} || !$disabled{"dynamic-engine"});
|
||||
$disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
|
||||
$disabled{module} = "no-shared-target";
|
||||
disable('no-shared-target', 'pic');
|
||||
}
|
||||
|
||||
if ($disabled{"dynamic-engine"}) {
|
||||
@@ -1344,12 +1388,12 @@ if ($disabled{"dynamic-engine"}) {
|
||||
$config{dynamic_engines} = 1;
|
||||
}
|
||||
|
||||
unless ($disabled{asan}) {
|
||||
unless ($disabled{asan} || defined $detected_sanitizers{asan}) {
|
||||
push @{$config{cflags}}, "-fsanitize=address";
|
||||
push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX};
|
||||
}
|
||||
|
||||
unless ($disabled{ubsan}) {
|
||||
unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) {
|
||||
# -DPEDANTIC or -fnosanitize=alignment may also be required on some
|
||||
# platforms.
|
||||
push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
|
||||
@@ -1357,7 +1401,7 @@ unless ($disabled{ubsan}) {
|
||||
if $config{CXX};
|
||||
}
|
||||
|
||||
unless ($disabled{msan}) {
|
||||
unless ($disabled{msan} || defined $detected_sanitizers{msan}) {
|
||||
push @{$config{cflags}}, "-fsanitize=memory";
|
||||
push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX};
|
||||
}
|
||||
@@ -1482,7 +1526,7 @@ if (!$disabled{makedepend}) {
|
||||
# In all other cases, we look for 'makedepend', and disable the
|
||||
# capability if not found.
|
||||
$config{makedepprog} = which('makedepend');
|
||||
$disabled{makedepend} = "unavailable" unless $config{makedepprog};
|
||||
disable('unavailable', 'makedepend') unless $config{makedepprog};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1569,12 +1613,17 @@ if ($strict_warnings)
|
||||
@{$clang_devteam_warn{CXXFLAGS}}
|
||||
if (defined($predefined_CXX{__clang__}));
|
||||
}
|
||||
|
||||
if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
|
||||
disable('static', 'pic', 'threads');
|
||||
}
|
||||
|
||||
foreach my $idx (qw(CFLAGS CXXFLAGS))
|
||||
{
|
||||
$useradd{$idx} = [ map { $_ eq '--ossl-strict-warnings'
|
||||
? @{$strict_warnings_collection{$idx}}
|
||||
: ( $_ ) }
|
||||
@{$useradd{$idx}} ];
|
||||
$config{$idx} = [ map { $_ eq '--ossl-strict-warnings'
|
||||
? @{$strict_warnings_collection{$idx}}
|
||||
: ( $_ ) }
|
||||
@{$config{$idx}} ];
|
||||
}
|
||||
|
||||
unless ($disabled{"crypto-mdebug-backtrace"})
|
||||
@@ -1603,15 +1652,15 @@ unless ($disabled{afalgeng}) {
|
||||
($mi2) = $mi2 =~ /(\d+)/;
|
||||
my $ver = $ma*10000 + $mi1*100 + $mi2;
|
||||
if ($ver < $minver) {
|
||||
$disabled{afalgeng} = "too-old-kernel";
|
||||
disable('too-old-kernel', 'afalgeng');
|
||||
} else {
|
||||
push @{$config{engdirs}}, "afalg";
|
||||
}
|
||||
} else {
|
||||
$disabled{afalgeng} = "cross-compiling";
|
||||
disable('cross-compiling', 'afalgeng');
|
||||
}
|
||||
} else {
|
||||
$disabled{afalgeng} = "not-linux";
|
||||
disable('not-linux', 'afalgeng');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1629,29 +1678,15 @@ unless ($disabled{ktls}) {
|
||||
my @verstr = split(" ",`cat $usr/include/linux/version.h | grep LINUX_VERSION_CODE`);
|
||||
|
||||
if ($verstr[2] < $minver) {
|
||||
$disabled{ktls} = "too-old-kernel";
|
||||
disable('too-old-kernel', 'ktls');
|
||||
}
|
||||
} else {
|
||||
$disabled{ktls} = "not-linux";
|
||||
disable('not-linux', 'ktls');
|
||||
}
|
||||
}
|
||||
|
||||
push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
|
||||
|
||||
# Finish up %config by appending things the user gave us on the command line
|
||||
# apart from "make variables"
|
||||
foreach (keys %useradd) {
|
||||
# The must all be lists, so we assert that here
|
||||
die "internal error: \$useradd{$_} isn't an ARRAY\n"
|
||||
unless ref $useradd{$_} eq 'ARRAY';
|
||||
|
||||
if (defined $config{$_}) {
|
||||
push @{$config{$_}}, @{$useradd{$_}};
|
||||
} else {
|
||||
$config{$_} = [ @{$useradd{$_}} ];
|
||||
}
|
||||
}
|
||||
|
||||
# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
|
||||
|
||||
# If we use the unified build, collect information from build.info files
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
Major changes between OpenSSL 1.1.1 and OpenSSL 3.0.0 [under development]
|
||||
|
||||
o Added 'openssl mac' that uses the EVP_MAC API.
|
||||
o Added 'openssl kdf' that uses the EVP_KDF API.
|
||||
o Add OPENSSL_info() and 'openssl info' to get built-in data.
|
||||
o Add support for enabling instrumentation through trace and debug
|
||||
output.
|
||||
o Changed our version number scheme and set the next major release to
|
||||
@@ -14,6 +17,8 @@
|
||||
o Added EVP_MAC, an EVP layer MAC API, and a generic EVP_PKEY to EVP_MAC
|
||||
bridge.
|
||||
o Removed the heartbeat message in DTLS feature.
|
||||
o Added EVP_KDF, an EVP layer KDF API, and a generic EVP_PKEY to EVP_KDF
|
||||
bridge.
|
||||
|
||||
Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018]
|
||||
|
||||
|
||||
+5
-7
@@ -170,17 +170,17 @@ int asn1parse_main(int argc, char **argv)
|
||||
if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
|
||||
goto end;
|
||||
|
||||
if ((buf = BUF_MEM_new()) == NULL)
|
||||
goto end;
|
||||
if (strictpem) {
|
||||
if (PEM_read_bio(in, &name, &header, &str, &num) !=
|
||||
1) {
|
||||
if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
|
||||
BIO_printf(bio_err, "Error reading PEM file\n");
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
buf->data = (char *)str;
|
||||
buf->length = buf->max = num;
|
||||
} else {
|
||||
|
||||
if ((buf = BUF_MEM_new()) == NULL)
|
||||
goto end;
|
||||
if (!BUF_MEM_grow(buf, BUFSIZ * 8))
|
||||
goto end; /* Pre-allocate :-) */
|
||||
|
||||
@@ -303,8 +303,6 @@ int asn1parse_main(int argc, char **argv)
|
||||
BUF_MEM_free(buf);
|
||||
OPENSSL_free(name);
|
||||
OPENSSL_free(header);
|
||||
if (strictpem)
|
||||
OPENSSL_free(str);
|
||||
ASN1_TYPE_free(at);
|
||||
sk_OPENSSL_STRING_free(osk);
|
||||
return ret;
|
||||
|
||||
+3
-2
@@ -2,10 +2,11 @@
|
||||
qw(openssl.c
|
||||
asn1pars.c ca.c ciphers.c cms.c crl.c crl2p7.c dgst.c dhparam.c
|
||||
dsa.c dsaparam.c ec.c ecparam.c enc.c engine.c errstr.c gendsa.c
|
||||
genpkey.c genrsa.c mac.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c
|
||||
genpkey.c genrsa.c kdf.c mac.c nseq.c ocsp.c passwd.c pkcs12.c pkcs7.c
|
||||
pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c
|
||||
rsautl.c s_client.c s_server.c s_time.c sess_id.c smime.c speed.c
|
||||
spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c);
|
||||
spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c
|
||||
info.c);
|
||||
our @apps_lib_src =
|
||||
( qw(apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c
|
||||
bf_prefix.c),
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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/crypto.h>
|
||||
#include "apps.h"
|
||||
#include "progs.h"
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||
OPT_CONFIGDIR, OPT_ENGINESDIR, OPT_MODULESDIR, OPT_DSOEXT, OPT_DIRNAMESEP,
|
||||
OPT_LISTSEP
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS info_options[] = {
|
||||
{"help", OPT_HELP, '-', "Display this summary"},
|
||||
{"configdir", OPT_CONFIGDIR, '-', "Default configuration file directory"},
|
||||
{"c", OPT_CONFIGDIR, '-', "Default configuration file directory"},
|
||||
{"enginesdir", OPT_ENGINESDIR, '-', "Default engine module directory"},
|
||||
{"e", OPT_ENGINESDIR, '-', "Default engine module directory"},
|
||||
{"modulesdir", OPT_ENGINESDIR, '-',
|
||||
"Default module directory (other than engine modules)"},
|
||||
{"m", OPT_ENGINESDIR, '-',
|
||||
"Default module directory (other than engine modules)"},
|
||||
{"dsoext", OPT_DSOEXT, '-', "Configured extension for modules"},
|
||||
{"dirnamesep", OPT_DIRNAMESEP, '-', "Directory-filename separator"},
|
||||
{"listsep", OPT_LISTSEP, '-', "List separator character"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
int info_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1, dirty = 0, type = 0;
|
||||
char *prog;
|
||||
OPTION_CHOICE o;
|
||||
|
||||
prog = opt_init(argc, argv, info_options);
|
||||
while ((o = opt_next()) != OPT_EOF) {
|
||||
switch (o) {
|
||||
case OPT_EOF:
|
||||
case OPT_ERR:
|
||||
opthelp:
|
||||
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
|
||||
goto end;
|
||||
case OPT_HELP:
|
||||
opt_help(info_options);
|
||||
ret = 0;
|
||||
goto end;
|
||||
case OPT_CONFIGDIR:
|
||||
type = OPENSSL_INFO_CONFIG_DIR;
|
||||
dirty++;
|
||||
break;
|
||||
case OPT_ENGINESDIR:
|
||||
type = OPENSSL_INFO_ENGINES_DIR;
|
||||
dirty++;
|
||||
break;
|
||||
case OPT_MODULESDIR:
|
||||
type = OPENSSL_INFO_MODULES_DIR;
|
||||
dirty++;
|
||||
break;
|
||||
case OPT_DSOEXT:
|
||||
type = OPENSSL_INFO_DSO_EXTENSION;
|
||||
dirty++;
|
||||
break;
|
||||
case OPT_DIRNAMESEP:
|
||||
type = OPENSSL_INFO_DIR_FILENAME_SEPARATOR;
|
||||
dirty++;
|
||||
break;
|
||||
case OPT_LISTSEP:
|
||||
type = OPENSSL_INFO_LIST_SEPARATOR;
|
||||
dirty++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt_num_rest() != 0) {
|
||||
BIO_printf(bio_err, "%s: Extra parameters given.\n", prog);
|
||||
goto opthelp;
|
||||
}
|
||||
if (dirty > 1) {
|
||||
BIO_printf(bio_err, "%s: Only one item allowed\n", prog);
|
||||
goto opthelp;
|
||||
}
|
||||
if (dirty == 0) {
|
||||
BIO_printf(bio_err, "%s: No items chosen\n", prog);
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
BIO_printf(bio_out, "%s\n", OPENSSL_info(type));
|
||||
ret = 0;
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "apps.h"
|
||||
#include "progs.h"
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||
OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS kdf_options[] = {
|
||||
{OPT_HELP_STR, 1, '-', "Usage: %s [options] kdf_name\n"},
|
||||
{OPT_HELP_STR, 1, '-', "kdf_name\t KDF algorithm.\n"},
|
||||
{"help", OPT_HELP, '-', "Display this summary"},
|
||||
{"kdfopt", OPT_KDFOPT, 's', "KDF algorithm control parameters in n:v form. "
|
||||
"See 'Supported Controls' in the EVP_KDF_ docs"},
|
||||
{"keylen", OPT_KEYLEN, 's', "The size of the output derived key"},
|
||||
{"out", OPT_OUT, '>', "Output to filename rather than stdout"},
|
||||
{"binary", OPT_BIN, '-', "Output in binary format (Default is hexadecimal "
|
||||
"output)"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static int kdf_ctrl_string(EVP_KDF_CTX *ctx, const char *value)
|
||||
{
|
||||
int rv;
|
||||
char *stmp, *vtmp = NULL;
|
||||
|
||||
stmp = OPENSSL_strdup(value);
|
||||
if (stmp == NULL)
|
||||
return -1;
|
||||
vtmp = strchr(stmp, ':');
|
||||
if (vtmp != NULL) {
|
||||
*vtmp = 0;
|
||||
vtmp++;
|
||||
}
|
||||
rv = EVP_KDF_ctrl_str(ctx, stmp, vtmp);
|
||||
OPENSSL_free(stmp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int kdf_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1, i, id, out_bin = 0;
|
||||
OPTION_CHOICE o;
|
||||
STACK_OF(OPENSSL_STRING) *opts = NULL;
|
||||
char *prog, *hexout = NULL;
|
||||
const char *outfile = NULL;
|
||||
unsigned char *dkm_bytes = NULL;
|
||||
size_t dkm_len = 0;
|
||||
BIO *out = NULL;
|
||||
EVP_KDF_CTX *ctx = NULL;
|
||||
|
||||
prog = opt_init(argc, argv, kdf_options);
|
||||
while ((o = opt_next()) != OPT_EOF) {
|
||||
switch (o) {
|
||||
default:
|
||||
opthelp:
|
||||
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
|
||||
goto err;
|
||||
case OPT_HELP:
|
||||
opt_help(kdf_options);
|
||||
ret = 0;
|
||||
goto err;
|
||||
case OPT_BIN:
|
||||
out_bin = 1;
|
||||
break;
|
||||
case OPT_KEYLEN:
|
||||
dkm_len = (size_t)atoi(opt_arg());
|
||||
break;
|
||||
case OPT_OUT:
|
||||
outfile = opt_arg();
|
||||
break;
|
||||
case OPT_KDFOPT:
|
||||
if (opts == NULL)
|
||||
opts = sk_OPENSSL_STRING_new_null();
|
||||
if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
|
||||
goto opthelp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc = opt_num_rest();
|
||||
argv = opt_rest();
|
||||
|
||||
if (argc != 1) {
|
||||
BIO_printf(bio_err, "Invalid number of extra arguments\n");
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
id = OBJ_sn2nid(argv[0]);
|
||||
if (id == NID_undef) {
|
||||
BIO_printf(bio_err, "Invalid KDF name %s\n", argv[0]);
|
||||
goto opthelp;
|
||||
}
|
||||
|
||||
ctx = EVP_KDF_CTX_new_id(id);
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
if (opts != NULL) {
|
||||
for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) {
|
||||
char *opt = sk_OPENSSL_STRING_value(opts, i);
|
||||
if (kdf_ctrl_string(ctx, opt) <= 0) {
|
||||
BIO_printf(bio_err, "KDF parameter error '%s'\n", opt);
|
||||
ERR_print_errors(bio_err);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
|
||||
if (out == NULL)
|
||||
goto err;
|
||||
|
||||
if (dkm_len <= 0) {
|
||||
BIO_printf(bio_err, "Invalid derived key length.\n");
|
||||
goto err;
|
||||
}
|
||||
dkm_bytes = app_malloc(dkm_len, "out buffer");
|
||||
if (dkm_bytes == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EVP_KDF_derive(ctx, dkm_bytes, dkm_len)) {
|
||||
BIO_printf(bio_err, "EVP_KDF_derive failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (out_bin) {
|
||||
BIO_write(out, dkm_bytes, dkm_len);
|
||||
} else {
|
||||
hexout = OPENSSL_buf2hexstr(dkm_bytes, dkm_len);
|
||||
BIO_printf(out, "%s\n\n", hexout);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
if (ret != 0)
|
||||
ERR_print_errors(bio_err);
|
||||
OPENSSL_clear_free(dkm_bytes, dkm_len);
|
||||
sk_OPENSSL_STRING_free(opts);
|
||||
EVP_KDF_CTX_free(ctx);
|
||||
BIO_free(out);
|
||||
OPENSSL_free(hexout);
|
||||
return ret;
|
||||
}
|
||||
@@ -51,6 +51,9 @@ print <<"EOF";
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/lhash.h>
|
||||
#include "opt.h"
|
||||
|
||||
typedef enum FUNC_TYPE {
|
||||
FT_none, FT_general, FT_md, FT_cipher, FT_pkey,
|
||||
FT_md_alg, FT_cipher_alg
|
||||
|
||||
+10
-3
@@ -33,7 +33,7 @@
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||
OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R
|
||||
OPT_B, OPT_D, OPT_E, OPT_M, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS version_options[] = {
|
||||
@@ -42,6 +42,7 @@ const OPTIONS version_options[] = {
|
||||
{"b", OPT_B, '-', "Show build date"},
|
||||
{"d", OPT_D, '-', "Show configuration directory"},
|
||||
{"e", OPT_E, '-', "Show engines directory"},
|
||||
{"m", OPT_M, '-', "Show modules directory"},
|
||||
{"f", OPT_F, '-', "Show compiler flags used"},
|
||||
{"o", OPT_O, '-', "Show some internal datatype options"},
|
||||
{"p", OPT_P, '-', "Show target build platform"},
|
||||
@@ -64,7 +65,7 @@ int version_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1, dirty = 0, seed = 0;
|
||||
int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0;
|
||||
int engdir = 0;
|
||||
int engdir = 0, moddir = 0;
|
||||
char *prog;
|
||||
OPTION_CHOICE o;
|
||||
|
||||
@@ -89,6 +90,9 @@ opthelp:
|
||||
case OPT_E:
|
||||
dirty = engdir = 1;
|
||||
break;
|
||||
case OPT_M:
|
||||
dirty = moddir = 1;
|
||||
break;
|
||||
case OPT_F:
|
||||
dirty = cflags = 1;
|
||||
break;
|
||||
@@ -105,7 +109,8 @@ opthelp:
|
||||
dirty = version = 1;
|
||||
break;
|
||||
case OPT_A:
|
||||
seed = options = cflags = version = date = platform = dir = engdir
|
||||
seed = options = cflags = version = date = platform
|
||||
= dir = engdir = moddir
|
||||
= 1;
|
||||
break;
|
||||
}
|
||||
@@ -155,6 +160,8 @@ opthelp:
|
||||
printf("%s\n", OpenSSL_version(OPENSSL_DIR));
|
||||
if (engdir)
|
||||
printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
|
||||
if (moddir)
|
||||
printf("%s\n", OpenSSL_version(OPENSSL_MODULES_DIR));
|
||||
if (seed) {
|
||||
printf("Seeding source:");
|
||||
#ifdef OPENSSL_RAND_SEED_RTDSC
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
SUBDIRS=crypto ssl apps test util tools fuzz engines providers
|
||||
|
||||
LIBS=libcrypto libssl
|
||||
INCLUDE[libcrypto]=. crypto/include include
|
||||
INCLUDE[libcrypto]=. crypto/include include providers/common/include
|
||||
INCLUDE[libssl]=. include
|
||||
DEPEND[libssl]=libcrypto
|
||||
|
||||
|
||||
@@ -27,18 +27,34 @@
|
||||
# CBC encrypt case. On Cortex-A57 parallelizable mode performance
|
||||
# seems to be limited by sheer amount of NEON instructions...
|
||||
#
|
||||
# April 2019
|
||||
#
|
||||
# Key to performance of parallelize-able modes is round instruction
|
||||
# interleaving. But which factor to use? There is optimal one for
|
||||
# each combination of instruction latency and issue rate, beyond
|
||||
# which increasing interleave factor doesn't pay off. While on cons
|
||||
# side we have code size increase and resource waste on platforms for
|
||||
# which interleave factor is too high. In other words you want it to
|
||||
# be just right. So far interleave factor of 3x was serving well all
|
||||
# platforms. But for ThunderX2 optimal interleave factor was measured
|
||||
# to be 5x...
|
||||
#
|
||||
# Performance in cycles per byte processed with 128-bit key:
|
||||
#
|
||||
# CBC enc CBC dec CTR
|
||||
# Apple A7 2.39 1.20 1.20
|
||||
# Cortex-A53 1.32 1.29 1.46
|
||||
# Cortex-A57(*) 1.95 0.85 0.93
|
||||
# Denver 1.96 0.86 0.80
|
||||
# Mongoose 1.33 1.20 1.20
|
||||
# Kryo 1.26 0.94 1.00
|
||||
# Cortex-A53 1.32 1.17/1.29(**) 1.36/1.46
|
||||
# Cortex-A57(*) 1.95 0.82/0.85 0.89/0.93
|
||||
# Cortex-A72 1.33 0.85/0.88 0.92/0.96
|
||||
# Denver 1.96 0.65/0.86 0.76/0.80
|
||||
# Mongoose 1.33 1.23/1.20 1.30/1.20
|
||||
# Kryo 1.26 0.87/0.94 1.00/1.00
|
||||
# ThunderX2 5.95 1.25 1.30
|
||||
#
|
||||
# (*) original 3.64/1.34/1.32 results were for r0p0 revision
|
||||
# and are still same even for updated module;
|
||||
# (**) numbers after slash are for 32-bit code, which is 3x-
|
||||
# interleaved;
|
||||
|
||||
$flavour = shift;
|
||||
$output = shift;
|
||||
@@ -523,6 +539,13 @@ $code.=<<___;
|
||||
___
|
||||
{
|
||||
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
|
||||
|
||||
my ($dat3,$in3,$tmp3); # used only in 64-bit mode
|
||||
my ($dat4,$in4,$tmp4);
|
||||
if ($flavour =~ /64/) {
|
||||
($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23));
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
.align 5
|
||||
.Lcbc_dec:
|
||||
@@ -539,7 +562,196 @@ $code.=<<___;
|
||||
vorr $in0,$dat,$dat
|
||||
vorr $in1,$dat1,$dat1
|
||||
vorr $in2,$dat2,$dat2
|
||||
___
|
||||
$code.=<<___ if ($flavour =~ /64/);
|
||||
cmp $len,#32
|
||||
b.lo .Loop3x_cbc_dec
|
||||
|
||||
vld1.8 {$dat3},[$inp],#16
|
||||
vld1.8 {$dat4},[$inp],#16
|
||||
sub $len,$len,#32 // bias
|
||||
mov $cnt,$rounds
|
||||
vorr $in3,$dat3,$dat3
|
||||
vorr $in4,$dat4,$dat4
|
||||
|
||||
.Loop5x_cbc_dec:
|
||||
aesd $dat0,q8
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q8
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q8
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q8
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q8
|
||||
aesimc $dat4,$dat4
|
||||
vld1.32 {q8},[$key_],#16
|
||||
subs $cnt,$cnt,#2
|
||||
aesd $dat0,q9
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q9
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q9
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q9
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q9
|
||||
aesimc $dat4,$dat4
|
||||
vld1.32 {q9},[$key_],#16
|
||||
b.gt .Loop5x_cbc_dec
|
||||
|
||||
aesd $dat0,q8
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q8
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q8
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q8
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q8
|
||||
aesimc $dat4,$dat4
|
||||
cmp $len,#0x40 // because .Lcbc_tail4x
|
||||
sub $len,$len,#0x50
|
||||
|
||||
aesd $dat0,q9
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q9
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q9
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q9
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q9
|
||||
aesimc $dat4,$dat4
|
||||
csel x6,xzr,$len,gt // borrow x6, $cnt, "gt" is not typo
|
||||
mov $key_,$key
|
||||
|
||||
aesd $dat0,q10
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q10
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q10
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q10
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q10
|
||||
aesimc $dat4,$dat4
|
||||
add $inp,$inp,x6 // $inp is adjusted in such way that
|
||||
// at exit from the loop $dat1-$dat4
|
||||
// are loaded with last "words"
|
||||
add x6,$len,#0x60 // because .Lcbc_tail4x
|
||||
|
||||
aesd $dat0,q11
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q11
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q11
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q11
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q11
|
||||
aesimc $dat4,$dat4
|
||||
|
||||
aesd $dat0,q12
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q12
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q12
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q12
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q12
|
||||
aesimc $dat4,$dat4
|
||||
|
||||
aesd $dat0,q13
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q13
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q13
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q13
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q13
|
||||
aesimc $dat4,$dat4
|
||||
|
||||
aesd $dat0,q14
|
||||
aesimc $dat0,$dat0
|
||||
aesd $dat1,q14
|
||||
aesimc $dat1,$dat1
|
||||
aesd $dat2,q14
|
||||
aesimc $dat2,$dat2
|
||||
aesd $dat3,q14
|
||||
aesimc $dat3,$dat3
|
||||
aesd $dat4,q14
|
||||
aesimc $dat4,$dat4
|
||||
|
||||
veor $tmp0,$ivec,$rndlast
|
||||
aesd $dat0,q15
|
||||
veor $tmp1,$in0,$rndlast
|
||||
vld1.8 {$in0},[$inp],#16
|
||||
aesd $dat1,q15
|
||||
veor $tmp2,$in1,$rndlast
|
||||
vld1.8 {$in1},[$inp],#16
|
||||
aesd $dat2,q15
|
||||
veor $tmp3,$in2,$rndlast
|
||||
vld1.8 {$in2},[$inp],#16
|
||||
aesd $dat3,q15
|
||||
veor $tmp4,$in3,$rndlast
|
||||
vld1.8 {$in3},[$inp],#16
|
||||
aesd $dat4,q15
|
||||
vorr $ivec,$in4,$in4
|
||||
vld1.8 {$in4},[$inp],#16
|
||||
cbz x6,.Lcbc_tail4x
|
||||
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
|
||||
veor $tmp0,$tmp0,$dat0
|
||||
vorr $dat0,$in0,$in0
|
||||
veor $tmp1,$tmp1,$dat1
|
||||
vorr $dat1,$in1,$in1
|
||||
veor $tmp2,$tmp2,$dat2
|
||||
vorr $dat2,$in2,$in2
|
||||
veor $tmp3,$tmp3,$dat3
|
||||
vorr $dat3,$in3,$in3
|
||||
veor $tmp4,$tmp4,$dat4
|
||||
vst1.8 {$tmp0},[$out],#16
|
||||
vorr $dat4,$in4,$in4
|
||||
vst1.8 {$tmp1},[$out],#16
|
||||
mov $cnt,$rounds
|
||||
vst1.8 {$tmp2},[$out],#16
|
||||
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
|
||||
vst1.8 {$tmp3},[$out],#16
|
||||
vst1.8 {$tmp4},[$out],#16
|
||||
b.hs .Loop5x_cbc_dec
|
||||
|
||||
add $len,$len,#0x50
|
||||
cbz $len,.Lcbc_done
|
||||
|
||||
add $cnt,$rounds,#2
|
||||
subs $len,$len,#0x30
|
||||
vorr $dat0,$in2,$in2
|
||||
vorr $in0,$in2,$in2
|
||||
vorr $dat1,$in3,$in3
|
||||
vorr $in1,$in3,$in3
|
||||
vorr $dat2,$in4,$in4
|
||||
vorr $in2,$in4,$in4
|
||||
b.lo .Lcbc_dec_tail
|
||||
|
||||
b .Loop3x_cbc_dec
|
||||
|
||||
.align 4
|
||||
.Lcbc_tail4x:
|
||||
veor $tmp1,$tmp0,$dat1
|
||||
veor $tmp2,$tmp2,$dat2
|
||||
veor $tmp3,$tmp3,$dat3
|
||||
veor $tmp4,$tmp4,$dat4
|
||||
vst1.8 {$tmp1},[$out],#16
|
||||
vst1.8 {$tmp2},[$out],#16
|
||||
vst1.8 {$tmp3},[$out],#16
|
||||
vst1.8 {$tmp4},[$out],#16
|
||||
|
||||
b .Lcbc_done
|
||||
.align 4
|
||||
___
|
||||
$code.=<<___;
|
||||
.Loop3x_cbc_dec:
|
||||
aesd $dat0,q8
|
||||
aesimc $dat0,$dat0
|
||||
@@ -700,6 +912,9 @@ my $step="x12"; # aliases with $tctr2
|
||||
my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$ivec,$rndlast)=map("q$_",(0..7));
|
||||
my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9));
|
||||
|
||||
# used only in 64-bit mode...
|
||||
my ($dat3,$dat4,$in3,$in4)=map("q$_",(16..23));
|
||||
|
||||
my ($dat,$tmp)=($dat0,$tmp0);
|
||||
|
||||
### q8-q15 preloaded key schedule
|
||||
@@ -752,6 +967,175 @@ $code.=<<___;
|
||||
rev $tctr2, $ctr
|
||||
sub $len,$len,#3 // bias
|
||||
vmov.32 ${dat2}[3],$tctr2
|
||||
___
|
||||
$code.=<<___ if ($flavour =~ /64/);
|
||||
cmp $len,#2
|
||||
b.lo .Loop3x_ctr32
|
||||
|
||||
add w13,$ctr,#1
|
||||
add w14,$ctr,#2
|
||||
vorr $dat3,$dat0,$dat0
|
||||
rev w13,w13
|
||||
vorr $dat4,$dat0,$dat0
|
||||
rev w14,w14
|
||||
vmov.32 ${dat3}[3],w13
|
||||
sub $len,$len,#2 // bias
|
||||
vmov.32 ${dat4}[3],w14
|
||||
add $ctr,$ctr,#2
|
||||
b .Loop5x_ctr32
|
||||
|
||||
.align 4
|
||||
.Loop5x_ctr32:
|
||||
aese $dat0,q8
|
||||
aesmc $dat0,$dat0
|
||||
aese $dat1,q8
|
||||
aesmc $dat1,$dat1
|
||||
aese $dat2,q8
|
||||
aesmc $dat2,$dat2
|
||||
aese $dat3,q8
|
||||
aesmc $dat3,$dat3
|
||||
aese $dat4,q8
|
||||
aesmc $dat4,$dat4
|
||||
vld1.32 {q8},[$key_],#16
|
||||
subs $cnt,$cnt,#2
|
||||
aese $dat0,q9
|
||||
aesmc $dat0,$dat0
|
||||
aese $dat1,q9
|
||||
aesmc $dat1,$dat1
|
||||
aese $dat2,q9
|
||||
aesmc $dat2,$dat2
|
||||
aese $dat3,q9
|
||||
aesmc $dat3,$dat3
|
||||
aese $dat4,q9
|
||||
aesmc $dat4,$dat4
|
||||
vld1.32 {q9},[$key_],#16
|
||||
b.gt .Loop5x_ctr32
|
||||
|
||||
mov $key_,$key
|
||||
aese $dat0,q8
|
||||
aesmc $dat0,$dat0
|
||||
aese $dat1,q8
|
||||
aesmc $dat1,$dat1
|
||||
aese $dat2,q8
|
||||
aesmc $dat2,$dat2
|
||||
aese $dat3,q8
|
||||
aesmc $dat3,$dat3
|
||||
aese $dat4,q8
|
||||
aesmc $dat4,$dat4
|
||||
vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0]
|
||||
|
||||
aese $dat0,q9
|
||||
aesmc $dat0,$dat0
|
||||
aese $dat1,q9
|
||||
aesmc $dat1,$dat1
|
||||
aese $dat2,q9
|
||||
aesmc $dat2,$dat2
|
||||
aese $dat3,q9
|
||||
aesmc $dat3,$dat3
|
||||
aese $dat4,q9
|
||||
aesmc $dat4,$dat4
|
||||
vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1]
|
||||
|
||||
aese $dat0,q12
|
||||
aesmc $dat0,$dat0
|
||||
add $tctr0,$ctr,#1
|
||||
add $tctr1,$ctr,#2
|
||||
aese $dat1,q12
|
||||
aesmc $dat1,$dat1
|
||||
add $tctr2,$ctr,#3
|
||||
add w13,$ctr,#4
|
||||
aese $dat2,q12
|
||||
aesmc $dat2,$dat2
|
||||
add w14,$ctr,#5
|
||||
rev $tctr0,$tctr0
|
||||
aese $dat3,q12
|
||||
aesmc $dat3,$dat3
|
||||
rev $tctr1,$tctr1
|
||||
rev $tctr2,$tctr2
|
||||
aese $dat4,q12
|
||||
aesmc $dat4,$dat4
|
||||
rev w13,w13
|
||||
rev w14,w14
|
||||
|
||||
aese $dat0,q13
|
||||
aesmc $dat0,$dat0
|
||||
aese $dat1,q13
|
||||
aesmc $dat1,$dat1
|
||||
aese $dat2,q13
|
||||
aesmc $dat2,$dat2
|
||||
aese $dat3,q13
|
||||
aesmc $dat3,$dat3
|
||||
aese $dat4,q13
|
||||
aesmc $dat4,$dat4
|
||||
|
||||
aese $dat0,q14
|
||||
aesmc $dat0,$dat0
|
||||
vld1.8 {$in0},[$inp],#16
|
||||
aese $dat1,q14
|
||||
aesmc $dat1,$dat1
|
||||
vld1.8 {$in1},[$inp],#16
|
||||
aese $dat2,q14
|
||||
aesmc $dat2,$dat2
|
||||
vld1.8 {$in2},[$inp],#16
|
||||
aese $dat3,q14
|
||||
aesmc $dat3,$dat3
|
||||
vld1.8 {$in3},[$inp],#16
|
||||
aese $dat4,q14
|
||||
aesmc $dat4,$dat4
|
||||
vld1.8 {$in4},[$inp],#16
|
||||
|
||||
aese $dat0,q15
|
||||
veor $in0,$in0,$rndlast
|
||||
aese $dat1,q15
|
||||
veor $in1,$in1,$rndlast
|
||||
aese $dat2,q15
|
||||
veor $in2,$in2,$rndlast
|
||||
aese $dat3,q15
|
||||
veor $in3,$in3,$rndlast
|
||||
aese $dat4,q15
|
||||
veor $in4,$in4,$rndlast
|
||||
|
||||
veor $in0,$in0,$dat0
|
||||
vorr $dat0,$ivec,$ivec
|
||||
veor $in1,$in1,$dat1
|
||||
vorr $dat1,$ivec,$ivec
|
||||
veor $in2,$in2,$dat2
|
||||
vorr $dat2,$ivec,$ivec
|
||||
veor $in3,$in3,$dat3
|
||||
vorr $dat3,$ivec,$ivec
|
||||
veor $in4,$in4,$dat4
|
||||
vorr $dat4,$ivec,$ivec
|
||||
|
||||
vst1.8 {$in0},[$out],#16
|
||||
vmov.32 ${dat0}[3],$tctr0
|
||||
vst1.8 {$in1},[$out],#16
|
||||
vmov.32 ${dat1}[3],$tctr1
|
||||
vst1.8 {$in2},[$out],#16
|
||||
vmov.32 ${dat2}[3],$tctr2
|
||||
vst1.8 {$in3},[$out],#16
|
||||
vmov.32 ${dat3}[3],w13
|
||||
vst1.8 {$in4},[$out],#16
|
||||
vmov.32 ${dat4}[3],w14
|
||||
|
||||
mov $cnt,$rounds
|
||||
cbz $len,.Lctr32_done
|
||||
|
||||
add $ctr,$ctr,#5
|
||||
subs $len,$len,#5
|
||||
b.hs .Loop5x_ctr32
|
||||
|
||||
add $len,$len,#5
|
||||
sub $ctr,$ctr,#5
|
||||
|
||||
cmp $len,#2
|
||||
mov $step,#16
|
||||
cclr $step,lo
|
||||
b.ls .Lctr32_tail
|
||||
|
||||
sub $len,$len,#3 // bias
|
||||
add $ctr,$ctr,#3
|
||||
___
|
||||
$code.=<<___;
|
||||
b .Loop3x_ctr32
|
||||
|
||||
.align 4
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
# Denver(***) 16.6(**) 15.1/17.8(**) [8.80/9.93 ]
|
||||
# Apple A7(***) 22.7(**) 10.9/14.3 [8.45/10.0 ]
|
||||
# Mongoose(***) 26.3(**) 21.0/25.0(**) [13.3/16.8 ]
|
||||
# ThunderX2(***) 39.4(**) 33.8/48.6(**)
|
||||
#
|
||||
# (*) ECB denotes approximate result for parallelizable modes
|
||||
# such as CBC decrypt, CTR, etc.;
|
||||
|
||||
+29
-12
@@ -57,7 +57,12 @@ static const BIO_METHOD secmem_method = {
|
||||
NULL, /* mem_callback_ctrl */
|
||||
};
|
||||
|
||||
/* BIO memory stores buffer and read pointer */
|
||||
/*
|
||||
* BIO memory stores buffer and read pointer
|
||||
* however the roles are different for read only BIOs.
|
||||
* In that case the readp just stores the original state
|
||||
* to be used for reset.
|
||||
*/
|
||||
typedef struct bio_buf_mem_st {
|
||||
struct buf_mem_st *buf; /* allocated buffer */
|
||||
struct buf_mem_st *readp; /* read pointer */
|
||||
@@ -192,11 +197,14 @@ static int mem_read(BIO *b, char *out, int outl)
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
BUF_MEM *bm = bbm->readp;
|
||||
|
||||
if (b->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
bm = bbm->buf;
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
|
||||
if ((out != NULL) && (ret > 0)) {
|
||||
memcpy(out, bm->data, ret);
|
||||
bm->length -= ret;
|
||||
bm->max -= ret;
|
||||
bm->data += ret;
|
||||
} else if (bm->length == 0) {
|
||||
ret = b->num;
|
||||
@@ -241,29 +249,36 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
BUF_MEM *bm;
|
||||
|
||||
if (b->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
bm = bbm->buf;
|
||||
else
|
||||
bm = bbm->readp;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
bm = bbm->buf;
|
||||
if (bm->data != NULL) {
|
||||
/* For read only case reset to the start again */
|
||||
if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) {
|
||||
bm->length = bm->max;
|
||||
if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) {
|
||||
if (b->flags & BIO_FLAGS_NONCLEAR_RST) {
|
||||
bm->length = bm->max;
|
||||
} else {
|
||||
memset(bm->data, 0, bm->max);
|
||||
bm->length = 0;
|
||||
}
|
||||
*bbm->readp = *bbm->buf;
|
||||
} else {
|
||||
memset(bm->data, 0, bm->max);
|
||||
bm->length = 0;
|
||||
/* For read only case just reset to the start again */
|
||||
*bbm->buf = *bbm->readp;
|
||||
}
|
||||
*bbm->readp = *bbm->buf;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
bm = bbm->readp;
|
||||
ret = (long)(bm->length == 0);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM_EOF_RETURN:
|
||||
b->num = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
bm = bbm->readp;
|
||||
ret = (long)bm->length;
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
@@ -278,8 +293,9 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
break;
|
||||
case BIO_C_GET_BUF_MEM_PTR:
|
||||
if (ptr != NULL) {
|
||||
mem_buf_sync(b);
|
||||
bm = bbm->readp;
|
||||
if (!(b->flags & BIO_FLAGS_MEM_RDONLY))
|
||||
mem_buf_sync(b);
|
||||
bm = bbm->buf;
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)bm;
|
||||
}
|
||||
@@ -294,7 +310,6 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
ret = 0L;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
bm = bbm->readp;
|
||||
ret = (long)bm->length;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
@@ -318,6 +333,8 @@ static int mem_gets(BIO *bp, char *buf, int size)
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr;
|
||||
BUF_MEM *bm = bbm->readp;
|
||||
|
||||
if (bp->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
bm = bbm->buf;
|
||||
BIO_clear_retry_flags(bp);
|
||||
j = bm->length;
|
||||
if ((size - 1) < j)
|
||||
|
||||
@@ -329,8 +329,6 @@ int bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
|
||||
if (BN_is_one(z))
|
||||
goto composite;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 1, i))
|
||||
goto err;
|
||||
/* At this point z = b^((w-1)/2) mod w */
|
||||
/* (Steps 4.8 - 4.9) x = z, z = x^2 mod w */
|
||||
if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx))
|
||||
@@ -358,6 +356,8 @@ composite:
|
||||
goto err;
|
||||
outer_loop: ;
|
||||
/* (Step 4.1.5) */
|
||||
if (!BN_GENCB_call(cb, 1, i))
|
||||
goto err;
|
||||
}
|
||||
/* (Step 5) */
|
||||
*status = BN_PRIMETEST_PROBABLY_PRIME;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ SOURCE[../libcrypto]=provider_core.c provider_predefined.c provider_conf.c \
|
||||
|
||||
# Central utilities
|
||||
SOURCE[../libcrypto]=\
|
||||
cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
|
||||
cryptlib.c mem.c mem_dbg.c cversion.c info.c ex_data.c cpt_err.c \
|
||||
ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
|
||||
threads_pthread.c threads_win.c threads_none.c getenv.c \
|
||||
o_init.c o_fips.c mem_sec.c init.c context.c sparse_array.c \
|
||||
|
||||
+347
-194
@@ -18,22 +18,31 @@
|
||||
#
|
||||
# ChaCha20 for ARMv8.
|
||||
#
|
||||
# April 2019
|
||||
#
|
||||
# Replace 3xNEON+1xIALU code path with 4+1. 4+1 is actually fastest
|
||||
# option on most(*), but not all, processors, yet 6+2 is retained.
|
||||
# This is because penalties are considered tolerable in comparison to
|
||||
# improvement on processors where 6+2 helps. Most notably +37% on
|
||||
# ThunderX2. It's server-oriented processor which will have to serve
|
||||
# as many requests as possible. While others are mostly clients, when
|
||||
# performance doesn't have to be absolute top-notch, just fast enough,
|
||||
# as majority of time is spent "entertaining" relatively slow human.
|
||||
#
|
||||
# Performance in cycles per byte out of large buffer.
|
||||
#
|
||||
# IALU/gcc-4.9 3xNEON+1xIALU 6xNEON+2xIALU
|
||||
# IALU/gcc-4.9 4xNEON+1xIALU 6xNEON+2xIALU
|
||||
#
|
||||
# Apple A7 5.50/+49% 3.33 1.70
|
||||
# Cortex-A53 8.40/+80% 4.72 4.72(*)
|
||||
# Cortex-A57 8.06/+43% 4.90 4.43(**)
|
||||
# Denver 4.50/+82% 2.63 2.67(*)
|
||||
# X-Gene 9.50/+46% 8.82 8.89(*)
|
||||
# Mongoose 8.00/+44% 3.64 3.25
|
||||
# Kryo 8.17/+50% 4.83 4.65
|
||||
# Apple A7 5.50/+49% 2.72 1.60
|
||||
# Cortex-A53 8.40/+80% 4.06 4.45(*)
|
||||
# Cortex-A57 8.06/+43% 4.15 4.40(*)
|
||||
# Denver 4.50/+82% 2.30 2.70(*)
|
||||
# X-Gene 9.50/+46% 8.20 8.90(*)
|
||||
# Mongoose 8.00/+44% 2.74 3.12(*)
|
||||
# Kryo 8.17/+50% 4.47 4.65(*)
|
||||
# ThunderX2 7.22/+48% 5.64 4.10
|
||||
#
|
||||
# (*) it's expected that doubling interleave factor doesn't help
|
||||
# all processors, only those with higher NEON latency and
|
||||
# higher instruction issue rate;
|
||||
# (**) expected improvement was actually higher;
|
||||
# (*) slower than 4+1:-(
|
||||
|
||||
$flavour=shift;
|
||||
$output=shift;
|
||||
@@ -120,18 +129,21 @@ my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
#include "arm_arch.h"
|
||||
#ifndef __KERNEL__
|
||||
# include "arm_arch.h"
|
||||
.extern OPENSSL_armcap_P
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.extern OPENSSL_armcap_P
|
||||
|
||||
.align 5
|
||||
.Lsigma:
|
||||
.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral
|
||||
.Lone:
|
||||
.long 1,0,0,0
|
||||
.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
.long 1,2,3,4
|
||||
.Lrot24:
|
||||
.long 0x02010003,0x06050407,0x0a09080b,0x0e0d0c0f
|
||||
.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by \@dot-asm"
|
||||
|
||||
.globl ChaCha20_ctr32
|
||||
.type ChaCha20_ctr32,%function
|
||||
@@ -141,10 +153,12 @@ ChaCha20_ctr32:
|
||||
cmp $len,#192
|
||||
b.lo .Lshort
|
||||
|
||||
#ifndef __KERNEL__
|
||||
adrp x17,OPENSSL_armcap_P
|
||||
ldr w17,[x17,#:lo12:OPENSSL_armcap_P]
|
||||
tst w17,#ARMV7_NEON
|
||||
b.ne .LChaCha20_neon
|
||||
#endif
|
||||
|
||||
.Lshort:
|
||||
.inst 0xd503233f // paciasp
|
||||
@@ -163,7 +177,7 @@ ChaCha20_ctr32:
|
||||
ldp @d[2],@d[3],[$key] // load key
|
||||
ldp @d[4],@d[5],[$key,#16]
|
||||
ldp @d[6],@d[7],[$ctr] // load counter
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
ror @d[2],@d[2],#32
|
||||
ror @d[3],@d[3],#32
|
||||
ror @d[4],@d[4],#32
|
||||
@@ -232,7 +246,7 @@ $code.=<<___;
|
||||
add @x[14],@x[14],@x[15],lsl#32
|
||||
ldp @x[13],@x[15],[$inp,#48]
|
||||
add $inp,$inp,#64
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -289,7 +303,7 @@ $code.=<<___;
|
||||
add @x[10],@x[10],@x[11],lsl#32
|
||||
add @x[12],@x[12],@x[13],lsl#32
|
||||
add @x[14],@x[14],@x[15],lsl#32
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -330,43 +344,87 @@ $code.=<<___;
|
||||
___
|
||||
|
||||
{{{
|
||||
my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) =
|
||||
map("v$_.4s",(0..7,16..23));
|
||||
my (@K)=map("v$_.4s",(24..30));
|
||||
my $ONE="v31.4s";
|
||||
my @K = map("v$_.4s",(0..3));
|
||||
my ($xt0,$xt1,$xt2,$xt3, $CTR,$ROT24) = map("v$_.4s",(4..9));
|
||||
my @X = map("v$_.4s",(16,20,24,28, 17,21,25,29, 18,22,26,30, 19,23,27,31));
|
||||
my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
|
||||
$xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3) = @X;
|
||||
|
||||
sub NEONROUND {
|
||||
my $odd = pop;
|
||||
my ($a,$b,$c,$d,$t)=@_;
|
||||
sub NEON_lane_ROUND {
|
||||
my ($a0,$b0,$c0,$d0)=@_;
|
||||
my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
|
||||
my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
|
||||
my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
|
||||
my @x=map("'$_'",@X);
|
||||
|
||||
(
|
||||
"&add ('$a','$a','$b')",
|
||||
"&eor ('$d','$d','$a')",
|
||||
"&rev32_16 ('$d','$d')", # vrot ($d,16)
|
||||
"&add (@x[$a0],@x[$a0],@x[$b0])", # Q1
|
||||
"&add (@x[$a1],@x[$a1],@x[$b1])", # Q2
|
||||
"&add (@x[$a2],@x[$a2],@x[$b2])", # Q3
|
||||
"&add (@x[$a3],@x[$a3],@x[$b3])", # Q4
|
||||
"&eor (@x[$d0],@x[$d0],@x[$a0])",
|
||||
"&eor (@x[$d1],@x[$d1],@x[$a1])",
|
||||
"&eor (@x[$d2],@x[$d2],@x[$a2])",
|
||||
"&eor (@x[$d3],@x[$d3],@x[$a3])",
|
||||
"&rev32_16 (@x[$d0],@x[$d0])",
|
||||
"&rev32_16 (@x[$d1],@x[$d1])",
|
||||
"&rev32_16 (@x[$d2],@x[$d2])",
|
||||
"&rev32_16 (@x[$d3],@x[$d3])",
|
||||
|
||||
"&add ('$c','$c','$d')",
|
||||
"&eor ('$t','$b','$c')",
|
||||
"&ushr ('$b','$t',20)",
|
||||
"&sli ('$b','$t',12)",
|
||||
"&add (@x[$c0],@x[$c0],@x[$d0])",
|
||||
"&add (@x[$c1],@x[$c1],@x[$d1])",
|
||||
"&add (@x[$c2],@x[$c2],@x[$d2])",
|
||||
"&add (@x[$c3],@x[$c3],@x[$d3])",
|
||||
"&eor ('$xt0',@x[$b0],@x[$c0])",
|
||||
"&eor ('$xt1',@x[$b1],@x[$c1])",
|
||||
"&eor ('$xt2',@x[$b2],@x[$c2])",
|
||||
"&eor ('$xt3',@x[$b3],@x[$c3])",
|
||||
"&ushr (@x[$b0],'$xt0',20)",
|
||||
"&ushr (@x[$b1],'$xt1',20)",
|
||||
"&ushr (@x[$b2],'$xt2',20)",
|
||||
"&ushr (@x[$b3],'$xt3',20)",
|
||||
"&sli (@x[$b0],'$xt0',12)",
|
||||
"&sli (@x[$b1],'$xt1',12)",
|
||||
"&sli (@x[$b2],'$xt2',12)",
|
||||
"&sli (@x[$b3],'$xt3',12)",
|
||||
|
||||
"&add ('$a','$a','$b')",
|
||||
"&eor ('$t','$d','$a')",
|
||||
"&ushr ('$d','$t',24)",
|
||||
"&sli ('$d','$t',8)",
|
||||
"&add (@x[$a0],@x[$a0],@x[$b0])",
|
||||
"&add (@x[$a1],@x[$a1],@x[$b1])",
|
||||
"&add (@x[$a2],@x[$a2],@x[$b2])",
|
||||
"&add (@x[$a3],@x[$a3],@x[$b3])",
|
||||
"&eor ('$xt0',@x[$d0],@x[$a0])",
|
||||
"&eor ('$xt1',@x[$d1],@x[$a1])",
|
||||
"&eor ('$xt2',@x[$d2],@x[$a2])",
|
||||
"&eor ('$xt3',@x[$d3],@x[$a3])",
|
||||
"&tbl (@x[$d0],'{$xt0}','$ROT24')",
|
||||
"&tbl (@x[$d1],'{$xt1}','$ROT24')",
|
||||
"&tbl (@x[$d2],'{$xt2}','$ROT24')",
|
||||
"&tbl (@x[$d3],'{$xt3}','$ROT24')",
|
||||
|
||||
"&add ('$c','$c','$d')",
|
||||
"&eor ('$t','$b','$c')",
|
||||
"&ushr ('$b','$t',25)",
|
||||
"&sli ('$b','$t',7)",
|
||||
|
||||
"&ext ('$c','$c','$c',8)",
|
||||
"&ext ('$d','$d','$d',$odd?4:12)",
|
||||
"&ext ('$b','$b','$b',$odd?12:4)"
|
||||
"&add (@x[$c0],@x[$c0],@x[$d0])",
|
||||
"&add (@x[$c1],@x[$c1],@x[$d1])",
|
||||
"&add (@x[$c2],@x[$c2],@x[$d2])",
|
||||
"&add (@x[$c3],@x[$c3],@x[$d3])",
|
||||
"&eor ('$xt0',@x[$b0],@x[$c0])",
|
||||
"&eor ('$xt1',@x[$b1],@x[$c1])",
|
||||
"&eor ('$xt2',@x[$b2],@x[$c2])",
|
||||
"&eor ('$xt3',@x[$b3],@x[$c3])",
|
||||
"&ushr (@x[$b0],'$xt0',25)",
|
||||
"&ushr (@x[$b1],'$xt1',25)",
|
||||
"&ushr (@x[$b2],'$xt2',25)",
|
||||
"&ushr (@x[$b3],'$xt3',25)",
|
||||
"&sli (@x[$b0],'$xt0',7)",
|
||||
"&sli (@x[$b1],'$xt1',7)",
|
||||
"&sli (@x[$b2],'$xt2',7)",
|
||||
"&sli (@x[$b3],'$xt3',7)"
|
||||
);
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
.globl ChaCha20_neon
|
||||
#endif
|
||||
.type ChaCha20_neon,%function
|
||||
.align 5
|
||||
ChaCha20_neon:
|
||||
@@ -393,8 +451,9 @@ ChaCha20_neon:
|
||||
ld1 {@K[1],@K[2]},[$key]
|
||||
ldp @d[6],@d[7],[$ctr] // load counter
|
||||
ld1 {@K[3]},[$ctr]
|
||||
ld1 {$ONE},[@x[0]]
|
||||
#ifdef __ARMEB__
|
||||
stp d8,d9,[sp] // meet ABI requirements
|
||||
ld1 {$CTR,$ROT24},[@x[0]]
|
||||
#ifdef __AARCH64EB__
|
||||
rev64 @K[0],@K[0]
|
||||
ror @d[2],@d[2],#32
|
||||
ror @d[3],@d[3],#32
|
||||
@@ -403,115 +462,129 @@ ChaCha20_neon:
|
||||
ror @d[6],@d[6],#32
|
||||
ror @d[7],@d[7],#32
|
||||
#endif
|
||||
add @K[3],@K[3],$ONE // += 1
|
||||
add @K[4],@K[3],$ONE
|
||||
add @K[5],@K[4],$ONE
|
||||
shl $ONE,$ONE,#2 // 1 -> 4
|
||||
|
||||
.Loop_outer_neon:
|
||||
mov.32 @x[0],@d[0] // unpack key block
|
||||
lsr @x[1],@d[0],#32
|
||||
mov $A0,@K[0]
|
||||
mov.32 @x[2],@d[1]
|
||||
lsr @x[3],@d[1],#32
|
||||
mov $A1,@K[0]
|
||||
mov.32 @x[4],@d[2]
|
||||
lsr @x[5],@d[2],#32
|
||||
mov $A2,@K[0]
|
||||
mov.32 @x[6],@d[3]
|
||||
mov $B0,@K[1]
|
||||
lsr @x[7],@d[3],#32
|
||||
mov $B1,@K[1]
|
||||
mov.32 @x[8],@d[4]
|
||||
mov $B2,@K[1]
|
||||
lsr @x[9],@d[4],#32
|
||||
mov $D0,@K[3]
|
||||
mov.32 @x[10],@d[5]
|
||||
mov $D1,@K[4]
|
||||
lsr @x[11],@d[5],#32
|
||||
mov $D2,@K[5]
|
||||
mov.32 @x[12],@d[6]
|
||||
mov $C0,@K[2]
|
||||
lsr @x[13],@d[6],#32
|
||||
mov $C1,@K[2]
|
||||
mov.32 @x[14],@d[7]
|
||||
mov $C2,@K[2]
|
||||
lsr @x[15],@d[7],#32
|
||||
dup $xa0,@{K[0]}[0] // unpack key block
|
||||
mov.32 @x[0],@d[0]
|
||||
dup $xa1,@{K[0]}[1]
|
||||
lsr @x[1],@d[0],#32
|
||||
dup $xa2,@{K[0]}[2]
|
||||
mov.32 @x[2],@d[1]
|
||||
dup $xa3,@{K[0]}[3]
|
||||
lsr @x[3],@d[1],#32
|
||||
dup $xb0,@{K[1]}[0]
|
||||
mov.32 @x[4],@d[2]
|
||||
dup $xb1,@{K[1]}[1]
|
||||
lsr @x[5],@d[2],#32
|
||||
dup $xb2,@{K[1]}[2]
|
||||
mov.32 @x[6],@d[3]
|
||||
dup $xb3,@{K[1]}[3]
|
||||
lsr @x[7],@d[3],#32
|
||||
dup $xd0,@{K[3]}[0]
|
||||
mov.32 @x[8],@d[4]
|
||||
dup $xd1,@{K[3]}[1]
|
||||
lsr @x[9],@d[4],#32
|
||||
dup $xd2,@{K[3]}[2]
|
||||
mov.32 @x[10],@d[5]
|
||||
dup $xd3,@{K[3]}[3]
|
||||
lsr @x[11],@d[5],#32
|
||||
add $xd0,$xd0,$CTR
|
||||
mov.32 @x[12],@d[6]
|
||||
dup $xc0,@{K[2]}[0]
|
||||
lsr @x[13],@d[6],#32
|
||||
dup $xc1,@{K[2]}[1]
|
||||
mov.32 @x[14],@d[7]
|
||||
dup $xc2,@{K[2]}[2]
|
||||
lsr @x[15],@d[7],#32
|
||||
dup $xc3,@{K[2]}[3]
|
||||
|
||||
mov $ctr,#10
|
||||
subs $len,$len,#256
|
||||
subs $len,$len,#320
|
||||
.Loop_neon:
|
||||
sub $ctr,$ctr,#1
|
||||
___
|
||||
my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
|
||||
my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
|
||||
my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
|
||||
my @thread3=&ROUND(0,4,8,12);
|
||||
my @plus_one=&ROUND(0,4,8,12);
|
||||
foreach (&NEON_lane_ROUND(0,4,8,12)) { eval; eval(shift(@plus_one)); }
|
||||
|
||||
foreach (@thread0) {
|
||||
eval; eval(shift(@thread3));
|
||||
eval(shift(@thread1)); eval(shift(@thread3));
|
||||
eval(shift(@thread2)); eval(shift(@thread3));
|
||||
}
|
||||
|
||||
@thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
|
||||
@thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
|
||||
@thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
|
||||
@thread3=&ROUND(0,5,10,15);
|
||||
|
||||
foreach (@thread0) {
|
||||
eval; eval(shift(@thread3));
|
||||
eval(shift(@thread1)); eval(shift(@thread3));
|
||||
eval(shift(@thread2)); eval(shift(@thread3));
|
||||
}
|
||||
@plus_one=&ROUND(0,5,10,15);
|
||||
foreach (&NEON_lane_ROUND(0,5,10,15)) { eval; eval(shift(@plus_one)); }
|
||||
$code.=<<___;
|
||||
cbnz $ctr,.Loop_neon
|
||||
|
||||
add.32 @x[0],@x[0],@d[0] // accumulate key block
|
||||
add $A0,$A0,@K[0]
|
||||
add @x[1],@x[1],@d[0],lsr#32
|
||||
add $A1,$A1,@K[0]
|
||||
add.32 @x[2],@x[2],@d[1]
|
||||
add $A2,$A2,@K[0]
|
||||
add @x[3],@x[3],@d[1],lsr#32
|
||||
add $C0,$C0,@K[2]
|
||||
add.32 @x[4],@x[4],@d[2]
|
||||
add $C1,$C1,@K[2]
|
||||
add @x[5],@x[5],@d[2],lsr#32
|
||||
add $C2,$C2,@K[2]
|
||||
add.32 @x[6],@x[6],@d[3]
|
||||
add $D0,$D0,@K[3]
|
||||
add @x[7],@x[7],@d[3],lsr#32
|
||||
add.32 @x[8],@x[8],@d[4]
|
||||
add $D1,$D1,@K[4]
|
||||
add @x[9],@x[9],@d[4],lsr#32
|
||||
add.32 @x[10],@x[10],@d[5]
|
||||
add $D2,$D2,@K[5]
|
||||
add @x[11],@x[11],@d[5],lsr#32
|
||||
add.32 @x[12],@x[12],@d[6]
|
||||
add $B0,$B0,@K[1]
|
||||
add @x[13],@x[13],@d[6],lsr#32
|
||||
add.32 @x[14],@x[14],@d[7]
|
||||
add $B1,$B1,@K[1]
|
||||
add @x[15],@x[15],@d[7],lsr#32
|
||||
add $B2,$B2,@K[1]
|
||||
add $xd0,$xd0,$CTR
|
||||
|
||||
zip1 $xt0,$xa0,$xa1 // transpose data
|
||||
zip1 $xt1,$xa2,$xa3
|
||||
zip2 $xt2,$xa0,$xa1
|
||||
zip2 $xt3,$xa2,$xa3
|
||||
zip1.64 $xa0,$xt0,$xt1
|
||||
zip2.64 $xa1,$xt0,$xt1
|
||||
zip1.64 $xa2,$xt2,$xt3
|
||||
zip2.64 $xa3,$xt2,$xt3
|
||||
|
||||
zip1 $xt0,$xb0,$xb1
|
||||
zip1 $xt1,$xb2,$xb3
|
||||
zip2 $xt2,$xb0,$xb1
|
||||
zip2 $xt3,$xb2,$xb3
|
||||
zip1.64 $xb0,$xt0,$xt1
|
||||
zip2.64 $xb1,$xt0,$xt1
|
||||
zip1.64 $xb2,$xt2,$xt3
|
||||
zip2.64 $xb3,$xt2,$xt3
|
||||
|
||||
zip1 $xt0,$xc0,$xc1
|
||||
add.32 @x[0],@x[0],@d[0] // accumulate key block
|
||||
zip1 $xt1,$xc2,$xc3
|
||||
add @x[1],@x[1],@d[0],lsr#32
|
||||
zip2 $xt2,$xc0,$xc1
|
||||
add.32 @x[2],@x[2],@d[1]
|
||||
zip2 $xt3,$xc2,$xc3
|
||||
add @x[3],@x[3],@d[1],lsr#32
|
||||
zip1.64 $xc0,$xt0,$xt1
|
||||
add.32 @x[4],@x[4],@d[2]
|
||||
zip2.64 $xc1,$xt0,$xt1
|
||||
add @x[5],@x[5],@d[2],lsr#32
|
||||
zip1.64 $xc2,$xt2,$xt3
|
||||
add.32 @x[6],@x[6],@d[3]
|
||||
zip2.64 $xc3,$xt2,$xt3
|
||||
add @x[7],@x[7],@d[3],lsr#32
|
||||
|
||||
zip1 $xt0,$xd0,$xd1
|
||||
add.32 @x[8],@x[8],@d[4]
|
||||
zip1 $xt1,$xd2,$xd3
|
||||
add @x[9],@x[9],@d[4],lsr#32
|
||||
zip2 $xt2,$xd0,$xd1
|
||||
add.32 @x[10],@x[10],@d[5]
|
||||
zip2 $xt3,$xd2,$xd3
|
||||
add @x[11],@x[11],@d[5],lsr#32
|
||||
zip1.64 $xd0,$xt0,$xt1
|
||||
add.32 @x[12],@x[12],@d[6]
|
||||
zip2.64 $xd1,$xt0,$xt1
|
||||
add @x[13],@x[13],@d[6],lsr#32
|
||||
zip1.64 $xd2,$xt2,$xt3
|
||||
add.32 @x[14],@x[14],@d[7]
|
||||
zip2.64 $xd3,$xt2,$xt3
|
||||
add @x[15],@x[15],@d[7],lsr#32
|
||||
|
||||
b.lo .Ltail_neon
|
||||
|
||||
add @x[0],@x[0],@x[1],lsl#32 // pack
|
||||
add @x[2],@x[2],@x[3],lsl#32
|
||||
ldp @x[1],@x[3],[$inp,#0] // load input
|
||||
add $xa0,$xa0,@K[0] // accumulate key block
|
||||
add @x[4],@x[4],@x[5],lsl#32
|
||||
add @x[6],@x[6],@x[7],lsl#32
|
||||
ldp @x[5],@x[7],[$inp,#16]
|
||||
add $xb0,$xb0,@K[1]
|
||||
add @x[8],@x[8],@x[9],lsl#32
|
||||
add @x[10],@x[10],@x[11],lsl#32
|
||||
ldp @x[9],@x[11],[$inp,#32]
|
||||
add $xc0,$xc0,@K[2]
|
||||
add @x[12],@x[12],@x[13],lsl#32
|
||||
add @x[14],@x[14],@x[15],lsl#32
|
||||
ldp @x[13],@x[15],[$inp,#48]
|
||||
add $xd0,$xd0,@K[3]
|
||||
add $inp,$inp,#64
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -521,48 +594,68 @@ $code.=<<___;
|
||||
rev @x[12],@x[12]
|
||||
rev @x[14],@x[14]
|
||||
#endif
|
||||
ld1.8 {$T0-$T3},[$inp],#64
|
||||
ld1.8 {$xt0-$xt3},[$inp],#64
|
||||
eor @x[0],@x[0],@x[1]
|
||||
add $xa1,$xa1,@K[0]
|
||||
eor @x[2],@x[2],@x[3]
|
||||
add $xb1,$xb1,@K[1]
|
||||
eor @x[4],@x[4],@x[5]
|
||||
add $xc1,$xc1,@K[2]
|
||||
eor @x[6],@x[6],@x[7]
|
||||
add $xd1,$xd1,@K[3]
|
||||
eor @x[8],@x[8],@x[9]
|
||||
eor $A0,$A0,$T0
|
||||
eor $xa0,$xa0,$xt0
|
||||
movi $xt0,#5
|
||||
eor @x[10],@x[10],@x[11]
|
||||
eor $B0,$B0,$T1
|
||||
eor $xb0,$xb0,$xt1
|
||||
eor @x[12],@x[12],@x[13]
|
||||
eor $C0,$C0,$T2
|
||||
eor $xc0,$xc0,$xt2
|
||||
eor @x[14],@x[14],@x[15]
|
||||
eor $D0,$D0,$T3
|
||||
ld1.8 {$T0-$T3},[$inp],#64
|
||||
eor $xd0,$xd0,$xt3
|
||||
add $CTR,$CTR,$xt0 // += 5
|
||||
ld1.8 {$xt0-$xt3},[$inp],#64
|
||||
|
||||
stp @x[0],@x[2],[$out,#0] // store output
|
||||
add @d[6],@d[6],#4 // increment counter
|
||||
add @d[6],@d[6],#5 // increment counter
|
||||
stp @x[4],@x[6],[$out,#16]
|
||||
add @K[3],@K[3],$ONE // += 4
|
||||
stp @x[8],@x[10],[$out,#32]
|
||||
add @K[4],@K[4],$ONE
|
||||
stp @x[12],@x[14],[$out,#48]
|
||||
add @K[5],@K[5],$ONE
|
||||
add $out,$out,#64
|
||||
|
||||
st1.8 {$A0-$D0},[$out],#64
|
||||
ld1.8 {$A0-$D0},[$inp],#64
|
||||
st1.8 {$xa0-$xd0},[$out],#64
|
||||
add $xa2,$xa2,@K[0]
|
||||
add $xb2,$xb2,@K[1]
|
||||
add $xc2,$xc2,@K[2]
|
||||
add $xd2,$xd2,@K[3]
|
||||
ld1.8 {$xa0-$xd0},[$inp],#64
|
||||
|
||||
eor $A1,$A1,$T0
|
||||
eor $B1,$B1,$T1
|
||||
eor $C1,$C1,$T2
|
||||
eor $D1,$D1,$T3
|
||||
st1.8 {$A1-$D1},[$out],#64
|
||||
eor $xa1,$xa1,$xt0
|
||||
eor $xb1,$xb1,$xt1
|
||||
eor $xc1,$xc1,$xt2
|
||||
eor $xd1,$xd1,$xt3
|
||||
st1.8 {$xa1-$xd1},[$out],#64
|
||||
add $xa3,$xa3,@K[0]
|
||||
add $xb3,$xb3,@K[1]
|
||||
add $xc3,$xc3,@K[2]
|
||||
add $xd3,$xd3,@K[3]
|
||||
ld1.8 {$xa1-$xd1},[$inp],#64
|
||||
|
||||
eor $A2,$A2,$A0
|
||||
eor $B2,$B2,$B0
|
||||
eor $C2,$C2,$C0
|
||||
eor $D2,$D2,$D0
|
||||
st1.8 {$A2-$D2},[$out],#64
|
||||
eor $xa2,$xa2,$xa0
|
||||
eor $xb2,$xb2,$xb0
|
||||
eor $xc2,$xc2,$xc0
|
||||
eor $xd2,$xd2,$xd0
|
||||
st1.8 {$xa2-$xd2},[$out],#64
|
||||
|
||||
eor $xa3,$xa3,$xa1
|
||||
eor $xb3,$xb3,$xb1
|
||||
eor $xc3,$xc3,$xc1
|
||||
eor $xd3,$xd3,$xd1
|
||||
st1.8 {$xa3-$xd3},[$out],#64
|
||||
|
||||
b.hi .Loop_outer_neon
|
||||
|
||||
ldp d8,d9,[sp] // meet ABI requirements
|
||||
|
||||
ldp x19,x20,[x29,#16]
|
||||
add sp,sp,#64
|
||||
ldp x21,x22,[x29,#32]
|
||||
@@ -573,8 +666,10 @@ $code.=<<___;
|
||||
.inst 0xd50323bf // autiasp
|
||||
ret
|
||||
|
||||
.align 4
|
||||
.Ltail_neon:
|
||||
add $len,$len,#256
|
||||
add $len,$len,#320
|
||||
ldp d8,d9,[sp] // meet ABI requirements
|
||||
cmp $len,#64
|
||||
b.lo .Less_than_64
|
||||
|
||||
@@ -591,7 +686,7 @@ $code.=<<___;
|
||||
add @x[14],@x[14],@x[15],lsl#32
|
||||
ldp @x[13],@x[15],[$inp,#48]
|
||||
add $inp,$inp,#64
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -611,48 +706,68 @@ $code.=<<___;
|
||||
eor @x[14],@x[14],@x[15]
|
||||
|
||||
stp @x[0],@x[2],[$out,#0] // store output
|
||||
add @d[6],@d[6],#4 // increment counter
|
||||
add $xa0,$xa0,@K[0] // accumulate key block
|
||||
stp @x[4],@x[6],[$out,#16]
|
||||
add $xb0,$xb0,@K[1]
|
||||
stp @x[8],@x[10],[$out,#32]
|
||||
add $xc0,$xc0,@K[2]
|
||||
stp @x[12],@x[14],[$out,#48]
|
||||
add $xd0,$xd0,@K[3]
|
||||
add $out,$out,#64
|
||||
b.eq .Ldone_neon
|
||||
sub $len,$len,#64
|
||||
cmp $len,#64
|
||||
b.lo .Less_than_128
|
||||
b.lo .Last_neon
|
||||
|
||||
ld1.8 {$T0-$T3},[$inp],#64
|
||||
eor $A0,$A0,$T0
|
||||
eor $B0,$B0,$T1
|
||||
eor $C0,$C0,$T2
|
||||
eor $D0,$D0,$T3
|
||||
st1.8 {$A0-$D0},[$out],#64
|
||||
ld1.8 {$xt0-$xt3},[$inp],#64
|
||||
eor $xa0,$xa0,$xt0
|
||||
eor $xb0,$xb0,$xt1
|
||||
eor $xc0,$xc0,$xt2
|
||||
eor $xd0,$xd0,$xt3
|
||||
st1.8 {$xa0-$xd0},[$out],#64
|
||||
b.eq .Ldone_neon
|
||||
|
||||
add $xa0,$xa1,@K[0]
|
||||
add $xb0,$xb1,@K[1]
|
||||
sub $len,$len,#64
|
||||
add $xc0,$xc1,@K[2]
|
||||
cmp $len,#64
|
||||
b.lo .Less_than_192
|
||||
add $xd0,$xd1,@K[3]
|
||||
b.lo .Last_neon
|
||||
|
||||
ld1.8 {$T0-$T3},[$inp],#64
|
||||
eor $A1,$A1,$T0
|
||||
eor $B1,$B1,$T1
|
||||
eor $C1,$C1,$T2
|
||||
eor $D1,$D1,$T3
|
||||
st1.8 {$A1-$D1},[$out],#64
|
||||
ld1.8 {$xt0-$xt3},[$inp],#64
|
||||
eor $xa1,$xa0,$xt0
|
||||
eor $xb1,$xb0,$xt1
|
||||
eor $xc1,$xc0,$xt2
|
||||
eor $xd1,$xd0,$xt3
|
||||
st1.8 {$xa1-$xd1},[$out],#64
|
||||
b.eq .Ldone_neon
|
||||
|
||||
add $xa0,$xa2,@K[0]
|
||||
add $xb0,$xb2,@K[1]
|
||||
sub $len,$len,#64
|
||||
add $xc0,$xc2,@K[2]
|
||||
cmp $len,#64
|
||||
add $xd0,$xd2,@K[3]
|
||||
b.lo .Last_neon
|
||||
|
||||
ld1.8 {$xt0-$xt3},[$inp],#64
|
||||
eor $xa2,$xa0,$xt0
|
||||
eor $xb2,$xb0,$xt1
|
||||
eor $xc2,$xc0,$xt2
|
||||
eor $xd2,$xd0,$xt3
|
||||
st1.8 {$xa2-$xd2},[$out],#64
|
||||
b.eq .Ldone_neon
|
||||
|
||||
add $xa0,$xa3,@K[0]
|
||||
add $xb0,$xb3,@K[1]
|
||||
add $xc0,$xc3,@K[2]
|
||||
add $xd0,$xd3,@K[3]
|
||||
sub $len,$len,#64
|
||||
|
||||
st1.8 {$A2-$D2},[sp]
|
||||
b .Last_neon
|
||||
|
||||
.Less_than_128:
|
||||
st1.8 {$A0-$D0},[sp]
|
||||
b .Last_neon
|
||||
.Less_than_192:
|
||||
st1.8 {$A1-$D1},[sp]
|
||||
b .Last_neon
|
||||
|
||||
.align 4
|
||||
.Last_neon:
|
||||
st1.8 {$xa0-$xd0},[sp]
|
||||
|
||||
sub $out,$out,#1
|
||||
add $inp,$inp,$len
|
||||
add $out,$out,$len
|
||||
@@ -685,9 +800,41 @@ $code.=<<___;
|
||||
.size ChaCha20_neon,.-ChaCha20_neon
|
||||
___
|
||||
{
|
||||
my @K = map("v$_.4s",(0..6));
|
||||
my ($T0,$T1,$T2,$T3,$T4,$T5)=@K;
|
||||
my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,
|
||||
$A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23));
|
||||
$A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(8..31));
|
||||
my $rot24 = @K[6];
|
||||
my $ONE = "v7.4s";
|
||||
|
||||
sub NEONROUND {
|
||||
my $odd = pop;
|
||||
my ($a,$b,$c,$d,$t)=@_;
|
||||
|
||||
(
|
||||
"&add ('$a','$a','$b')",
|
||||
"&eor ('$d','$d','$a')",
|
||||
"&rev32_16 ('$d','$d')", # vrot ($d,16)
|
||||
|
||||
"&add ('$c','$c','$d')",
|
||||
"&eor ('$t','$b','$c')",
|
||||
"&ushr ('$b','$t',20)",
|
||||
"&sli ('$b','$t',12)",
|
||||
|
||||
"&add ('$a','$a','$b')",
|
||||
"&eor ('$d','$d','$a')",
|
||||
"&tbl ('$d','{$d}','$rot24')",
|
||||
|
||||
"&add ('$c','$c','$d')",
|
||||
"&eor ('$t','$b','$c')",
|
||||
"&ushr ('$b','$t',25)",
|
||||
"&sli ('$b','$t',7)",
|
||||
|
||||
"&ext ('$c','$c','$c',8)",
|
||||
"&ext ('$d','$d','$d',$odd?4:12)",
|
||||
"&ext ('$b','$b','$b',$odd?12:4)"
|
||||
);
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
.type ChaCha20_512_neon,%function
|
||||
@@ -707,6 +854,7 @@ ChaCha20_512_neon:
|
||||
.L512_or_more_neon:
|
||||
sub sp,sp,#128+64
|
||||
|
||||
eor $ONE,$ONE,$ONE
|
||||
ldp @d[0],@d[1],[@x[0]] // load sigma
|
||||
ld1 {@K[0]},[@x[0]],#16
|
||||
ldp @d[2],@d[3],[$key] // load key
|
||||
@@ -714,8 +862,9 @@ ChaCha20_512_neon:
|
||||
ld1 {@K[1],@K[2]},[$key]
|
||||
ldp @d[6],@d[7],[$ctr] // load counter
|
||||
ld1 {@K[3]},[$ctr]
|
||||
ld1 {$ONE},[@x[0]]
|
||||
#ifdef __ARMEB__
|
||||
ld1 {$ONE}[0],[@x[0]]
|
||||
add $key,@x[0],#16 // .Lrot24
|
||||
#ifdef __AARCH64EB__
|
||||
rev64 @K[0],@K[0]
|
||||
ror @d[2],@d[2],#32
|
||||
ror @d[3],@d[3],#32
|
||||
@@ -782,9 +931,10 @@ ChaCha20_512_neon:
|
||||
mov $C4,@K[2]
|
||||
stp @K[3],@K[4],[sp,#48] // off-load key block, variable part
|
||||
mov $C5,@K[2]
|
||||
str @K[5],[sp,#80]
|
||||
stp @K[5],@K[6],[sp,#80]
|
||||
|
||||
mov $ctr,#5
|
||||
ld1 {$rot24},[$key]
|
||||
subs $len,$len,#512
|
||||
.Loop_upper_neon:
|
||||
sub $ctr,$ctr,#1
|
||||
@@ -857,7 +1007,7 @@ $code.=<<___;
|
||||
add @x[14],@x[14],@x[15],lsl#32
|
||||
ldp @x[13],@x[15],[$inp,#48]
|
||||
add $inp,$inp,#64
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -946,6 +1096,7 @@ $code.=<<___;
|
||||
add.32 @x[2],@x[2],@d[1]
|
||||
ldp @K[4],@K[5],[sp,#64]
|
||||
add @x[3],@x[3],@d[1],lsr#32
|
||||
ldr @K[6],[sp,#96]
|
||||
add $A0,$A0,@K[0]
|
||||
add.32 @x[4],@x[4],@d[2]
|
||||
add $A1,$A1,@K[0]
|
||||
@@ -998,7 +1149,7 @@ $code.=<<___;
|
||||
add $inp,$inp,#64
|
||||
add $B5,$B5,@K[1]
|
||||
|
||||
#ifdef __ARMEB__
|
||||
#ifdef __AARCH64EB__
|
||||
rev @x[0],@x[0]
|
||||
rev @x[2],@x[2]
|
||||
rev @x[4],@x[4]
|
||||
@@ -1076,24 +1227,24 @@ $code.=<<___;
|
||||
b.hs .Loop_outer_512_neon
|
||||
|
||||
adds $len,$len,#512
|
||||
ushr $A0,$ONE,#2 // 4 -> 1
|
||||
ushr $ONE,$ONE,#1 // 4 -> 2
|
||||
|
||||
ldp d8,d9,[sp,#128+0] // meet ABI requirements
|
||||
ldp d10,d11,[sp,#128+16]
|
||||
ldp d12,d13,[sp,#128+32]
|
||||
ldp d14,d15,[sp,#128+48]
|
||||
|
||||
stp @K[0],$ONE,[sp,#0] // wipe off-load area
|
||||
stp @K[0],$ONE,[sp,#32]
|
||||
stp @K[0],$ONE,[sp,#64]
|
||||
stp @K[0],@K[0],[sp,#0] // wipe off-load area
|
||||
stp @K[0],@K[0],[sp,#32]
|
||||
stp @K[0],@K[0],[sp,#64]
|
||||
|
||||
b.eq .Ldone_512_neon
|
||||
|
||||
sub $key,$key,#16 // .Lone
|
||||
cmp $len,#192
|
||||
sub @K[3],@K[3],$A0 // -= 1
|
||||
sub @K[4],@K[4],$A0
|
||||
sub @K[5],@K[5],$A0
|
||||
add sp,sp,#128
|
||||
sub @K[3],@K[3],$ONE // -= 2
|
||||
ld1 {$CTR,$ROT24},[$key]
|
||||
b.hs .Loop_outer_neon
|
||||
|
||||
eor @K[1],@K[1],@K[1]
|
||||
@@ -1123,9 +1274,11 @@ foreach (split("\n",$code)) {
|
||||
s/\`([^\`]*)\`/eval $1/geo;
|
||||
|
||||
(s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1)) or
|
||||
(m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1)) or
|
||||
(m/\b(eor|ext|mov|tbl)\b/ and (s/\.4s/\.16b/g or 1)) or
|
||||
(s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1)) or
|
||||
(m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1)) or
|
||||
(m/\b(dup|ld1)\b/ and (s/\.4(s}?\[[0-3]\])/.$1/g or 1)) or
|
||||
(s/\b(zip[12])\.64\b/$1/ and (s/\.4s/\.2d/g or 1)) or
|
||||
(s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1));
|
||||
|
||||
#s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
use strict;
|
||||
use FindBin qw($Bin);
|
||||
use lib "$Bin/../..";
|
||||
use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE);
|
||||
use perlasm::s390x qw(:DEFAULT :VX :LD AUTOLOAD LABEL INCLUDE);
|
||||
|
||||
my $flavour = shift;
|
||||
|
||||
|
||||
@@ -69,6 +69,12 @@ const char *OpenSSL_version(int t)
|
||||
return "ENGINESDIR: \"" ENGINESDIR "\"";
|
||||
#else
|
||||
return "ENGINESDIR: N/A";
|
||||
#endif
|
||||
case OPENSSL_MODULES_DIR:
|
||||
#ifdef MODULESDIR
|
||||
return "MODULESDIR: \"" MODULESDIR "\"";
|
||||
#else
|
||||
return "MODULESDIR: N/A";
|
||||
#endif
|
||||
}
|
||||
return "not available";
|
||||
|
||||
@@ -1488,7 +1488,7 @@ $code.=<<___;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
|
||||
// int rep);
|
||||
// uint64_t rep);
|
||||
.globl ecp_nistz256_ord_sqr_mont
|
||||
.type ecp_nistz256_ord_sqr_mont,%function
|
||||
.align 4
|
||||
|
||||
@@ -1919,7 +1919,7 @@ $code.=<<___;
|
||||
|
||||
################################################################################
|
||||
# void ecp_nistz256_ord_sqr_mont(uint64_t res[4], uint64_t a[4],
|
||||
# int rep);
|
||||
# uint64_t rep);
|
||||
.globl ecp_nistz256_ord_sqr_mont
|
||||
.align 5
|
||||
ecp_nistz256_ord_sqr_mont:
|
||||
|
||||
@@ -826,7 +826,7 @@ $code.=<<___;
|
||||
# void ecp_nistz256_ord_sqr_mont(
|
||||
# uint64_t res[4],
|
||||
# uint64_t a[4],
|
||||
# int rep);
|
||||
# uint64_t rep);
|
||||
|
||||
.globl ecp_nistz256_ord_sqr_mont
|
||||
.type ecp_nistz256_ord_sqr_mont,\@function,3
|
||||
|
||||
+2
-2
@@ -441,7 +441,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
* scalar multiplication implementation based on a Montgomery ladder,
|
||||
* with various timing attack defenses.
|
||||
*/
|
||||
if ((scalar != NULL) && (num == 0)) {
|
||||
if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * GeneratorPoint: this
|
||||
* codepath is reached most prominently by (ephemeral) key
|
||||
@@ -452,7 +452,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
*/
|
||||
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
|
||||
}
|
||||
if ((scalar == NULL) && (num == 1)) {
|
||||
if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * VariablePoint: this
|
||||
* codepath is reached most prominently by the second half of ECDH,
|
||||
|
||||
@@ -1467,7 +1467,7 @@ void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS],
|
||||
const BN_ULONG b[P256_LIMBS]);
|
||||
void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS],
|
||||
const BN_ULONG a[P256_LIMBS],
|
||||
int rep);
|
||||
BN_ULONG rep);
|
||||
|
||||
static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *x, BN_CTX *ctx)
|
||||
|
||||
@@ -66,6 +66,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
|
||||
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
|
||||
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
|
||||
{ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <openssl/storeerr.h>
|
||||
#include <openssl/esserr.h>
|
||||
#include "internal/propertyerr.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
int err_load_crypto_strings_int(void)
|
||||
{
|
||||
@@ -102,7 +103,8 @@ int err_load_crypto_strings_int(void)
|
||||
#endif
|
||||
ERR_load_KDF_strings() == 0 ||
|
||||
ERR_load_OSSL_STORE_strings() == 0 ||
|
||||
ERR_load_PROP_strings() == 0)
|
||||
ERR_load_PROP_strings() == 0 ||
|
||||
ERR_load_PROV_strings() == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -37,6 +37,7 @@ L SM2 crypto/include/internal/sm2.h crypto/sm2/sm2_err.c
|
||||
L OSSL_STORE include/openssl/store.h crypto/store/store_err.c
|
||||
L ESS include/openssl/ess.h crypto/ess/ess_err.c
|
||||
L PROP include/internal/property.h crypto/property/property_err.c
|
||||
L PROV providers/common/include/internal/providercommon.h providers/common/provider_err.c
|
||||
|
||||
# additional header files to be scanned for function names
|
||||
L NONE include/openssl/x509_vfy.h NONE
|
||||
|
||||
@@ -785,6 +785,9 @@ EVP_F_EVP_CIPHER_ASN1_TO_PARAM:204:EVP_CIPHER_asn1_to_param
|
||||
EVP_F_EVP_CIPHER_CTX_COPY:163:EVP_CIPHER_CTX_copy
|
||||
EVP_F_EVP_CIPHER_CTX_CTRL:124:EVP_CIPHER_CTX_ctrl
|
||||
EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH:122:EVP_CIPHER_CTX_set_key_length
|
||||
EVP_F_EVP_CIPHER_CTX_SET_PADDING:237:EVP_CIPHER_CTX_set_padding
|
||||
EVP_F_EVP_CIPHER_FROM_DISPATCH:238:evp_cipher_from_dispatch
|
||||
EVP_F_EVP_CIPHER_MODE:239:EVP_CIPHER_mode
|
||||
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
|
||||
@@ -1102,6 +1105,21 @@ PROP_F_PARSE_NUMBER:104:parse_number
|
||||
PROP_F_PARSE_OCT:105:parse_oct
|
||||
PROP_F_PARSE_STRING:106:parse_string
|
||||
PROP_F_PARSE_UNQUOTED:107:parse_unquoted
|
||||
PROV_F_AESNI_INIT_KEY:101:aesni_init_key
|
||||
PROV_F_AES_BLOCK_FINAL:102:aes_block_final
|
||||
PROV_F_AES_BLOCK_UPDATE:103:aes_block_update
|
||||
PROV_F_AES_CIPHER:104:aes_cipher
|
||||
PROV_F_AES_CTX_GET_PARAMS:105:aes_ctx_get_params
|
||||
PROV_F_AES_CTX_SET_PARAMS:106:aes_ctx_set_params
|
||||
PROV_F_AES_DINIT:107:aes_dinit
|
||||
PROV_F_AES_DUPCTX:108:aes_dupctx
|
||||
PROV_F_AES_EINIT:109:aes_einit
|
||||
PROV_F_AES_INIT_KEY:110:aes_init_key
|
||||
PROV_F_AES_STREAM_UPDATE:111:aes_stream_update
|
||||
PROV_F_AES_T4_INIT_KEY:112:aes_t4_init_key
|
||||
PROV_F_PROV_AES_KEY_GENERIC_INIT:113:PROV_AES_KEY_generic_init
|
||||
PROV_F_TRAILINGDATA:114:trailingdata
|
||||
PROV_F_UNPADBLOCK:100:unpadblock
|
||||
RAND_F_DRBG_BYTES:101:drbg_bytes
|
||||
RAND_F_DRBG_CTR_INIT:125:drbg_ctr_init
|
||||
RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
|
||||
@@ -2381,6 +2399,7 @@ EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
|
||||
EVP_R_INVALID_KEY:163:invalid key
|
||||
EVP_R_INVALID_KEY_LENGTH:130:invalid key length
|
||||
EVP_R_INVALID_OPERATION:148:invalid operation
|
||||
EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
|
||||
EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
|
||||
EVP_R_KEYGEN_FAILURE:120:keygen failure
|
||||
EVP_R_KEY_SETUP_FAILED:180:key setup failed
|
||||
@@ -2604,6 +2623,14 @@ PROP_R_NO_VALUE:107:no value
|
||||
PROP_R_PARSE_FAILED:108:parse failed
|
||||
PROP_R_STRING_TOO_LONG:109:string too long
|
||||
PROP_R_TRAILING_CHARACTERS:110:trailing characters
|
||||
PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed
|
||||
PROV_R_BAD_DECRYPT:100:bad decrypt
|
||||
PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
|
||||
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
|
||||
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
|
||||
PROV_R_INVALID_KEYLEN:105:invalid keylen
|
||||
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
|
||||
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
|
||||
RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
|
||||
RAND_R_ALREADY_INSTANTIATED:103:already instantiated
|
||||
RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
|
||||
|
||||
+30
-2
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
|
||||
@@ -21,6 +22,12 @@ EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
|
||||
cipher->nid = cipher_type;
|
||||
cipher->block_size = block_size;
|
||||
cipher->key_len = key_len;
|
||||
cipher->lock = CRYPTO_THREAD_lock_new();
|
||||
if (cipher->lock == NULL) {
|
||||
OPENSSL_free(cipher);
|
||||
return NULL;
|
||||
}
|
||||
cipher->refcnt = 1;
|
||||
}
|
||||
return cipher;
|
||||
}
|
||||
@@ -30,14 +37,35 @@ EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
|
||||
EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
|
||||
cipher->key_len);
|
||||
|
||||
if (to != NULL)
|
||||
if (to != NULL) {
|
||||
CRYPTO_RWLOCK *lock = to->lock;
|
||||
|
||||
memcpy(to, cipher, sizeof(*to));
|
||||
to->lock = lock;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
|
||||
{
|
||||
OPENSSL_free(cipher);
|
||||
if (cipher != NULL) {
|
||||
int i;
|
||||
|
||||
CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
|
||||
if (i > 0)
|
||||
return;
|
||||
ossl_provider_free(cipher->prov);
|
||||
CRYPTO_THREAD_lock_free(cipher->lock);
|
||||
OPENSSL_free(cipher);
|
||||
}
|
||||
}
|
||||
|
||||
int EVP_CIPHER_upref(EVP_CIPHER *cipher)
|
||||
{
|
||||
int ref = 0;
|
||||
|
||||
CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
|
||||
|
||||
+5
-4
@@ -295,6 +295,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
|
||||
{
|
||||
int ret;
|
||||
size_t size = 0;
|
||||
size_t mdsize = EVP_MD_size(ctx->digest);
|
||||
|
||||
if (ctx->digest == NULL || ctx->digest->prov == NULL)
|
||||
goto legacy;
|
||||
@@ -304,7 +305,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ctx->digest->dfinal(ctx->provctx, md, &size);
|
||||
ret = ctx->digest->dfinal(ctx->provctx, md, &size, mdsize);
|
||||
|
||||
if (isize != NULL) {
|
||||
if (size <= UINT_MAX) {
|
||||
@@ -321,10 +322,10 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
|
||||
OPENSSL_assert(mdsize <= EVP_MAX_MD_SIZE);
|
||||
ret = ctx->digest->final(ctx, md);
|
||||
if (isize != NULL)
|
||||
*isize = ctx->digest->md_size;
|
||||
*isize = mdsize;
|
||||
if (ctx->digest->cleanup) {
|
||||
ctx->digest->cleanup(ctx);
|
||||
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
|
||||
@@ -516,7 +517,7 @@ static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
|
||||
md->dinit = OSSL_get_OP_digest_init(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_UPDDATE:
|
||||
case OSSL_FUNC_DIGEST_UPDATE:
|
||||
if (md->dupdate != NULL)
|
||||
break;
|
||||
md->dupdate = OSSL_get_OP_digest_update(fns);
|
||||
|
||||
+510
-27
@@ -15,25 +15,46 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rand_drbg.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c)
|
||||
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
if (c == NULL)
|
||||
if (ctx == NULL)
|
||||
return 1;
|
||||
if (c->cipher != NULL) {
|
||||
if (c->cipher->cleanup && !c->cipher->cleanup(c))
|
||||
|
||||
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (ctx->provctx != NULL) {
|
||||
if (ctx->cipher->freectx != NULL)
|
||||
ctx->cipher->freectx(ctx->provctx);
|
||||
ctx->provctx = NULL;
|
||||
}
|
||||
if (ctx->fetched_cipher != NULL)
|
||||
EVP_CIPHER_meth_free(ctx->fetched_cipher);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
return 1;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
if (ctx->cipher != NULL) {
|
||||
if (ctx->cipher->cleanup && !ctx->cipher->cleanup(ctx))
|
||||
return 0;
|
||||
/* Cleanse cipher context data */
|
||||
if (c->cipher_data && c->cipher->ctx_size)
|
||||
OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
|
||||
if (ctx->cipher_data && ctx->cipher->ctx_size)
|
||||
OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
|
||||
}
|
||||
OPENSSL_free(c->cipher_data);
|
||||
OPENSSL_free(ctx->cipher_data);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(c->engine);
|
||||
ENGINE_finish(ctx->engine);
|
||||
#endif
|
||||
memset(c, 0, sizeof(*c));
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -60,13 +81,30 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
ENGINE *impl, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
if (enc == -1)
|
||||
EVP_CIPHER *provciph = NULL;
|
||||
ENGINE *tmpimpl = NULL;
|
||||
const EVP_CIPHER *tmpcipher;
|
||||
|
||||
/*
|
||||
* enc == 1 means we are encrypting.
|
||||
* enc == 0 means we are decrypting.
|
||||
* enc == -1 means, use the previously initialised value for encrypt/decrypt
|
||||
*/
|
||||
if (enc == -1) {
|
||||
enc = ctx->encrypt;
|
||||
else {
|
||||
} else {
|
||||
if (enc)
|
||||
enc = 1;
|
||||
ctx->encrypt = enc;
|
||||
}
|
||||
|
||||
if (cipher == NULL && ctx->cipher == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -77,11 +115,161 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
if (ctx->engine && ctx->cipher
|
||||
&& (cipher == NULL || cipher->nid == ctx->cipher->nid))
|
||||
goto skip_to_init;
|
||||
|
||||
if (cipher != NULL && impl == NULL) {
|
||||
/* Ask if an ENGINE is reserved for this job */
|
||||
tmpimpl = ENGINE_get_cipher_engine(cipher->nid);
|
||||
}
|
||||
#endif
|
||||
if (cipher) {
|
||||
|
||||
/*
|
||||
* If there are engines involved then we should use legacy handling for now.
|
||||
*/
|
||||
if (ctx->engine != NULL
|
||||
|| impl != NULL
|
||||
|| tmpimpl != NULL) {
|
||||
if (ctx->cipher == ctx->fetched_cipher)
|
||||
ctx->cipher = NULL;
|
||||
EVP_CIPHER_meth_free(ctx->fetched_cipher);
|
||||
ctx->fetched_cipher = NULL;
|
||||
goto legacy;
|
||||
}
|
||||
|
||||
tmpcipher = (cipher == NULL) ? ctx->cipher : cipher;
|
||||
|
||||
if (tmpcipher->prov == NULL) {
|
||||
switch(tmpcipher->nid) {
|
||||
case NID_aes_256_ecb:
|
||||
case NID_aes_192_ecb:
|
||||
case NID_aes_128_ecb:
|
||||
case NID_aes_256_cbc:
|
||||
case NID_aes_192_cbc:
|
||||
case NID_aes_128_cbc:
|
||||
case NID_aes_256_ofb128:
|
||||
case NID_aes_192_ofb128:
|
||||
case NID_aes_128_ofb128:
|
||||
case NID_aes_256_cfb128:
|
||||
case NID_aes_192_cfb128:
|
||||
case NID_aes_128_cfb128:
|
||||
case NID_aes_256_cfb1:
|
||||
case NID_aes_192_cfb1:
|
||||
case NID_aes_128_cfb1:
|
||||
case NID_aes_256_cfb8:
|
||||
case NID_aes_192_cfb8:
|
||||
case NID_aes_128_cfb8:
|
||||
case NID_aes_256_ctr:
|
||||
case NID_aes_192_ctr:
|
||||
case NID_aes_128_ctr:
|
||||
break;
|
||||
default:
|
||||
goto legacy;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure a context left lying around from last time is cleared
|
||||
* (legacy code)
|
||||
*/
|
||||
if (cipher != NULL && ctx->cipher != NULL) {
|
||||
OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
|
||||
ctx->cipher_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* TODO(3.0): Start of non-legacy code below */
|
||||
|
||||
/* Ensure a context left lying around from last time is cleared */
|
||||
if (cipher != NULL && ctx->cipher != NULL) {
|
||||
unsigned long flags = ctx->flags;
|
||||
|
||||
EVP_CIPHER_CTX_reset(ctx);
|
||||
/* Restore encrypt and flags */
|
||||
ctx->encrypt = enc;
|
||||
ctx->flags = flags;
|
||||
}
|
||||
|
||||
if (cipher != NULL)
|
||||
ctx->cipher = cipher;
|
||||
else
|
||||
cipher = ctx->cipher;
|
||||
|
||||
if (cipher->prov == NULL) {
|
||||
provciph = EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
|
||||
if (provciph == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
cipher = provciph;
|
||||
EVP_CIPHER_meth_free(ctx->fetched_cipher);
|
||||
ctx->fetched_cipher = provciph;
|
||||
}
|
||||
|
||||
ctx->cipher = cipher;
|
||||
if (ctx->provctx == NULL) {
|
||||
ctx->provctx = ctx->cipher->newctx();
|
||||
if (ctx->provctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
|
||||
/*
|
||||
* Ensure a context left lying around from last time is cleared (the
|
||||
* previous check attempted to avoid this if the same ENGINE and
|
||||
* If this ctx was already set up for no padding then we need to tell
|
||||
* the new cipher about it.
|
||||
*/
|
||||
if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (EVP_CIPHER_mode(ctx->cipher)) {
|
||||
case EVP_CIPH_CFB_MODE:
|
||||
case EVP_CIPH_OFB_MODE:
|
||||
case EVP_CIPH_CBC_MODE:
|
||||
/* For these modes we remember the original IV for later use */
|
||||
if (!ossl_assert(EVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->oiv))) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (iv != NULL)
|
||||
memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
|
||||
}
|
||||
|
||||
if (enc) {
|
||||
if (ctx->cipher->einit == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->cipher->einit(ctx->provctx,
|
||||
key,
|
||||
key == NULL ? 0
|
||||
: EVP_CIPHER_CTX_key_length(ctx),
|
||||
iv,
|
||||
iv == NULL ? 0
|
||||
: EVP_CIPHER_CTX_iv_length(ctx));
|
||||
}
|
||||
|
||||
if (ctx->cipher->dinit == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->cipher->dinit(ctx->provctx,
|
||||
key,
|
||||
key == NULL ? 0
|
||||
: EVP_CIPHER_CTX_key_length(ctx),
|
||||
iv,
|
||||
iv == NULL ? 0
|
||||
: EVP_CIPHER_CTX_iv_length(ctx));
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
if (cipher != NULL) {
|
||||
/*
|
||||
* Ensure a context left lying around from last time is cleared (we
|
||||
* previously attempted to avoid this if the same ENGINE and
|
||||
* EVP_CIPHER could be used).
|
||||
*/
|
||||
if (ctx->cipher) {
|
||||
@@ -92,18 +280,19 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
ctx->flags = flags;
|
||||
}
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
if (impl) {
|
||||
if (impl != NULL) {
|
||||
if (!ENGINE_init(impl)) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
/* Ask if an ENGINE is reserved for this job */
|
||||
impl = ENGINE_get_cipher_engine(cipher->nid);
|
||||
if (impl) {
|
||||
} else {
|
||||
impl = tmpimpl;
|
||||
}
|
||||
if (impl != NULL) {
|
||||
/* There's an ENGINE for this job ... (apparently) */
|
||||
const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
|
||||
if (!c) {
|
||||
|
||||
if (c == NULL) {
|
||||
/*
|
||||
* One positive side-effect of US's export control history,
|
||||
* is that we should at least be able to avoid using US
|
||||
@@ -119,8 +308,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
* from an ENGINE and we need to release it when done.
|
||||
*/
|
||||
ctx->engine = impl;
|
||||
} else
|
||||
} else {
|
||||
ctx->engine = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->cipher = cipher;
|
||||
@@ -144,9 +334,6 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (!ctx->cipher) {
|
||||
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
skip_to_init:
|
||||
@@ -377,12 +564,39 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
|
||||
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
const unsigned char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
size_t soutl;
|
||||
int blocksize;
|
||||
|
||||
/* Prevent accidental use of decryption context when encrypting */
|
||||
if (!ctx->encrypt) {
|
||||
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
||||
|
||||
if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
||||
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
|
||||
inl + (blocksize == 1 ? 0 : blocksize), in,
|
||||
(size_t)inl);
|
||||
|
||||
if (soutl > INT_MAX) {
|
||||
EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*outl = soutl;
|
||||
return ret;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
|
||||
}
|
||||
|
||||
@@ -397,6 +611,8 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
||||
{
|
||||
int n, ret;
|
||||
unsigned int i, b, bl;
|
||||
size_t soutl;
|
||||
int blocksize;
|
||||
|
||||
/* Prevent accidental use of decryption context when encrypting */
|
||||
if (!ctx->encrypt) {
|
||||
@@ -404,6 +620,30 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
||||
|
||||
if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
|
||||
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
|
||||
blocksize == 1 ? 0 : blocksize);
|
||||
|
||||
if (soutl > INT_MAX) {
|
||||
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*outl = soutl;
|
||||
|
||||
return ret;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
|
||||
if (ret < 0)
|
||||
@@ -444,8 +684,10 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
||||
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
const unsigned char *in, int inl)
|
||||
{
|
||||
int fix_len, cmpl = inl;
|
||||
int fix_len, cmpl = inl, ret;
|
||||
unsigned int b;
|
||||
size_t soutl;
|
||||
int blocksize;
|
||||
|
||||
/* Prevent accidental use of encryption context when decrypting */
|
||||
if (ctx->encrypt) {
|
||||
@@ -453,6 +695,32 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
||||
|
||||
if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
||||
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
|
||||
inl + (blocksize == 1 ? 0 : blocksize), in,
|
||||
(size_t)inl);
|
||||
|
||||
if (ret) {
|
||||
if (soutl > INT_MAX) {
|
||||
EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*outl = soutl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
b = ctx->cipher->block_size;
|
||||
|
||||
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
|
||||
@@ -527,6 +795,9 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
||||
{
|
||||
int i, n;
|
||||
unsigned int b;
|
||||
size_t soutl;
|
||||
int ret;
|
||||
int blocksize;
|
||||
|
||||
/* Prevent accidental use of encryption context when decrypting */
|
||||
if (ctx->encrypt) {
|
||||
@@ -534,6 +805,32 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
||||
|
||||
if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
|
||||
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
|
||||
blocksize == 1 ? 0 : blocksize);
|
||||
|
||||
if (ret) {
|
||||
if (soutl > INT_MAX) {
|
||||
EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*outl = soutl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
*outl = 0;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
@@ -590,7 +887,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
|
||||
{
|
||||
if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
|
||||
return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
|
||||
if (c->key_len == keylen)
|
||||
if (EVP_CIPHER_CTX_key_length(c) == keylen)
|
||||
return 1;
|
||||
if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
|
||||
c->key_len = keylen;
|
||||
@@ -606,6 +903,24 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
|
||||
ctx->flags &= ~EVP_CIPH_NO_PADDING;
|
||||
else
|
||||
ctx->flags |= EVP_CIPH_NO_PADDING;
|
||||
|
||||
if (ctx->cipher != NULL && ctx->cipher->prov != NULL) {
|
||||
OSSL_PARAM params[] = {
|
||||
OSSL_PARAM_int(OSSL_CIPHER_PARAM_PADDING, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
params[0].data = &pad;
|
||||
|
||||
if (ctx->cipher->ctx_set_params == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHER_CTX_SET_PADDING, EVP_R_CTRL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->cipher->ctx_set_params(ctx->provctx, params))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -636,7 +951,7 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
|
||||
{
|
||||
if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
|
||||
return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
|
||||
if (RAND_priv_bytes(key, ctx->key_len) <= 0)
|
||||
if (RAND_priv_bytes(key, EVP_CIPHER_CTX_key_length(ctx)) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -647,6 +962,36 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
|
||||
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in->cipher->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (in->cipher->dupctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_reset(out);
|
||||
|
||||
*out = *in;
|
||||
out->provctx = NULL;
|
||||
|
||||
if (in->fetched_cipher != NULL && !EVP_CIPHER_upref(in->fetched_cipher)) {
|
||||
out->fetched_cipher = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
out->provctx = in->cipher->dupctx(in->provctx);
|
||||
if (out->provctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
/* Make sure it's safe to copy a cipher context using an ENGINE */
|
||||
if (in->engine && !ENGINE_init(in->engine)) {
|
||||
@@ -676,3 +1021,141 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
|
||||
OSSL_PROVIDER *prov)
|
||||
{
|
||||
EVP_CIPHER *cipher = NULL;
|
||||
int fnciphcnt = 0, fnctxcnt = 0;
|
||||
|
||||
if ((cipher = EVP_CIPHER_meth_new(nid, 0, 0)) == NULL)
|
||||
return NULL;
|
||||
|
||||
for (; fns->function_id != 0; fns++) {
|
||||
switch (fns->function_id) {
|
||||
case OSSL_FUNC_CIPHER_NEWCTX:
|
||||
if (cipher->newctx != NULL)
|
||||
break;
|
||||
cipher->newctx = OSSL_get_OP_cipher_newctx(fns);
|
||||
fnctxcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_ENCRYPT_INIT:
|
||||
if (cipher->einit != NULL)
|
||||
break;
|
||||
cipher->einit = OSSL_get_OP_cipher_encrypt_init(fns);
|
||||
fnciphcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_DECRYPT_INIT:
|
||||
if (cipher->dinit != NULL)
|
||||
break;
|
||||
cipher->dinit = OSSL_get_OP_cipher_decrypt_init(fns);
|
||||
fnciphcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_UPDATE:
|
||||
if (cipher->cupdate != NULL)
|
||||
break;
|
||||
cipher->cupdate = OSSL_get_OP_cipher_update(fns);
|
||||
fnciphcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_FINAL:
|
||||
if (cipher->cfinal != NULL)
|
||||
break;
|
||||
cipher->cfinal = OSSL_get_OP_cipher_final(fns);
|
||||
fnciphcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_CIPHER:
|
||||
if (cipher->ccipher != NULL)
|
||||
break;
|
||||
cipher->ccipher = OSSL_get_OP_cipher_cipher(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_FREECTX:
|
||||
if (cipher->freectx != NULL)
|
||||
break;
|
||||
cipher->freectx = OSSL_get_OP_cipher_freectx(fns);
|
||||
fnctxcnt++;
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_DUPCTX:
|
||||
if (cipher->dupctx != NULL)
|
||||
break;
|
||||
cipher->dupctx = OSSL_get_OP_cipher_dupctx(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_KEY_LENGTH:
|
||||
if (cipher->key_length != NULL)
|
||||
break;
|
||||
cipher->key_length = OSSL_get_OP_cipher_key_length(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_IV_LENGTH:
|
||||
if (cipher->iv_length != NULL)
|
||||
break;
|
||||
cipher->iv_length = OSSL_get_OP_cipher_iv_length(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_BLOCK_SIZE:
|
||||
if (cipher->blocksize != NULL)
|
||||
break;
|
||||
cipher->blocksize = OSSL_get_OP_cipher_block_size(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_GET_PARAMS:
|
||||
if (cipher->get_params != NULL)
|
||||
break;
|
||||
cipher->get_params = OSSL_get_OP_cipher_get_params(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_CTX_GET_PARAMS:
|
||||
if (cipher->ctx_get_params != NULL)
|
||||
break;
|
||||
cipher->ctx_get_params = OSSL_get_OP_cipher_ctx_get_params(fns);
|
||||
break;
|
||||
case OSSL_FUNC_CIPHER_CTX_SET_PARAMS:
|
||||
if (cipher->ctx_set_params != NULL)
|
||||
break;
|
||||
cipher->ctx_set_params = OSSL_get_OP_cipher_ctx_set_params(fns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
|
||||
|| (fnciphcnt == 0 && cipher->ccipher == NULL)
|
||||
|| fnctxcnt != 2
|
||||
|| cipher->blocksize == NULL
|
||||
|| cipher->iv_length == NULL
|
||||
|| cipher->key_length == NULL) {
|
||||
/*
|
||||
* In order to be a consistent set of functions we must have at least
|
||||
* a complete set of "encrypt" functions, or a complete set of "decrypt"
|
||||
* functions, or a single "cipher" function. In all cases we need a
|
||||
* complete set of context management functions, as well as the
|
||||
* blocksize, iv_length and key_length functions.
|
||||
*/
|
||||
EVP_CIPHER_meth_free(cipher);
|
||||
EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);
|
||||
return NULL;
|
||||
}
|
||||
cipher->prov = prov;
|
||||
if (prov != NULL)
|
||||
ossl_provider_upref(prov);
|
||||
|
||||
return cipher;
|
||||
}
|
||||
|
||||
static int evp_cipher_upref(void *cipher)
|
||||
{
|
||||
return EVP_CIPHER_upref(cipher);
|
||||
}
|
||||
|
||||
static void evp_cipher_free(void *cipher)
|
||||
{
|
||||
EVP_CIPHER_meth_free(cipher);
|
||||
}
|
||||
|
||||
static int evp_cipher_nid(void *vcipher)
|
||||
{
|
||||
EVP_CIPHER *cipher = vcipher;
|
||||
|
||||
return cipher->nid;
|
||||
}
|
||||
|
||||
EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
||||
const char *properties)
|
||||
{
|
||||
return evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
|
||||
evp_cipher_from_dispatch, evp_cipher_upref,
|
||||
evp_cipher_free, evp_cipher_nid);
|
||||
}
|
||||
@@ -53,6 +53,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
"EVP_CIPHER_CTX_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, 0),
|
||||
"EVP_CIPHER_CTX_set_key_length"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_PADDING, 0),
|
||||
"EVP_CIPHER_CTX_set_padding"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_FROM_DISPATCH, 0),
|
||||
"evp_cipher_from_dispatch"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_MODE, 0), "EVP_CIPHER_mode"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_PARAM_TO_ASN1, 0),
|
||||
"EVP_CIPHER_param_to_asn1"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, 0),
|
||||
@@ -246,6 +251,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PROVIDER_FUNCTIONS),
|
||||
"invalid provider functions"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH),
|
||||
"invalid salt length"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"},
|
||||
|
||||
@@ -173,11 +173,15 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
|
||||
void (*free_method)(void *),
|
||||
int (*nid_method)(void *))
|
||||
{
|
||||
OSSL_METHOD_STORE *store = get_default_method_store(libctx);
|
||||
int nid = OBJ_sn2nid(algorithm);
|
||||
void *method = NULL;
|
||||
|
||||
if (store == NULL)
|
||||
return NULL;
|
||||
|
||||
if (nid == NID_undef
|
||||
|| !ossl_method_store_cache_get(NULL, nid, properties, &method)) {
|
||||
|| !ossl_method_store_cache_get(store, nid, properties, &method)) {
|
||||
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
|
||||
alloc_tmp_method_store,
|
||||
dealloc_tmp_method_store,
|
||||
@@ -198,7 +202,9 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
|
||||
method = ossl_method_construct(libctx, operation_id, algorithm,
|
||||
properties, 0 /* !force_cache */,
|
||||
&mcm, &mcmdata);
|
||||
ossl_method_store_cache_set(NULL, nid, properties, method);
|
||||
ossl_method_store_cache_set(store, nid, properties, method);
|
||||
} else {
|
||||
upref_method(method);
|
||||
}
|
||||
|
||||
return method;
|
||||
|
||||
+113
-20
@@ -11,6 +11,8 @@
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider.h"
|
||||
#include "evp_locl.h"
|
||||
@@ -18,13 +20,28 @@
|
||||
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
{
|
||||
int ret;
|
||||
const EVP_CIPHER *cipher = c->cipher;
|
||||
|
||||
if (c->cipher->set_asn1_parameters != NULL)
|
||||
ret = c->cipher->set_asn1_parameters(c, type);
|
||||
else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
|
||||
switch (EVP_CIPHER_CTX_mode(c)) {
|
||||
if (cipher->prov != NULL) {
|
||||
/*
|
||||
* The cipher has come from a provider and won't have the default flags.
|
||||
* Find the implicit form so we can check the flags.
|
||||
* TODO(3.0): This won't work for 3rd party ciphers we know nothing about
|
||||
* We'll need to think of something else for those.
|
||||
*/
|
||||
cipher = EVP_get_cipherbynid(cipher->nid);
|
||||
if (cipher == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ASN1_R_UNSUPPORTED_CIPHER);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cipher->set_asn1_parameters != NULL)
|
||||
ret = cipher->set_asn1_parameters(c, type);
|
||||
else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
|
||||
switch (EVP_CIPHER_mode(cipher)) {
|
||||
case EVP_CIPH_WRAP_MODE:
|
||||
if (EVP_CIPHER_CTX_nid(c) == NID_id_smime_alg_CMS3DESwrap)
|
||||
if (EVP_CIPHER_nid(cipher) == NID_id_smime_alg_CMS3DESwrap)
|
||||
ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
|
||||
ret = 1;
|
||||
break;
|
||||
@@ -53,11 +70,22 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
{
|
||||
int ret;
|
||||
const EVP_CIPHER *cipher = c->cipher;
|
||||
|
||||
if (c->cipher->get_asn1_parameters != NULL)
|
||||
ret = c->cipher->get_asn1_parameters(c, type);
|
||||
else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
|
||||
switch (EVP_CIPHER_CTX_mode(c)) {
|
||||
if (cipher->prov != NULL) {
|
||||
/*
|
||||
* The cipher has come from a provider and won't have the default flags.
|
||||
* Find the implicit form so we can check the flags.
|
||||
*/
|
||||
cipher = EVP_get_cipherbynid(cipher->nid);
|
||||
if (cipher == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cipher->get_asn1_parameters != NULL)
|
||||
ret = cipher->get_asn1_parameters(c, type);
|
||||
else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
|
||||
switch (EVP_CIPHER_mode(cipher)) {
|
||||
|
||||
case EVP_CIPH_WRAP_MODE:
|
||||
ret = 1;
|
||||
@@ -85,19 +113,23 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int l;
|
||||
|
||||
if (type != NULL) {
|
||||
l = EVP_CIPHER_CTX_iv_length(c);
|
||||
OPENSSL_assert(l <= sizeof(c->iv));
|
||||
i = ASN1_TYPE_get_octetstring(type, c->oiv, l);
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
|
||||
l = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
if (!ossl_assert(l <= sizeof(iv)))
|
||||
return -1;
|
||||
i = ASN1_TYPE_get_octetstring(type, iv, l);
|
||||
if (i != (int)l)
|
||||
return -1;
|
||||
else if (i > 0)
|
||||
memcpy(c->iv, c->oiv, l);
|
||||
|
||||
if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1))
|
||||
return -1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -175,14 +207,20 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
int EVP_CIPHER_block_size(const EVP_CIPHER *e)
|
||||
int EVP_CIPHER_block_size(const EVP_CIPHER *cipher)
|
||||
{
|
||||
return e->block_size;
|
||||
if (cipher->prov != NULL) {
|
||||
if (cipher->blocksize != NULL)
|
||||
return cipher->blocksize();
|
||||
/* We default to a block size of 1 */
|
||||
return 1;
|
||||
}
|
||||
return cipher->block_size;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
return ctx->cipher->block_size;
|
||||
return EVP_CIPHER_block_size(ctx->cipher);
|
||||
}
|
||||
|
||||
int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
|
||||
@@ -193,6 +231,12 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
|
||||
int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, unsigned int inl)
|
||||
{
|
||||
if (ctx->cipher->prov != NULL) {
|
||||
if (ctx->cipher->ccipher != NULL)
|
||||
return ctx->cipher->ccipher(ctx->provctx, out, in, (size_t)inl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->cipher->do_cipher(ctx, out, in, inl);
|
||||
}
|
||||
|
||||
@@ -238,12 +282,18 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
|
||||
|
||||
int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
|
||||
{
|
||||
if (cipher->prov != NULL) {
|
||||
if (cipher->iv_length != NULL)
|
||||
return (int)cipher->iv_length();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cipher->iv_len;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
return ctx->cipher->iv_len;
|
||||
return EVP_CIPHER_iv_length(ctx->cipher);
|
||||
}
|
||||
|
||||
const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx)
|
||||
@@ -278,11 +328,23 @@ void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
|
||||
|
||||
int EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
|
||||
{
|
||||
if (cipher->prov != NULL) {
|
||||
if (cipher->key_length != NULL)
|
||||
return (int)cipher->key_length();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cipher->key_len;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
/*
|
||||
* TODO(3.0): This may need to change if/when we introduce variable length
|
||||
* key ciphers into the providers.
|
||||
*/
|
||||
if (ctx->cipher != NULL && ctx->cipher->prov != NULL)
|
||||
return EVP_CIPHER_key_length(ctx->cipher);
|
||||
return ctx->key_len;
|
||||
}
|
||||
|
||||
@@ -296,6 +358,33 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
|
||||
return ctx->cipher->nid;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
|
||||
{
|
||||
if (cipher->prov != NULL) {
|
||||
int mode;
|
||||
|
||||
/* Cipher comes from a provider - so ask the provider for the mode */
|
||||
OSSL_PARAM params[] = {
|
||||
OSSL_PARAM_int(OSSL_CIPHER_PARAM_MODE, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
params[0].data = &mode;
|
||||
|
||||
if (cipher->get_params == NULL) {
|
||||
EVPerr(EVP_F_EVP_CIPHER_MODE, EVP_R_CTRL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cipher->get_params(params))
|
||||
return 0;
|
||||
|
||||
return mode;
|
||||
}
|
||||
return EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE;
|
||||
}
|
||||
|
||||
|
||||
int EVP_MD_block_size(const EVP_MD *md)
|
||||
{
|
||||
if (md == NULL) {
|
||||
@@ -353,12 +442,16 @@ EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
|
||||
{
|
||||
EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type);
|
||||
|
||||
if (to != NULL)
|
||||
if (to != NULL) {
|
||||
CRYPTO_RWLOCK *lock = to->lock;
|
||||
memcpy(to, md, sizeof(*to));
|
||||
to->lock = lock;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ struct evp_cipher_ctx_st {
|
||||
int final_used;
|
||||
int block_mask;
|
||||
unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
|
||||
|
||||
/* Provider ctx */
|
||||
void *provctx;
|
||||
EVP_CIPHER *fetched_cipher;
|
||||
} /* EVP_CIPHER_CTX */ ;
|
||||
|
||||
struct evp_mac_ctx_st {
|
||||
|
||||
@@ -210,10 +210,14 @@ struct evp_md_st {
|
||||
|
||||
struct evp_cipher_st {
|
||||
int nid;
|
||||
|
||||
int block_size;
|
||||
/* Default value for variable length ciphers */
|
||||
int key_len;
|
||||
int iv_len;
|
||||
|
||||
/* Legacy structure members */
|
||||
/* TODO(3.0): Remove these */
|
||||
/* Various flags */
|
||||
unsigned long flags;
|
||||
/* init key */
|
||||
@@ -234,6 +238,26 @@ struct evp_cipher_st {
|
||||
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);
|
||||
/* Application data */
|
||||
void *app_data;
|
||||
|
||||
/* 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_cipher_newctx_fn *newctx;
|
||||
OSSL_OP_cipher_encrypt_init_fn *einit;
|
||||
OSSL_OP_cipher_decrypt_init_fn *dinit;
|
||||
OSSL_OP_cipher_update_fn *cupdate;
|
||||
OSSL_OP_cipher_final_fn *cfinal;
|
||||
OSSL_OP_cipher_cipher_fn *ccipher;
|
||||
OSSL_OP_cipher_freectx_fn *freectx;
|
||||
OSSL_OP_cipher_dupctx_fn *dupctx;
|
||||
OSSL_OP_cipher_key_length_fn *key_length;
|
||||
OSSL_OP_cipher_iv_length_fn *iv_length;
|
||||
OSSL_OP_cipher_block_size_fn *blocksize;
|
||||
OSSL_OP_cipher_get_params_fn *get_params;
|
||||
OSSL_OP_cipher_ctx_get_params_fn *ctx_get_params;
|
||||
OSSL_OP_cipher_ctx_set_params_fn *ctx_set_params;
|
||||
} /* EVP_CIPHER */ ;
|
||||
|
||||
/* Macros to code block cipher wrappers */
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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/crypto.h>
|
||||
#include "internal/dso_conf.h"
|
||||
#include "e_os.h"
|
||||
|
||||
const char *OPENSSL_info(int t)
|
||||
{
|
||||
switch (t) {
|
||||
case OPENSSL_INFO_CONFIG_DIR:
|
||||
return OPENSSLDIR;
|
||||
case OPENSSL_INFO_ENGINES_DIR:
|
||||
return ENGINESDIR;
|
||||
case OPENSSL_INFO_MODULES_DIR:
|
||||
return MODULESDIR;
|
||||
case OPENSSL_INFO_DSO_EXTENSION:
|
||||
return DSO_EXTENSION;
|
||||
case OPENSSL_INFO_DIR_FILENAME_SEPARATOR:
|
||||
#if defined(_WIN32)
|
||||
return "\\";
|
||||
#elif defined(__VMS)
|
||||
return "";
|
||||
#else /* Assume POSIX */
|
||||
return "/";
|
||||
#endif
|
||||
case OPENSSL_INFO_LIST_SEPARATOR:
|
||||
{
|
||||
static const char list_sep[] = { LIST_SEPARATOR_CHAR, '\0' };
|
||||
return list_sep;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Not an error */
|
||||
return NULL;
|
||||
}
|
||||
@@ -98,6 +98,7 @@ void OPENSSL_LH_flush(OPENSSL_LHASH *lh)
|
||||
OPENSSL_free(n);
|
||||
n = nn;
|
||||
}
|
||||
lh->b[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
# Denver 0.51 0.65 6.02
|
||||
# Mongoose 0.65 1.10 8.06
|
||||
# Kryo 0.76 1.16 8.00
|
||||
# ThunderX2 1.05
|
||||
#
|
||||
# (*) presented for reference/comparison purposes;
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
|
||||
|
||||
M *= 2;
|
||||
M += 2;
|
||||
if (len < M)
|
||||
if (len != M)
|
||||
return 0;
|
||||
memcpy(tag, ctx->cmac.c, M);
|
||||
return M;
|
||||
|
||||
+88
-6
@@ -6,23 +6,37 @@
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
# Copyright IBM Corp. 2018
|
||||
# Copyright IBM Corp. 2018-2019
|
||||
# Author: Patrick Steuer <patrick.steuer@de.ibm.com>
|
||||
|
||||
package perlasm::s390x;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bigint;
|
||||
use Carp qw(confess);
|
||||
use Exporter qw(import);
|
||||
|
||||
our @EXPORT=qw(PERLASM_BEGIN PERLASM_END);
|
||||
our @EXPORT_OK=qw(AUTOLOAD LABEL INCLUDE stfle);
|
||||
our %EXPORT_TAGS=(
|
||||
# long-displacement facility
|
||||
LD => [qw(clgfi)],
|
||||
# general-instruction-extension facility
|
||||
GE => [qw(risbg)],
|
||||
# extended-immediate facility
|
||||
EI => [qw(lt)],
|
||||
# miscellaneous-instruction-extensions facility 1
|
||||
MI1 => [qw(risbgn)],
|
||||
# message-security assist
|
||||
MSA => [qw(kmac km kmc kimd klmd)],
|
||||
# message-security-assist extension 4
|
||||
MSA4 => [qw(kmf kmo pcc kmctr)],
|
||||
# message-security-assist extension 5
|
||||
MSA5 => [qw(ppno prno)],
|
||||
# message-security-assist extension 8
|
||||
MSA8 => [qw(kma)],
|
||||
# vector facility
|
||||
VX => [qw(vgef vgeg vgbm vzero vone vgm vgmb vgmh vgmf vgmg
|
||||
vl vlr vlrep vlrepb vlreph vlrepf vlrepg vleb vleh vlef vleg vleib
|
||||
vleih vleif vleig vlgv vlgvb vlgvh vlgvf vlgvg vllez vllezb vllezh
|
||||
@@ -71,6 +85,7 @@ our %EXPORT_TAGS=(
|
||||
wfmadb vfms vfmsdb wfmsdb vfpso vfpsodb wfpsodb vflcdb wflcdb
|
||||
vflndb wflndb vflpdb wflpdb vfsq vfsqdb wfsqdb vfs vfsdb wfsdb
|
||||
vftci vftcidb wftcidb)],
|
||||
# vector-enhancements facility 1
|
||||
VXE => [qw(vbperm vllezlf vmsl vmslg vnx vnn voc vpopctb vpopcth
|
||||
vpopctf vpopctg vfasb wfasb wfaxb wfcsb wfcxb wfksb wfkxb vfcesb
|
||||
vfcesbs wfcesb wfcesbs wfcexb wfcexbs vfchsb vfchsbs wfchsb wfchsbs
|
||||
@@ -83,10 +98,11 @@ our %EXPORT_TAGS=(
|
||||
wfnmsxb vfpsosb wfpsosb vflcsb wflcsb vflnsb wflnsb vflpsb wflpsb
|
||||
vfpsoxb wfpsoxb vflcxb wflcxb vflnxb wflnxb vflpxb wflpxb vfsqsb
|
||||
wfsqsb wfsqxb vfssb wfssb wfsxb vftcisb wftcisb wftcixb)],
|
||||
# vector-packed-decimal facility
|
||||
VXD => [qw(vlrlr vlrl vstrlr vstrl vap vcp vcvb vcvbg vcvd vcvdg vdp
|
||||
vlip vmp vmsp vpkz vpsop vrp vsdp vsrp vsp vtp vupkz)],
|
||||
);
|
||||
Exporter::export_ok_tags(qw(MSA MSA4 MSA5 MSA8 VX VXE VXD));
|
||||
Exporter::export_ok_tags(qw(LD GE EI MI1 MSA MSA4 MSA5 MSA8 VX VXE VXD));
|
||||
|
||||
our $AUTOLOAD;
|
||||
|
||||
@@ -143,6 +159,28 @@ sub stfle {
|
||||
S(0xb2b0,@_);
|
||||
}
|
||||
|
||||
# MISC
|
||||
|
||||
sub clgfi {
|
||||
confess(err("ARGNUM")) if ($#_!=1);
|
||||
RILa(0xc2e,@_);
|
||||
}
|
||||
|
||||
sub lt {
|
||||
confess(err("ARGNUM")) if ($#_!=1);
|
||||
RXYa(0xe312,@_);
|
||||
}
|
||||
|
||||
sub risbg {
|
||||
confess(err("ARGNUM")) if ($#_<3||$#_>4);
|
||||
RIEf(0xec55,@_);
|
||||
}
|
||||
|
||||
sub risbgn {
|
||||
confess(err("ARGNUM")) if ($#_<3||$#_>4);
|
||||
RIEf(0xec59,@_);
|
||||
}
|
||||
|
||||
# MSA
|
||||
|
||||
sub kmac {
|
||||
@@ -250,7 +288,7 @@ sub vgmg {
|
||||
}
|
||||
|
||||
sub vl {
|
||||
confess(err("ARGNUM")) if ($#_!=1);
|
||||
confess(err("ARGNUM")) if ($#_<1||$#_>2);
|
||||
VRX(0xe706,@_);
|
||||
}
|
||||
|
||||
@@ -345,7 +383,7 @@ sub vllezg {
|
||||
}
|
||||
|
||||
sub vlm {
|
||||
confess(err("ARGNUM")) if ($#_!=2);
|
||||
confess(err("ARGNUM")) if ($#_<2||$#_>3);
|
||||
VRSa(0xe736,@_);
|
||||
}
|
||||
|
||||
@@ -548,7 +586,7 @@ sub vsegf {
|
||||
}
|
||||
|
||||
sub vst {
|
||||
confess(err("ARGNUM")) if ($#_!=1);
|
||||
confess(err("ARGNUM")) if ($#_<1||$#_>2);
|
||||
VRX(0xe70e,@_);
|
||||
}
|
||||
|
||||
@@ -570,7 +608,7 @@ sub vsteg {
|
||||
}
|
||||
|
||||
sub vstm {
|
||||
confess(err("ARGNUM")) if ($#_!=2);
|
||||
confess(err("ARGNUM")) if ($#_<2||$#_>3);
|
||||
VRSa(0xe73e,@_);
|
||||
}
|
||||
|
||||
@@ -2486,6 +2524,36 @@ sub vupkz {
|
||||
# Instruction Formats
|
||||
#
|
||||
|
||||
sub RIEf {
|
||||
confess(err("ARGNUM")) if ($#_<4||5<$#_);
|
||||
my $ops=join(',',@_[1..$#_]);
|
||||
my $memn=(caller(1))[3];
|
||||
$memn=~s/^.*:://;
|
||||
my ($opcode,$r1,$r2,$i3,$i4,$i5)=(shift,get_R(shift),get_R(shift),
|
||||
get_I(shift,8),get_I(shift,8),
|
||||
get_I(shift,8));
|
||||
|
||||
$out.="\t.word\t";
|
||||
$out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$r2)).",";
|
||||
$out.=sprintf("%#06x",($i3<<8)|$i4).",";
|
||||
$out.=sprintf("%#06x",($i5<<8)|($opcode&0xff));
|
||||
$out.="\t# $memn\t$ops\n"
|
||||
}
|
||||
|
||||
sub RILa {
|
||||
confess(err("ARGNUM")) if ($#_!=2);
|
||||
my $ops=join(',',@_[1..$#_]);
|
||||
my $memn=(caller(1))[3];
|
||||
$memn=~s/^.*:://;
|
||||
my ($opcode,$r1,$i2)=(shift,get_R(shift),get_I(shift,32));
|
||||
|
||||
$out.="\t.word\t";
|
||||
$out.=sprintf("%#06x",(($opcode>>4)<<8|$r1<<4|($opcode&0xf))).",";
|
||||
$out.=sprintf("%#06x",($i2>>16)).",";
|
||||
$out.=sprintf("%#06x",($i2&0xffff));
|
||||
$out.="\t# $memn\t$ops\n"
|
||||
}
|
||||
|
||||
sub RRE {
|
||||
confess(err("ARGNUM")) if ($#_<0||2<$#_);
|
||||
my $ops=join(',',@_[1..$#_]);
|
||||
@@ -2510,6 +2578,20 @@ sub RRFb {
|
||||
$out.="\t# $memn\t$ops\n"
|
||||
}
|
||||
|
||||
sub RXYa {
|
||||
confess(err("ARGNUM")) if ($#_!=2);
|
||||
my $ops=join(',',@_[1..$#_]);
|
||||
my $memn=(caller(1))[3];
|
||||
$memn=~s/^.*:://;
|
||||
my ($opcode,$r1,$d2,$x2,$b2)=(shift,get_R(shift),get_DXB(shift));
|
||||
|
||||
$out.="\t.word\t";
|
||||
$out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$x2)).",";
|
||||
$out.=sprintf("%#06x",($b2<<12|($d2&0xfff))).",";
|
||||
$out.=sprintf("%#06x",(($d2>>12)<<8|$opcode&0xff));
|
||||
$out.="\t# $memn\t$ops\n"
|
||||
}
|
||||
|
||||
sub S {
|
||||
confess(err("ARGNUM")) if ($#_<0||1<$#_);
|
||||
my $ops=join(',',@_[1..$#_]);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
# X-Gene 2.13/+68% 2.27
|
||||
# Mongoose 1.77/+75% 1.12
|
||||
# Kryo 2.70/+55% 1.13
|
||||
# ThunderX2 1.17/+95% 1.36
|
||||
#
|
||||
# (*) estimate based on resources availability is less than 1.0,
|
||||
# i.e. measured result is worse than expected, presumably binary
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
use strict;
|
||||
use FindBin qw($Bin);
|
||||
use lib "$Bin/../..";
|
||||
use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE);
|
||||
use perlasm::s390x qw(:DEFAULT :LD :GE :EI :MI1 :VX AUTOLOAD LABEL INCLUDE);
|
||||
|
||||
my $flavour = shift;
|
||||
|
||||
|
||||
@@ -450,7 +450,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
elem.query = prop_query;
|
||||
elem.query = prop_query != NULL ? prop_query : "";
|
||||
r = lh_QUERY_retrieve(alg->cache, &elem);
|
||||
if (r == NULL) {
|
||||
ossl_property_unlock(store);
|
||||
|
||||
@@ -30,7 +30,7 @@ int rand_crngt_get_entropy_cb(unsigned char *buf)
|
||||
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);
|
||||
memcpy(buf, p, CRNGT_BUFSIZ);
|
||||
rand_pool_reattach(crngt_pool, p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,13 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
|
||||
param, plen, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform ihe padding as per NIST 800-56B 7.2.2.3
|
||||
* from (K) is the key material.
|
||||
* param (A) is the additional input.
|
||||
* Step numbers are included here but not in the constant time inverse below
|
||||
* to avoid complicating an already difficult enough function.
|
||||
*/
|
||||
int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
const unsigned char *param, int plen,
|
||||
@@ -57,6 +64,7 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
|
||||
/* step 2b: check KLen > nLen - 2 HLen - 2 */
|
||||
if (flen > emlen - 2 * mdlen - 1) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
@@ -69,15 +77,20 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* step 3i: EM = 00000000 || maskedMGF || maskedDB */
|
||||
to[0] = 0;
|
||||
seed = to + 1;
|
||||
db = to + mdlen + 1;
|
||||
|
||||
/* step 3a: hash the additional input */
|
||||
if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
|
||||
goto err;
|
||||
/* step 3b: zero bytes array of length nLen - KLen - 2 HLen -2 */
|
||||
memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
|
||||
/* step 3c: DB = HA || PS || 00000001 || K */
|
||||
db[emlen - flen - mdlen - 1] = 0x01;
|
||||
memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
|
||||
/* step 3d: generate random byte string */
|
||||
if (RAND_bytes(seed, mdlen) <= 0)
|
||||
goto err;
|
||||
|
||||
@@ -88,13 +101,17 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 3e: dbMask = MGF(mgfSeed, nLen - HLen - 1) */
|
||||
if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0)
|
||||
goto err;
|
||||
/* step 3f: maskedDB = DB XOR dbMask */
|
||||
for (i = 0; i < dbmask_len; i++)
|
||||
db[i] ^= dbmask[i];
|
||||
|
||||
/* step 3g: mgfSeed = MGF(maskedDB, HLen) */
|
||||
if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0)
|
||||
goto err;
|
||||
/* stepo 3h: maskedMGFSeed = mgfSeed XOR mgfSeedMask */
|
||||
for (i = 0; i < mdlen; i++)
|
||||
seed[i] ^= seedmask[i];
|
||||
rv = 1;
|
||||
@@ -270,6 +287,13 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
return constant_time_select_int(good, mlen, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask Generation Function corresponding to section 7.2.2.2 of NIST SP 800-56B.
|
||||
* The variables are named differently to NIST:
|
||||
* mask (T) and len (maskLen)are the returned mask.
|
||||
* seed (mgfSeed).
|
||||
* The range checking steps inm the process are performed outside.
|
||||
*/
|
||||
int PKCS1_MGF1(unsigned char *mask, long len,
|
||||
const unsigned char *seed, long seedlen, const EVP_MD *dgst)
|
||||
{
|
||||
@@ -285,11 +309,14 @@ int PKCS1_MGF1(unsigned char *mask, long len,
|
||||
mdlen = EVP_MD_size(dgst);
|
||||
if (mdlen < 0)
|
||||
goto err;
|
||||
/* step 4 */
|
||||
for (i = 0; outlen < len; i++) {
|
||||
/* step 4a: D = I2BS(counter, 4) */
|
||||
cnt[0] = (unsigned char)((i >> 24) & 255);
|
||||
cnt[1] = (unsigned char)((i >> 16) & 255);
|
||||
cnt[2] = (unsigned char)((i >> 8)) & 255;
|
||||
cnt[3] = (unsigned char)(i & 255);
|
||||
/* step 4b: T =T || hash(mgfSeed || D) */
|
||||
if (!EVP_DigestInit_ex(c, dgst, NULL)
|
||||
|| !EVP_DigestUpdate(c, seed, seedlen)
|
||||
|| !EVP_DigestUpdate(c, cnt, 4))
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
# Kryo 12
|
||||
# Denver 7.8
|
||||
# Apple A7 7.2
|
||||
# ThunderX2 9.7
|
||||
#
|
||||
# (*) Corresponds to SHA3-256. No improvement coefficients are listed
|
||||
# because they vary too much from compiler to compiler. Newer
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# X-Gene 8.80 (+200%)
|
||||
# Mongoose 2.05 6.50 (+160%)
|
||||
# Kryo 1.88 8.00 (+90%)
|
||||
# ThunderX2 2.64 6.36 (+150%)
|
||||
#
|
||||
# (*) Software results are presented mostly for reference purposes.
|
||||
# (**) Keep in mind that Denver relies on binary translation, which
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
# X-Gene 20.0 (+100%) 12.8 (+300%(***))
|
||||
# Mongoose 2.36 13.0 (+50%) 8.36 (+33%)
|
||||
# Kryo 1.92 17.4 (+30%) 11.2 (+8%)
|
||||
# ThunderX2 2.54 13.2 (+40%) 8.40 (+18%)
|
||||
#
|
||||
# (*) Software SHA256 results are of lesser relevance, presented
|
||||
# mostly for informational purposes.
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
openssl-info,
|
||||
info - print OpenSSL built-in information
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<openssl info>
|
||||
[B<-help>]
|
||||
[B<-configdir> | B<-c>]
|
||||
[B<-enginesdir> | B<-e>]
|
||||
[B<-modulesdir> | B<-m>]
|
||||
[B<-dsoext>]
|
||||
[B<-dirfilesep>]
|
||||
[B<-listsep]>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This command is used to print out information about OpenSSL.
|
||||
The information is written exactly as it is with no extra text, which
|
||||
makes useful for scripts.
|
||||
|
||||
As a consequence, only one item may be chosen for each run of this
|
||||
command.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print out a usage message.
|
||||
|
||||
=item B<-configdir>, B<-c>
|
||||
|
||||
Outputs the default directory for OpenSSL configuration files.
|
||||
|
||||
=item B<-enginesdir>, B<-e>
|
||||
|
||||
Outputs the default directory for OpenSSL engine modules.
|
||||
|
||||
=item B<-modulesdir>, B<-m>
|
||||
|
||||
Outputs the default directory for OpenSSL dynamically loadable modules
|
||||
other than engine modules.
|
||||
|
||||
=item B<-dsoext>
|
||||
|
||||
Outputs the DSO extension OpenSSL uses.
|
||||
|
||||
=item B<-dirnamesep>
|
||||
|
||||
Outputs the separator character between a directory specification and
|
||||
a file name.
|
||||
Note that on some operating systems, this is not the same as the
|
||||
separator between directory elements.
|
||||
|
||||
=item B<-listsep>
|
||||
|
||||
Outputs the OpenSSL list separator character.
|
||||
This is typically used to construct C<$PATH> (C<%PATH%> on Windows)
|
||||
style lists.
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
The B<openssl info> command was added in OpenSSL 3.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
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
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
||||
@@ -0,0 +1,167 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
openssl-kdf,
|
||||
kdf - perform Key Derivation Function operations
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<openssl kdf>
|
||||
[B<-help>]
|
||||
[B<-kdfopt> I<nm:v>]
|
||||
[B<-keylen> I<num>]
|
||||
[B<-out> I<filename>]
|
||||
[B<-binary>]
|
||||
I<kdf_name>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The key derivation functions generate a derived key from either a secret or
|
||||
password.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print a usage message.
|
||||
|
||||
=item B<-keylen> I<num>
|
||||
|
||||
The output size of the derived key. This field is required.
|
||||
|
||||
=item B<-out> I<filename>
|
||||
|
||||
Filename to output to, or standard output by default.
|
||||
|
||||
=item B<-binary>
|
||||
|
||||
Output the derived key in binary form. Uses hexadecimal text format if not specified.
|
||||
|
||||
=item B<-kdfopt> I<nm:v>
|
||||
|
||||
Passes options to the KDF algorithm.
|
||||
A comprehensive list of controls can be found in the EVP_KDF_CTX implementation
|
||||
documentation.
|
||||
Common control strings used by EVP_KDF_ctrl_str() are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<key:>I<string>
|
||||
|
||||
Specifies the secret key as an alphanumeric string (use if the key contains
|
||||
printable characters only).
|
||||
The string length must conform to any restrictions of the KDF algorithm.
|
||||
A key must be specified for most KDF algorithms.
|
||||
|
||||
=item B<hexkey:>I<string>
|
||||
|
||||
Specifies the secret key in hexadecimal form (two hex digits per byte).
|
||||
The key length must conform to any restrictions of the KDF algorithm.
|
||||
A key must be specified for most KDF algorithms.
|
||||
|
||||
=item B<pass:>I<string>
|
||||
|
||||
Specifies the password as an alphanumeric string (use if the password contains
|
||||
printable characters only).
|
||||
The password must be specified for PBKDF2 and scrypt.
|
||||
|
||||
=item B<hexpass:>I<string>
|
||||
|
||||
Specifies the password in hexadecimal form (two hex digits per byte).
|
||||
The password must be specified for PBKDF2 and scrypt.
|
||||
|
||||
=item B<digest:>I<string>
|
||||
|
||||
Specifies the name of a digest as an alphanumeric string.
|
||||
To see the list of supported digests, use the command I<list -digest-commands>.
|
||||
|
||||
=back
|
||||
|
||||
=item I<kdf_name>
|
||||
|
||||
Specifies the name of a supported KDF algorithm which will be used.
|
||||
The supported algorithms names are TLS1-PRF, HKDF, SSKDF, PBKDF2, SSHKDF and id-scrypt.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Use TLS1-PRF to create a hex-encoded derived key from a secret key and seed:
|
||||
|
||||
openssl kdf -keylen 16 -kdfopt digest:SHA256 -kdfopt key:secret \
|
||||
-kdfopt seed:seed TLS1-PRF
|
||||
|
||||
Use HKDF to create a hex-encoded derived key from a secret key, salt and info:
|
||||
|
||||
openssl kdf -keylen 10 -kdfopt digest:SHA256 -kdfopt key:secret \
|
||||
-kdfopt salt:salt -kdfopt info:label HKDF
|
||||
|
||||
Use SSKDF with KMAC to create a hex-encoded derived key from a secret key, salt and info:
|
||||
|
||||
openssl kdf -keylen 64 -kdfopt mac:KMAC128 -kdfopt maclen:20 \
|
||||
-kdfopt hexkey:b74a149a161545 -kdfopt hexinfo:348a37a2 \
|
||||
-kdfopt hexsalt:3638271ccd68a2 SSKDF
|
||||
|
||||
Use SSKDF with HMAC to create a hex-encoded derived key from a secret key, salt and info:
|
||||
|
||||
openssl kdf -keylen 16 -kdfopt mac:HMAC -kdfopt digest:SHA256 \
|
||||
-kdfopt hexkey:b74a149a -kdfopt hexinfo:348a37a2 \
|
||||
-kdfopt hexsalt:3638271c SSKDF
|
||||
|
||||
Use SSKDF with Hash to create a hex-encoded derived key from a secret key, salt and info:
|
||||
|
||||
openssl kdf -keylen 14 -kdfopt digest:SHA256 \
|
||||
-kdfopt hexkey:6dbdc23f045488 \
|
||||
-kdfopt hexinfo:a1b2c3d4 SSKDF
|
||||
|
||||
Use SSHKDF to create a hex-encoded derived key from a secret key, hash and session_id:
|
||||
|
||||
openssl kdf -keylen 16 -kdfopt digest:SHA256 \
|
||||
-kdfopt hexkey:0102030405 \
|
||||
-kdfopt hexxcghash:06090A \
|
||||
-kdfopt hexsession_id:01020304 \
|
||||
-kdfopt type:A SSHKDF
|
||||
|
||||
Use PBKDF2 to create a hex-encoded derived key from a password and salt:
|
||||
|
||||
openssl kdf -keylen 32 -kdfopt digest:SHA256 -kdfopt pass:password \
|
||||
-kdfopt salt:salt -kdfopt iter:2 PBKDF2
|
||||
|
||||
Use scrypt to create a hex-encoded derived key from a password and salt:
|
||||
|
||||
openssl kdf -keylen 64 -kdfopt pass:password -kdfopt salt:NaCl \
|
||||
-kdfopt N:1024 -kdfopt r:8 -kdfopt p:16 \
|
||||
-kdfopt maxmem_bytes:10485760 id-scrypt
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The KDF mechanisms that are available will depend on the options
|
||||
used when building OpenSSL.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<EVP_KDF_CTX(3)>,
|
||||
L<EVP_KDF_SCRYPT(7)>
|
||||
L<EVP_KDF_TLS1_PRF(7)>
|
||||
L<EVP_KDF_PBKDF2(7)>
|
||||
L<EVP_KDF_HKDF(7)>
|
||||
L<EVP_KDF_SS(7)>
|
||||
L<EVP_KDF_SSHKDF(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
Added in OpenSSL 3.0
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the OpenSSL license (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
||||
+10
-2
@@ -167,6 +167,14 @@ Generation of Private Key or Parameters.
|
||||
|
||||
Generation of RSA Private Key. Superseded by L<genpkey(1)>.
|
||||
|
||||
=item B<info>
|
||||
|
||||
Display diverse information built into the OpenSSL libraries.
|
||||
|
||||
=item B<kdf>
|
||||
|
||||
Key Derivation Functions.
|
||||
|
||||
=item B<mac>
|
||||
|
||||
Message Authentication Code Calculation.
|
||||
@@ -612,7 +620,7 @@ L<crl(1)>, L<crl2pkcs7(1)>, L<dgst(1)>,
|
||||
L<dhparam(1)>, L<dsa(1)>, L<dsaparam(1)>,
|
||||
L<ec(1)>, L<ecparam(1)>,
|
||||
L<enc(1)>, L<engine(1)>, L<errstr(1)>, L<gendsa(1)>, L<genpkey(1)>,
|
||||
L<genrsa(1)>, L<mac(1)>, L<nseq(1)>, L<ocsp(1)>,
|
||||
L<genrsa(1)>, L<kdf(1)>, L<mac(1)>, L<nseq(1)>, L<ocsp(1)>,
|
||||
L<passwd(1)>,
|
||||
L<pkcs12(1)>, L<pkcs7(1)>, L<pkcs8(1)>,
|
||||
L<pkey(1)>, L<pkeyparam(1)>, L<pkeyutl(1)>, L<prime(1)>,
|
||||
@@ -632,7 +640,7 @@ manual pages.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
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
|
||||
|
||||
@@ -88,6 +88,22 @@ a buffering BIO to the chain will speed up the process.
|
||||
Calling BIO_set_mem_buf() on a BIO created with BIO_new_secmem() will
|
||||
give undefined results, including perhaps a program crash.
|
||||
|
||||
Switching the memory BIO from read write to read only is not supported and
|
||||
can give undefined results including a program crash. There are two notable
|
||||
exceptions to the rule. The first one is to assign a static memory buffer
|
||||
immediately after BIO creation and set the BIO as read only.
|
||||
|
||||
The other supported sequence is to start with read write BIO then temporarily
|
||||
switch it to read only and call BIO_reset() on the read only BIO immediately
|
||||
before switching it back to read write. Before the BIO is freed it must be
|
||||
switched back to the read write mode.
|
||||
|
||||
Calling BIO_get_mem_ptr() on read only BIO will return a BUF_MEM that
|
||||
contains only the remaining data to be read. If the close status of the
|
||||
BIO is set to BIO_NOCLOSE, before freeing the BUF_MEM the data pointer
|
||||
in it must be set to NULL as the data pointer does not point to an
|
||||
allocated memory.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
There should be an option to set the maximum size of a memory BIO.
|
||||
|
||||
@@ -200,7 +200,7 @@ ANSI X9.62, US Federal Information Processing Standard FIPS 186-2
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<DSA_new(3)>,
|
||||
L<EC_KEY_new(3)>,
|
||||
L<EVP_DigestSignInit(3)>,
|
||||
L<EVP_DigestVerifyInit(3)>
|
||||
|
||||
|
||||
@@ -151,9 +151,9 @@ The value string is expected to be the name of a MAC.
|
||||
This control expects one argument: C<EVP_MD *md>
|
||||
|
||||
For MAC implementations that use a message digest as an underlying computation
|
||||
algorithm, this control set what the digest algorithm should be.
|
||||
algorithm, this control sets what the digest algorithm should be.
|
||||
|
||||
EVP_KDF_ctrl_str() type string: "md"
|
||||
EVP_KDF_ctrl_str() type string: "digest"
|
||||
|
||||
The value string is expected to be the name of a digest.
|
||||
|
||||
@@ -232,6 +232,7 @@ L<EVP_KDF_TLS1_PRF(7)>
|
||||
L<EVP_KDF_PBKDF2(7)>
|
||||
L<EVP_KDF_HKDF(7)>
|
||||
L<EVP_KDF_SS(7)>
|
||||
L<EVP_KDF_SSHKDF(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
||||
@@ -21,7 +21,15 @@ The ChaCha20 stream cipher for EVP.
|
||||
|
||||
=item EVP_chacha20()
|
||||
|
||||
The ChaCha20 stream cipher. The key length is 256 bits, the IV is 96 bits long.
|
||||
The ChaCha20 stream cipher. The key length is 256 bits, the IV is 128 bits long.
|
||||
The first 32 bits consists of a counter in little-endian order followed by a 96
|
||||
bit nonce. For example a nonce of:
|
||||
|
||||
000000000000000000000002
|
||||
|
||||
With an initial counter of 42 (2a in hex) would be expressed as:
|
||||
|
||||
2a000000000000000000000000000002
|
||||
|
||||
=item EVP_chacha20_poly1305()
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ OPENSSL_VERSION_PRE_RELEASE_STR, OPENSSL_VERSION_BUILD_METADATA_STR,
|
||||
OPENSSL_VERSION_TEXT,
|
||||
OPENSSL_version_major, OPENSSL_version_minor, OPENSSL_version_patch,
|
||||
OPENSSL_version_pre_release, OPENSSL_version_build_metadata, OpenSSL_version,
|
||||
OPENSSL_VERSION_NUMBER, OpenSSL_version_num
|
||||
- get OpenSSL version number
|
||||
OPENSSL_VERSION_NUMBER, OpenSSL_version_num, OPENSSL_info
|
||||
- get OpenSSL version number and other information
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -37,6 +37,8 @@ OPENSSL_VERSION_NUMBER, OpenSSL_version_num
|
||||
|
||||
const char *OpenSSL_version(int t);
|
||||
|
||||
const char *OPENSSL_info(int t);
|
||||
|
||||
Deprecated:
|
||||
|
||||
/* from openssl/opensslv.h */
|
||||
@@ -127,6 +129,47 @@ if available or "ENGINESDIR: N/A" otherwise.
|
||||
|
||||
For an unknown B<t>, the text "not available" is returned.
|
||||
|
||||
OPENSSL_info() also returns different strings depending on B<t>:
|
||||
|
||||
=over 4
|
||||
|
||||
=item OPENSSL_INFO_CONFIG_DIR
|
||||
|
||||
The configured C<OPENSSLDIR>, which is the default location for
|
||||
OpenSSL configuration files.
|
||||
|
||||
=item OPENSSL_INFO_ENGINES_DIR
|
||||
|
||||
The configured C<ENGINESDIR>, which is the default location for
|
||||
OpenSSL engines.
|
||||
|
||||
=item OPENSSL_INFO_MODULES_DIR
|
||||
|
||||
The configured C<MODULESDIR>, which is the default location for
|
||||
dynamically loadable OpenSSL modules other than engines.
|
||||
|
||||
=item OPENSSL_INFO_DSO_EXTENSION
|
||||
|
||||
The configured dynamically loadable module extension.
|
||||
|
||||
=item OPENSSL_INFO_DIR_FILENAME_SEPARATOR
|
||||
|
||||
The separator between a directory specification and a file name.
|
||||
Note that on some operating systems, this is not the same as the
|
||||
separator between directory elements.
|
||||
|
||||
=item OPENSSL_INFO_LIST_SEPARATOR
|
||||
|
||||
The OpenSSL list separator.
|
||||
This is typically used in strings that are lists of items, such as the
|
||||
value of the environment variable C<$PATH> on Unix (where the
|
||||
separator is ":") or C<%PATH%> on Windows (where the separator is
|
||||
";").
|
||||
|
||||
=back
|
||||
|
||||
For an unknown B<t>, NULL is returned.
|
||||
|
||||
=head1 BACKWARD COMPATIBILITY
|
||||
|
||||
For compatibility, some older macros and functions are retained or
|
||||
|
||||
@@ -65,6 +65,8 @@ both required, and on success the caller must release the storage allocated for
|
||||
B<*out> using OPENSSL_free(). The contents of B<*out> is an array of integers
|
||||
holding the numerical value of the TLS extension types in the order they appear
|
||||
in the ClientHello. B<*outlen> contains the number of elements in the array.
|
||||
In situations when the ClientHello has no extensions, the function will return
|
||||
success with B<*out> set to NULL and B<*outlen> set to 0.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
|
||||
@@ -90,6 +90,10 @@ static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
|
||||
# define TCP_ULP 31
|
||||
# endif
|
||||
|
||||
# ifndef TLS_RX
|
||||
# define TLS_RX 2
|
||||
# endif
|
||||
|
||||
/*
|
||||
* When successful, this socket option doesn't change the behaviour of the
|
||||
* TCP socket, except changing the TCP setsockopt handler to enable the
|
||||
|
||||
+11
-4
@@ -152,13 +152,20 @@ extern "C" {
|
||||
* # define BIO_CTRL_CLEAR_KTLS_CTRL_MSG 75
|
||||
*/
|
||||
|
||||
# define BIO_CTRL_GET_KTLS_SEND 73
|
||||
# define BIO_CTRL_GET_KTLS_RECV 76
|
||||
# define BIO_CTRL_GET_KTLS_SEND 73
|
||||
# define BIO_CTRL_GET_KTLS_RECV 76
|
||||
|
||||
# ifndef OPENSSL_NO_KTLS
|
||||
# define BIO_get_ktls_send(b) \
|
||||
BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL)
|
||||
(BIO_method_type(b) == BIO_TYPE_SOCKET \
|
||||
&& BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL))
|
||||
# define BIO_get_ktls_recv(b) \
|
||||
BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL)
|
||||
(BIO_method_type(b) == BIO_TYPE_SOCKET \
|
||||
&& BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL))
|
||||
# else
|
||||
# define BIO_get_ktls_send(b) (0)
|
||||
# define BIO_get_ktls_recv(b) (0)
|
||||
# endif
|
||||
|
||||
/* modifiers */
|
||||
# define BIO_FP_READ 0x02
|
||||
|
||||
@@ -34,6 +34,12 @@ extern "C" {
|
||||
*/
|
||||
#define OSSL_PROV_PARAM_BUILDINFO "buildinfo"
|
||||
|
||||
|
||||
/* Well known cipher parameters */
|
||||
|
||||
#define OSSL_CIPHER_PARAM_PADDING "padding"
|
||||
#define OSSL_CIPHER_PARAM_MODE "mode"
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -78,7 +78,7 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
|
||||
|
||||
# define OSSL_FUNC_DIGEST_NEWCTX 1
|
||||
# define OSSL_FUNC_DIGEST_INIT 2
|
||||
# define OSSL_FUNC_DIGEST_UPDDATE 3
|
||||
# define OSSL_FUNC_DIGEST_UPDATE 3
|
||||
# define OSSL_FUNC_DIGEST_FINAL 4
|
||||
# define OSSL_FUNC_DIGEST_DIGEST 5
|
||||
# define OSSL_FUNC_DIGEST_FREECTX 6
|
||||
@@ -86,21 +86,74 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
|
||||
# define OSSL_FUNC_DIGEST_SIZE 8
|
||||
# define OSSL_FUNC_DIGEST_BLOCK_SIZE 9
|
||||
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_digest_update,
|
||||
(void *, const unsigned char *in, size_t inl))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
|
||||
(void *, unsigned char *out, size_t *outl))
|
||||
(void *, unsigned char *out, size_t *outl, size_t outsz))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
|
||||
(const unsigned char *in, size_t inl, unsigned char *out,
|
||||
size_t *out_l))
|
||||
size_t *out_l, size_t outsz))
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_digest_dupctx, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(size_t, OP_digest_size, (void))
|
||||
OSSL_CORE_MAKE_FUNC(size_t, OP_digest_block_size, (void))
|
||||
|
||||
|
||||
/* Symmetric Ciphers */
|
||||
|
||||
# define OSSL_OP_CIPHER 2
|
||||
|
||||
# define OSSL_FUNC_CIPHER_NEWCTX 1
|
||||
# define OSSL_FUNC_CIPHER_ENCRYPT_INIT 2
|
||||
# define OSSL_FUNC_CIPHER_DECRYPT_INIT 3
|
||||
# define OSSL_FUNC_CIPHER_UPDATE 4
|
||||
# define OSSL_FUNC_CIPHER_FINAL 5
|
||||
# define OSSL_FUNC_CIPHER_CIPHER 6
|
||||
# define OSSL_FUNC_CIPHER_FREECTX 7
|
||||
# define OSSL_FUNC_CIPHER_DUPCTX 8
|
||||
# define OSSL_FUNC_CIPHER_KEY_LENGTH 9
|
||||
# define OSSL_FUNC_CIPHER_IV_LENGTH 10
|
||||
# define OSSL_FUNC_CIPHER_BLOCK_SIZE 11
|
||||
# define OSSL_FUNC_CIPHER_GET_PARAMS 12
|
||||
# define OSSL_FUNC_CIPHER_CTX_GET_PARAMS 13
|
||||
# define OSSL_FUNC_CIPHER_CTX_SET_PARAMS 14
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_cipher_newctx, (void))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_encrypt_init, (void *vctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen,
|
||||
const unsigned char *iv,
|
||||
size_t ivlen))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_decrypt_init, (void *vctx,
|
||||
const unsigned char *key,
|
||||
size_t keylen,
|
||||
const unsigned char *iv,
|
||||
size_t ivlen))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_update,
|
||||
(void *, unsigned char *out, size_t *outl, size_t outsize,
|
||||
const unsigned char *in, size_t inl))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_final,
|
||||
(void *, unsigned char *out, size_t *outl, size_t outsize))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_cipher,
|
||||
(void *, unsigned char *out, const unsigned char *in,
|
||||
size_t inl))
|
||||
OSSL_CORE_MAKE_FUNC(void, OP_cipher_freectx, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_cipher_dupctx, (void *vctx))
|
||||
OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_key_length, (void))
|
||||
OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_iv_length, (void))
|
||||
OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_block_size, (void))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_get_params, (const OSSL_PARAM params[]))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *vctx,
|
||||
const OSSL_PARAM params[]))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *vctx,
|
||||
const OSSL_PARAM params[]))
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -163,6 +163,19 @@ const char *OpenSSL_version(int type);
|
||||
# define OPENSSL_ENGINES_DIR 5
|
||||
# define OPENSSL_VERSION_STRING 6
|
||||
# define OPENSSL_FULL_VERSION_STRING 7
|
||||
# define OPENSSL_MODULES_DIR 8
|
||||
|
||||
const char *OPENSSL_info(int type);
|
||||
/*
|
||||
* The series starts at 1001 to avoid confusion with the OpenSSL_version
|
||||
* types.
|
||||
*/
|
||||
# define OPENSSL_INFO_CONFIG_DIR 1001
|
||||
# define OPENSSL_INFO_ENGINES_DIR 1002
|
||||
# define OPENSSL_INFO_MODULES_DIR 1003
|
||||
# define OPENSSL_INFO_DSO_EXTENSION 1004
|
||||
# define OPENSSL_INFO_DIR_FILENAME_SEPARATOR 1005
|
||||
# define OPENSSL_INFO_LIST_SEPARATOR 1006
|
||||
|
||||
int OPENSSL_issetugid(void);
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ typedef struct err_state_st {
|
||||
# define ERR_LIB_ESS 54
|
||||
# define ERR_LIB_PROP 55
|
||||
# define ERR_LIB_CRMF 56
|
||||
# define ERR_LIB_PROV 57
|
||||
|
||||
# define ERR_LIB_USER 128
|
||||
|
||||
@@ -140,6 +141,7 @@ typedef struct err_state_st {
|
||||
# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
|
||||
# define ESSerr(f,r) ERR_PUT_error(ERR_LIB_ESS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
|
||||
# define PROPerr(f,r) ERR_PUT_error(ERR_LIB_PROP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
|
||||
# define PROVerr(f,r) ERR_PUT_error(ERR_LIB_PROV,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
|
||||
|
||||
# define ERR_PACK(l,f,r) ( \
|
||||
(((unsigned int)(l) & 0x0FF) << 24L) | \
|
||||
|
||||
@@ -190,6 +190,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
|
||||
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
|
||||
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
|
||||
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
|
||||
int EVP_CIPHER_upref(EVP_CIPHER *cipher);
|
||||
|
||||
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
|
||||
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
|
||||
@@ -473,7 +474,9 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher);
|
||||
int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
|
||||
int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
|
||||
unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
|
||||
# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
|
||||
int EVP_CIPHER_mode(const EVP_CIPHER *cipher);
|
||||
EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
||||
const char *properties);
|
||||
|
||||
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
|
||||
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
@@ -55,6 +55,9 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_F_EVP_CIPHER_CTX_COPY 163
|
||||
# define EVP_F_EVP_CIPHER_CTX_CTRL 124
|
||||
# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122
|
||||
# define EVP_F_EVP_CIPHER_CTX_SET_PADDING 237
|
||||
# define EVP_F_EVP_CIPHER_FROM_DISPATCH 238
|
||||
# define EVP_F_EVP_CIPHER_MODE 239
|
||||
# define EVP_F_EVP_CIPHER_PARAM_TO_ASN1 205
|
||||
# define EVP_F_EVP_DECRYPTFINAL_EX 101
|
||||
# define EVP_F_EVP_DECRYPTUPDATE 166
|
||||
@@ -190,6 +193,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_INVALID_KEY 163
|
||||
# define EVP_R_INVALID_KEY_LENGTH 130
|
||||
# define EVP_R_INVALID_OPERATION 148
|
||||
# define EVP_R_INVALID_PROVIDER_FUNCTIONS 193
|
||||
# define EVP_R_INVALID_SALT_LENGTH 186
|
||||
# define EVP_R_KEYGEN_FAILURE 120
|
||||
# define EVP_R_KEY_SETUP_FAILED 180
|
||||
|
||||
@@ -7,7 +7,7 @@ IF[{- !$disabled{fips} -}]
|
||||
SOURCE[fips]=fips.ld
|
||||
GENERATE[fips.ld]=../util/providers.num
|
||||
ENDIF
|
||||
INCLUDE[fips]=.. ../include ../crypto/include
|
||||
INCLUDE[fips]=.. ../include ../crypto/include common/include
|
||||
DEFINE[fips]=FIPS_MODE
|
||||
ENDIF
|
||||
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
SUBDIRS=digests
|
||||
SUBDIRS=digests ciphers
|
||||
|
||||
SOURCE[../../libcrypto]=\
|
||||
provider_err.c
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/provider_algs.h"
|
||||
#include "ciphers_locl.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
static OSSL_OP_cipher_encrypt_init_fn aes_einit;
|
||||
static OSSL_OP_cipher_decrypt_init_fn aes_dinit;
|
||||
static OSSL_OP_cipher_update_fn aes_block_update;
|
||||
static OSSL_OP_cipher_final_fn aes_block_final;
|
||||
static OSSL_OP_cipher_update_fn aes_stream_update;
|
||||
static OSSL_OP_cipher_final_fn aes_stream_final;
|
||||
static OSSL_OP_cipher_cipher_fn aes_cipher;
|
||||
static OSSL_OP_cipher_freectx_fn aes_freectx;
|
||||
static OSSL_OP_cipher_dupctx_fn aes_dupctx;
|
||||
static OSSL_OP_cipher_key_length_fn key_length_256;
|
||||
static OSSL_OP_cipher_key_length_fn key_length_192;
|
||||
static OSSL_OP_cipher_key_length_fn key_length_128;
|
||||
static OSSL_OP_cipher_iv_length_fn iv_length_16;
|
||||
static OSSL_OP_cipher_iv_length_fn iv_length_0;
|
||||
static OSSL_OP_cipher_block_size_fn block_size_16;
|
||||
static OSSL_OP_cipher_block_size_fn block_size_1;
|
||||
static OSSL_OP_cipher_ctx_get_params_fn aes_ctx_get_params;
|
||||
static OSSL_OP_cipher_ctx_set_params_fn aes_ctx_set_params;
|
||||
|
||||
static int PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx,
|
||||
const unsigned char *iv,
|
||||
size_t ivlen,
|
||||
int enc)
|
||||
{
|
||||
if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
|
||||
if (ivlen != AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_PROV_AES_KEY_GENERIC_INIT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
ctx->enc = enc;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_einit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 1)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
PROVerr(PROV_F_AES_EINIT, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->ciph->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_dinit(void *vctx, const unsigned char *key, size_t keylen,
|
||||
const unsigned char *iv, size_t ivlen)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 0)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
if (key != NULL) {
|
||||
if (keylen != ctx->keylen) {
|
||||
PROVerr(PROV_F_AES_DINIT, PROV_R_INVALID_KEYLEN);
|
||||
return 0;
|
||||
}
|
||||
return ctx->ciph->init(ctx, key, ctx->keylen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_block_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in, size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in,
|
||||
&inl);
|
||||
size_t outlint = 0;
|
||||
|
||||
/*
|
||||
* If we're decrypting and we end an update on a block boundary we hold
|
||||
* the last block back in case this is the last update call and the last
|
||||
* block is padded.
|
||||
*/
|
||||
if (ctx->bufsz == AES_BLOCK_SIZE
|
||||
&& (ctx->enc || inl > 0 || !ctx->pad)) {
|
||||
if (outsize < AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
outlint = AES_BLOCK_SIZE;
|
||||
out += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (nextblocks > 0) {
|
||||
if (!ctx->enc && ctx->pad && nextblocks == inl) {
|
||||
if (!ossl_assert(inl >= AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
nextblocks -= AES_BLOCK_SIZE;
|
||||
}
|
||||
outlint += nextblocks;
|
||||
if (outsize < outlint) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
in += nextblocks;
|
||||
inl -= nextblocks;
|
||||
}
|
||||
if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = outlint;
|
||||
return inl == 0;
|
||||
}
|
||||
|
||||
static int aes_block_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (ctx->enc) {
|
||||
if (ctx->pad) {
|
||||
padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE);
|
||||
} else if (ctx->bufsz == 0) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
} else if (ctx->bufsz != AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < AES_BLOCK_SIZE) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
ctx->bufsz = 0;
|
||||
*outl = AES_BLOCK_SIZE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decrypting */
|
||||
if (ctx->bufsz != AES_BLOCK_SIZE) {
|
||||
if (ctx->bufsz == 0 && !ctx->pad) {
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) {
|
||||
/* PROVerr already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outsize < ctx->bufsz) {
|
||||
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, ctx->buf, ctx->bufsz);
|
||||
*outl = ctx->bufsz;
|
||||
ctx->bufsz = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_stream_update(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (outsize < inl) {
|
||||
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
|
||||
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*outl = inl;
|
||||
return 1;
|
||||
}
|
||||
static int aes_stream_final(void *vctx, unsigned char *out, size_t *outl,
|
||||
size_t outsize)
|
||||
{
|
||||
*outl = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cipher(void *vctx, unsigned char *out, const unsigned char *in,
|
||||
size_t inl)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
|
||||
PROVerr(PROV_F_AES_CIPHER, PROV_R_CIPHER_OPERATION_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_new_params(lcmode, UCMODE) \
|
||||
static OSSL_OP_cipher_get_params_fn aes_##lcmode##_get_params; \
|
||||
static int aes_##lcmode##_get_params(const OSSL_PARAM params[]) \
|
||||
{ \
|
||||
const OSSL_PARAM *p; \
|
||||
\
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \
|
||||
if (p != NULL && !OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \
|
||||
return 0; \
|
||||
\
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_new_ctx(lcmode, UCMODE, len) \
|
||||
static OSSL_OP_cipher_newctx_fn aes_##len##_##lcmode##_newctx; \
|
||||
static void *aes_##len##_##lcmode##_newctx(void) \
|
||||
{ \
|
||||
PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
||||
\
|
||||
ctx->pad = 1; \
|
||||
ctx->keylen = (len / 8); \
|
||||
ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
|
||||
ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
|
||||
return ctx; \
|
||||
}
|
||||
|
||||
/* ECB */
|
||||
IMPLEMENT_new_params(ecb, ECB)
|
||||
IMPLEMENT_new_ctx(ecb, ECB, 256)
|
||||
IMPLEMENT_new_ctx(ecb, ECB, 192)
|
||||
IMPLEMENT_new_ctx(ecb, ECB, 128)
|
||||
|
||||
/* CBC */
|
||||
IMPLEMENT_new_params(cbc, CBC)
|
||||
IMPLEMENT_new_ctx(cbc, CBC, 256)
|
||||
IMPLEMENT_new_ctx(cbc, CBC, 192)
|
||||
IMPLEMENT_new_ctx(cbc, CBC, 128)
|
||||
|
||||
/* OFB */
|
||||
IMPLEMENT_new_params(ofb, OFB)
|
||||
IMPLEMENT_new_ctx(ofb, OFB, 256)
|
||||
IMPLEMENT_new_ctx(ofb, OFB, 192)
|
||||
IMPLEMENT_new_ctx(ofb, OFB, 128)
|
||||
|
||||
/* CFB */
|
||||
IMPLEMENT_new_params(cfb, CFB)
|
||||
IMPLEMENT_new_params(cfb1, CFB)
|
||||
IMPLEMENT_new_params(cfb8, CFB)
|
||||
IMPLEMENT_new_ctx(cfb, CFB, 256)
|
||||
IMPLEMENT_new_ctx(cfb, CFB, 192)
|
||||
IMPLEMENT_new_ctx(cfb, CFB, 128)
|
||||
IMPLEMENT_new_ctx(cfb1, CFB, 256)
|
||||
IMPLEMENT_new_ctx(cfb1, CFB, 192)
|
||||
IMPLEMENT_new_ctx(cfb1, CFB, 128)
|
||||
IMPLEMENT_new_ctx(cfb8, CFB, 256)
|
||||
IMPLEMENT_new_ctx(cfb8, CFB, 192)
|
||||
IMPLEMENT_new_ctx(cfb8, CFB, 128)
|
||||
|
||||
/* CTR */
|
||||
IMPLEMENT_new_params(ctr, CTR)
|
||||
IMPLEMENT_new_ctx(ctr, CTR, 256)
|
||||
IMPLEMENT_new_ctx(ctr, CTR, 192)
|
||||
IMPLEMENT_new_ctx(ctr, CTR, 128)
|
||||
|
||||
static void aes_freectx(void *vctx)
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
static void *aes_dupctx(void *ctx)
|
||||
{
|
||||
PROV_AES_KEY *in = (PROV_AES_KEY *)ctx;
|
||||
PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
PROVerr(PROV_F_AES_DUPCTX, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
*ret = *in;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t key_length_256(void)
|
||||
{
|
||||
return 256 / 8;
|
||||
}
|
||||
|
||||
static size_t key_length_192(void)
|
||||
{
|
||||
return 192 / 8;
|
||||
}
|
||||
|
||||
static size_t key_length_128(void)
|
||||
{
|
||||
return 128 / 8;
|
||||
}
|
||||
|
||||
static size_t iv_length_16(void)
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
static size_t iv_length_0(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t block_size_16(void)
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
static size_t block_size_1(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctx_get_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->pad)) {
|
||||
PROVerr(PROV_F_AES_CTX_GET_PARAMS, PROV_R_FAILED_TO_SET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
|
||||
if (p != NULL) {
|
||||
int pad;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &pad)) {
|
||||
PROVerr(PROV_F_AES_CTX_SET_PARAMS, PROV_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx->pad = pad ? 1 : 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_block_funcs(mode, keylen, ivlen) \
|
||||
const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_block_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_block_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \
|
||||
{ OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \
|
||||
{ OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_16 }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define IMPLEMENT_stream_funcs(mode, keylen, ivlen) \
|
||||
const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \
|
||||
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \
|
||||
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
|
||||
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
|
||||
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_stream_update }, \
|
||||
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_stream_final }, \
|
||||
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
|
||||
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
|
||||
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
|
||||
{ OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \
|
||||
{ OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \
|
||||
{ OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_1 }, \
|
||||
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
|
||||
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
/* ECB */
|
||||
IMPLEMENT_block_funcs(ecb, 256, 0)
|
||||
IMPLEMENT_block_funcs(ecb, 192, 0)
|
||||
IMPLEMENT_block_funcs(ecb, 128, 0)
|
||||
|
||||
/* CBC */
|
||||
IMPLEMENT_block_funcs(cbc, 256, 16)
|
||||
IMPLEMENT_block_funcs(cbc, 192, 16)
|
||||
IMPLEMENT_block_funcs(cbc, 128, 16)
|
||||
|
||||
/* OFB */
|
||||
IMPLEMENT_stream_funcs(ofb, 256, 16)
|
||||
IMPLEMENT_stream_funcs(ofb, 192, 16)
|
||||
IMPLEMENT_stream_funcs(ofb, 128, 16)
|
||||
|
||||
/* CFB */
|
||||
IMPLEMENT_stream_funcs(cfb, 256, 16)
|
||||
IMPLEMENT_stream_funcs(cfb, 192, 16)
|
||||
IMPLEMENT_stream_funcs(cfb, 128, 16)
|
||||
IMPLEMENT_stream_funcs(cfb1, 256, 16)
|
||||
IMPLEMENT_stream_funcs(cfb1, 192, 16)
|
||||
IMPLEMENT_stream_funcs(cfb1, 128, 16)
|
||||
IMPLEMENT_stream_funcs(cfb8, 256, 16)
|
||||
IMPLEMENT_stream_funcs(cfb8, 192, 16)
|
||||
IMPLEMENT_stream_funcs(cfb8, 128, 16)
|
||||
|
||||
/* CTR */
|
||||
IMPLEMENT_stream_funcs(ctr, 256, 16)
|
||||
IMPLEMENT_stream_funcs(ctr, 192, 16)
|
||||
IMPLEMENT_stream_funcs(ctr, 128, 16)
|
||||
@@ -0,0 +1,866 @@
|
||||
/*
|
||||
* Copyright 2001-2018 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/opensslconf.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/aes.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include "ciphers_locl.h"
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
|
||||
|
||||
#ifdef VPAES_ASM
|
||||
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void vpaes_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void vpaes_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
|
||||
void vpaes_cbc_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length,
|
||||
const AES_KEY *key, unsigned char *ivec, int enc);
|
||||
#endif
|
||||
#ifdef BSAES_ASM
|
||||
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t length, const AES_KEY *key,
|
||||
unsigned char ivec[16], int enc);
|
||||
void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const unsigned char ivec[16]);
|
||||
#endif
|
||||
#ifdef AES_CTR_ASM
|
||||
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
const unsigned char ivec[AES_BLOCK_SIZE]);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
|
||||
# include "ppc_arch.h"
|
||||
# ifdef VPAES_ASM
|
||||
# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
|
||||
# endif
|
||||
# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
|
||||
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
|
||||
# define HWAES_encrypt aes_p8_encrypt
|
||||
# define HWAES_decrypt aes_p8_decrypt
|
||||
# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
|
||||
# define HWAES_xts_encrypt aes_p8_xts_encrypt
|
||||
# define HWAES_xts_decrypt aes_p8_xts_decrypt
|
||||
#endif
|
||||
|
||||
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
|
||||
((defined(__i386) || defined(__i386__) || \
|
||||
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
|
||||
defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64) )
|
||||
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
|
||||
# ifdef VPAES_ASM
|
||||
# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
|
||||
# endif
|
||||
# ifdef BSAES_ASM
|
||||
# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
|
||||
# endif
|
||||
/*
|
||||
* AES-NI section
|
||||
*/
|
||||
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
|
||||
|
||||
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void aesni_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void aesni_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
|
||||
void aesni_ecb_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length, const AES_KEY *key, int enc);
|
||||
void aesni_cbc_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t length,
|
||||
const AES_KEY *key, unsigned char *ivec, int enc);
|
||||
|
||||
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
size_t blocks,
|
||||
const void *key, const unsigned char *ivec);
|
||||
|
||||
static int aesni_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = aesni_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f) aesni_decrypt;
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aesni_cbc_encrypt : NULL;
|
||||
} else {
|
||||
ret = aesni_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f) aesni_encrypt;
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AESNI_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aesni_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
aesni_cbc_encrypt(in, out, len, &ctx->ks.ks, ctx->iv, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aesni_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 1;
|
||||
|
||||
aesni_ecb_encrypt(in, out, len, &ctx->ks.ks, ctx->enc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define aesni_ofb_cipher aes_ofb_cipher
|
||||
static int aesni_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb_cipher aes_cfb_cipher
|
||||
static int aesni_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb8_cipher aes_cfb8_cipher
|
||||
static int aesni_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_cfb1_cipher aes_cfb1_cipher
|
||||
static int aesni_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aesni_ctr_cipher aes_ctr_cipher
|
||||
static int aesni_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aesni_##mode = { \
|
||||
aesni_init_key, \
|
||||
aesni_##mode##_cipher}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return AESNI_CAPABLE?&aesni_##mode:&aes_##mode; }
|
||||
|
||||
|
||||
#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
|
||||
|
||||
# include "sparc_arch.h"
|
||||
|
||||
extern unsigned int OPENSSL_sparcv9cap_P[];
|
||||
|
||||
/*
|
||||
* Fujitsu SPARC64 X support
|
||||
*/
|
||||
# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
|
||||
# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
|
||||
# define HWAES_encrypt aes_fx_encrypt
|
||||
# define HWAES_decrypt aes_fx_decrypt
|
||||
# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
|
||||
|
||||
# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
|
||||
|
||||
void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
|
||||
void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
|
||||
void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
/*
|
||||
* Key-length specific subroutines were chosen for following reason.
|
||||
* Each SPARC T4 core can execute up to 8 threads which share core's
|
||||
* resources. Loading as much key material to registers allows to
|
||||
* minimize references to shared memory interface, as well as amount
|
||||
* of instructions in inner loops [much needed on T4]. But then having
|
||||
* non-key-length specific routines would require conditional branches
|
||||
* either in inner loops or on subroutines' entries. Former is hardly
|
||||
* acceptable, while latter means code size increase to size occupied
|
||||
* by multiple key-length specific subroutines, so why fight?
|
||||
*/
|
||||
void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t blocks, const AES_KEY *key,
|
||||
unsigned char *ivec);
|
||||
|
||||
static int aes_t4_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret, bits;
|
||||
|
||||
bits = keylen * 8;
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
ret = 0;
|
||||
aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
|
||||
dat->block = (block128_f) aes_t4_decrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes128_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 192:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes192_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
case 256:
|
||||
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
|
||||
(cbc128_f) aes256_t4_cbc_decrypt : NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
|
||||
dat->block = (block128_f)aes_t4_encrypt;
|
||||
switch (bits) {
|
||||
case 128:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 192:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
case 256:
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
|
||||
else if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
|
||||
else
|
||||
dat->stream.cbc = NULL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AES_T4_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define aes_t4_cbc_cipher aes_cbc_cipher
|
||||
static int aes_t4_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ecb_cipher aes_ecb_cipher
|
||||
static int aes_t4_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ofb_cipher aes_ofb_cipher
|
||||
static int aes_t4_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb_cipher aes_cfb_cipher
|
||||
static int aes_t4_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb8_cipher aes_cfb8_cipher
|
||||
static int aes_t4_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_cfb1_cipher aes_cfb1_cipher
|
||||
static int aes_t4_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define aes_t4_ctr_cipher aes_ctr_cipher
|
||||
static int aes_t4_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aes_t4_##mode = { \
|
||||
aes_t4_init_key, \
|
||||
aes_t4_##mode##_cipher}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return SPARC_AES_CAPABLE?&aes_t4_##mode:&aes_##mode; }
|
||||
|
||||
|
||||
#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
/*
|
||||
* IBM S390X support
|
||||
*/
|
||||
# include "s390x_arch.h"
|
||||
|
||||
/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
|
||||
# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
|
||||
|
||||
/* Most modes of operation need km for partial block processing. */
|
||||
# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128))
|
||||
# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192))
|
||||
# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256))
|
||||
|
||||
# define s390x_aes_init_key aes_init_key
|
||||
static int s390x_aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen);
|
||||
|
||||
# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */
|
||||
# define S390X_aes_192_cbc_CAPABLE 1
|
||||
# define S390X_aes_256_cbc_CAPABLE 1
|
||||
# define S390X_AES_CBC_CTX PROV_AES_KEY
|
||||
|
||||
# define s390x_aes_cbc_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_cbc_cipher aes_cbc_cipher
|
||||
static int s390x_aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
|
||||
# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
|
||||
# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
|
||||
|
||||
static int s390x_aes_ecb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(dat->plat.s390x.param.km.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
s390x_km(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.km);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128)))
|
||||
# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192)))
|
||||
# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmo[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256)))
|
||||
|
||||
static int s390x_aes_ofb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.res = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int n = dat->plat.s390x.res;
|
||||
int rem;
|
||||
|
||||
while (n && len) {
|
||||
*out = *in ^ dat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmo(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
dat->plat.s390x.param.kmo_kmf.cv, dat->plat.s390x.fc,
|
||||
dat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
out[n] = in[n] ^ dat->plat.s390x.param.kmo_kmf.cv[n];
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
dat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128)))
|
||||
# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192)))
|
||||
# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
|
||||
(OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256)))
|
||||
|
||||
static int s390x_aes_cfb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
dat->plat.s390x.res = 0;
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int n = dat->plat.s390x.res;
|
||||
int rem;
|
||||
unsigned char tmp;
|
||||
|
||||
while (n && len) {
|
||||
tmp = *in;
|
||||
*out = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
|
||||
n = (n + 1) & 0xf;
|
||||
--len;
|
||||
++in;
|
||||
++out;
|
||||
}
|
||||
|
||||
rem = len & 0xf;
|
||||
|
||||
len &= ~(size_t)0xf;
|
||||
if (len) {
|
||||
s390x_kmf(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
|
||||
out += len;
|
||||
in += len;
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
|
||||
dat->plat.s390x.param.kmo_kmf.cv,
|
||||
S390X_AES_FC(dat->keylen), dat->plat.s390x.param.kmo_kmf.k);
|
||||
|
||||
while (rem--) {
|
||||
tmp = in[n];
|
||||
out[n] = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
||||
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
dat->plat.s390x.res = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_128))
|
||||
# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_192))
|
||||
# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
|
||||
S390X_CAPBIT(S390X_AES_256))
|
||||
|
||||
static int s390x_aes_cfb8_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
dat->plat.s390x.fc = S390X_AES_FC(keylen);
|
||||
dat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
|
||||
if (!dat->enc)
|
||||
dat->plat.s390x.fc |= S390X_DECRYPT;
|
||||
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
|
||||
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int s390x_aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
s390x_kmf(in, len, out, dat->plat.s390x.fc,
|
||||
&dat->plat.s390x.param.kmo_kmf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# define S390X_aes_128_cfb1_CAPABLE 0
|
||||
# define S390X_aes_192_cfb1_CAPABLE 0
|
||||
# define S390X_aes_256_cfb1_CAPABLE 0
|
||||
|
||||
# define s390x_aes_cfb1_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_cfb1_cipher aes_cfb1_cipher
|
||||
static int s390x_aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */
|
||||
# define S390X_aes_192_ctr_CAPABLE 1
|
||||
# define S390X_aes_256_ctr_CAPABLE 1
|
||||
# define S390X_AES_CTR_CTX PROV_AES_KEY
|
||||
|
||||
# define s390x_aes_ctr_init_key aes_init_key
|
||||
|
||||
# define s390x_aes_ctr_cipher aes_ctr_cipher
|
||||
static int s390x_aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len);
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER s390x_aes_##mode = { \
|
||||
s390x_aes_##mode##_init_key, \
|
||||
s390x_aes_##mode##_cipher \
|
||||
}; \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher \
|
||||
}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ \
|
||||
if ((keylen == 128 && S390X_aes_128_##mode##_CAPABLE) \
|
||||
|| (keylen == 192 && S390X_aes_192_##mode##_CAPABLE) \
|
||||
|| (keylen == 256 && S390X_aes_256_##mode##_CAPABLE)) \
|
||||
return &s390x_aes_##mode; \
|
||||
\
|
||||
return &aes_##mode; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define BLOCK_CIPHER_generic_prov(mode) \
|
||||
static const PROV_AES_CIPHER aes_##mode = { \
|
||||
aes_init_key, \
|
||||
aes_##mode##_cipher}; \
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
|
||||
{ return &aes_##mode; }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
|
||||
# include "arm_arch.h"
|
||||
# if __ARM_MAX_ARCH__>=7
|
||||
# if defined(BSAES_ASM)
|
||||
# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
|
||||
# endif
|
||||
# if defined(VPAES_ASM)
|
||||
# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
|
||||
# endif
|
||||
# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
|
||||
# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
|
||||
# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
|
||||
# define HWAES_encrypt aes_v8_encrypt
|
||||
# define HWAES_decrypt aes_v8_decrypt
|
||||
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
|
||||
# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HWAES_CAPABLE)
|
||||
int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
void HWAES_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void HWAES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t length, const AES_KEY *key,
|
||||
unsigned char *ivec, const int enc);
|
||||
void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const unsigned char ivec[16]);
|
||||
#endif
|
||||
|
||||
static int aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
|
||||
&& !dat->enc) {
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)HWAES_decrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
# endif
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
?(cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
}
|
||||
} else
|
||||
#ifdef HWAES_CAPABLE
|
||||
if (HWAES_CAPABLE) {
|
||||
ret = HWAES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)HWAES_encrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
# ifdef HWAES_cbc_encrypt
|
||||
if (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
|
||||
else
|
||||
# endif
|
||||
# ifdef HWAES_ctr32_encrypt_blocks
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
|
||||
else
|
||||
# endif
|
||||
(void)0; /* terminate potentially open 'else' */
|
||||
} else
|
||||
#endif
|
||||
#ifdef BSAES_CAPABLE
|
||||
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
||||
} else
|
||||
#endif
|
||||
#ifdef VPAES_CAPABLE
|
||||
if (VPAES_CAPABLE) {
|
||||
ret = vpaes_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
|
||||
? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
#ifdef AES_CTR_ASM
|
||||
if (dat->mode == EVP_CIPH_CTR_MODE)
|
||||
dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
PROVerr(PROV_F_AES_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
if (dat->stream.cbc)
|
||||
(*dat->stream.cbc) (in, out, len, &dat->ks, dat->iv, dat->enc);
|
||||
else if (dat->enc)
|
||||
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, dat->iv, dat->block);
|
||||
else
|
||||
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, dat->iv, dat->block);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
return 1;
|
||||
|
||||
for (i = 0, len -= AES_BLOCK_SIZE; i <= len; i += AES_BLOCK_SIZE)
|
||||
(*dat->block) (in + i, out + i, &dat->ks);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
|
||||
dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
int num = dat->num;
|
||||
|
||||
if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
dat->num = num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (len >= MAXBITCHUNK) {
|
||||
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
|
||||
dat->iv, &num, dat->enc, dat->block);
|
||||
len -= MAXBITCHUNK;
|
||||
out += MAXBITCHUNK;
|
||||
in += MAXBITCHUNK;
|
||||
}
|
||||
if (len)
|
||||
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, dat->iv, &num,
|
||||
dat->enc, dat->block);
|
||||
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
unsigned int num = dat->num;
|
||||
|
||||
if (dat->stream.ctr)
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->stream.ctr);
|
||||
else
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, dat->iv, dat->buf,
|
||||
&num, dat->block);
|
||||
dat->num = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BLOCK_CIPHER_generic_prov(cbc)
|
||||
BLOCK_CIPHER_generic_prov(ecb)
|
||||
BLOCK_CIPHER_generic_prov(ofb)
|
||||
BLOCK_CIPHER_generic_prov(cfb)
|
||||
BLOCK_CIPHER_generic_prov(cfb1)
|
||||
BLOCK_CIPHER_generic_prov(cfb8)
|
||||
BLOCK_CIPHER_generic_prov(ctr)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include "ciphers_locl.h"
|
||||
#include <assert.h>
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
/*
|
||||
* Fills a single block of buffered data from the input, and returns the amount
|
||||
* of data remaining in the input that is a multiple of the blocksize. The buffer
|
||||
* is only filled if it already has some data in it, isn't full already or we
|
||||
* don't have at least one block in the input.
|
||||
*
|
||||
* buf: a buffer of blocksize bytes
|
||||
* buflen: contains the amount of data already in buf on entry. Updated with the
|
||||
* amount of data in buf at the end. On entry *buflen must always be
|
||||
* less than the blocksize
|
||||
* blocksize: size of a block. Must be greater than 0 and a power of 2
|
||||
* in: pointer to a pointer containing the input data
|
||||
* inlen: amount of input data available
|
||||
*
|
||||
* On return buf is filled with as much data as possible up to a full block,
|
||||
* *buflen is updated containing the amount of data in buf. *in is updated to
|
||||
* the new location where input data should be read from, *inlen is updated with
|
||||
* the remaining amount of data in *in. Returns the largest value <= *inlen
|
||||
* which is a multiple of the blocksize.
|
||||
*/
|
||||
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen)
|
||||
{
|
||||
size_t blockmask = ~(blocksize - 1);
|
||||
|
||||
assert(*buflen <= blocksize);
|
||||
assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
|
||||
|
||||
if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) {
|
||||
size_t bufremain = blocksize - *buflen;
|
||||
|
||||
if (*inlen < bufremain)
|
||||
bufremain = *inlen;
|
||||
memcpy(buf + *buflen, *in, bufremain);
|
||||
*in += bufremain;
|
||||
*inlen -= bufremain;
|
||||
*buflen += bufremain;
|
||||
}
|
||||
|
||||
return *inlen & blockmask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the buffer with trailing data from an encryption/decryption that didn't
|
||||
* fit into a full block.
|
||||
*/
|
||||
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen)
|
||||
{
|
||||
if (*inlen == 0)
|
||||
return 1;
|
||||
|
||||
if (*buflen + *inlen > blocksize) {
|
||||
PROVerr(PROV_F_TRAILINGDATA, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf + *buflen, *in, *inlen);
|
||||
*buflen += *inlen;
|
||||
*inlen = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Pad the final block for encryption */
|
||||
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
{
|
||||
size_t i;
|
||||
unsigned char pad = (unsigned char)(blocksize - *buflen);
|
||||
|
||||
for (i = *buflen; i < blocksize; i++)
|
||||
buf[i] = pad;
|
||||
}
|
||||
|
||||
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
{
|
||||
size_t pad, i;
|
||||
size_t len = *buflen;
|
||||
|
||||
if(len != blocksize) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following assumes that the ciphertext has been authenticated.
|
||||
* Otherwise it provides a padding oracle.
|
||||
*/
|
||||
pad = buf[blocksize - 1];
|
||||
if (pad == 0 || pad > blocksize) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < pad; i++) {
|
||||
if (buf[--len] != pad) {
|
||||
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*buflen = len;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
LIBS=../../../libcrypto
|
||||
SOURCE[../../../libcrypto]=\
|
||||
block.c aes.c aes_basic.c
|
||||
INCLUDE[../../../libcrypto]=. ../../../crypto
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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/aes.h>
|
||||
#include <openssl/modes.h>
|
||||
|
||||
typedef struct prov_aes_cipher_st PROV_AES_CIPHER;
|
||||
|
||||
typedef struct prov_aes_key_st {
|
||||
union {
|
||||
double align;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
block128_f block;
|
||||
union {
|
||||
cbc128_f cbc;
|
||||
ctr128_f ctr;
|
||||
} stream;
|
||||
|
||||
/* Platform specific data */
|
||||
union {
|
||||
int dummy;
|
||||
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
|
||||
struct {
|
||||
union {
|
||||
double align;
|
||||
/*-
|
||||
* KM-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-06)
|
||||
*/
|
||||
struct {
|
||||
unsigned char k[32];
|
||||
} km;
|
||||
/* KM-AES parameter block - end */
|
||||
/*-
|
||||
* KMO-AES/KMF-AES parameter block - begin
|
||||
* (see z/Architecture Principles of Operation >= SA22-7832-08)
|
||||
*/
|
||||
struct {
|
||||
unsigned char cv[16];
|
||||
unsigned char k[32];
|
||||
} kmo_kmf;
|
||||
/* KMO-AES/KMF-AES parameter block - end */
|
||||
} param;
|
||||
unsigned int fc;
|
||||
int res;
|
||||
} s390x;
|
||||
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
|
||||
} plat;
|
||||
|
||||
/* The cipher functions we are going to use */
|
||||
const PROV_AES_CIPHER *ciph;
|
||||
|
||||
/* The mode that we are using */
|
||||
int mode;
|
||||
|
||||
/* Set to 1 if we are encrypting or 0 otherwise */
|
||||
int enc;
|
||||
|
||||
unsigned char iv[AES_BLOCK_SIZE];
|
||||
|
||||
/*
|
||||
* num contains the number of bytes of |iv| which are valid for modes that
|
||||
* manage partial blocks themselves.
|
||||
*/
|
||||
size_t num;
|
||||
|
||||
/* Buffer of partial blocks processed via update calls */
|
||||
unsigned char buf[AES_BLOCK_SIZE];
|
||||
|
||||
/* Number of bytes in buf */
|
||||
size_t bufsz;
|
||||
|
||||
uint64_t flags;
|
||||
|
||||
size_t keylen;
|
||||
|
||||
/* Whether padding should be used or not */
|
||||
unsigned int pad : 1;
|
||||
} PROV_AES_KEY;
|
||||
|
||||
struct prov_aes_cipher_st {
|
||||
int (*init)(PROV_AES_KEY *dat, const uint8_t *key, size_t keylen);
|
||||
int (*cipher)(PROV_AES_KEY *dat, uint8_t *out, const uint8_t *in,
|
||||
size_t inl);
|
||||
};
|
||||
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(size_t keylen);
|
||||
const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(size_t keylen);
|
||||
|
||||
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen);
|
||||
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
|
||||
@@ -10,11 +10,30 @@
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static int sha256_final(void *ctx, unsigned char *md, size_t *size)
|
||||
/*
|
||||
* Forward declaration of everything implemented here. This is not strictly
|
||||
* necessary for the compiler, but provides an assurance that the signatures
|
||||
* of the functions in the dispatch table are correct.
|
||||
*/
|
||||
static OSSL_OP_digest_newctx_fn sha256_newctx;
|
||||
#if 0 /* Not defined here */
|
||||
static OSSL_OP_digest_init_fn sha256_init;
|
||||
static OSSL_OP_digest_update_fn sha256_update;
|
||||
#endif
|
||||
static OSSL_OP_digest_final_fn sha256_final;
|
||||
static OSSL_OP_digest_freectx_fn sha256_freectx;
|
||||
static OSSL_OP_digest_dupctx_fn sha256_dupctx;
|
||||
static OSSL_OP_digest_size_fn sha256_size;
|
||||
static OSSL_OP_digest_block_size_fn sha256_size;
|
||||
|
||||
static int sha256_final(void *ctx,
|
||||
unsigned char *md, size_t *mdl, size_t mdsz)
|
||||
{
|
||||
if (SHA256_Final(md, ctx)) {
|
||||
*size = SHA256_DIGEST_LENGTH;
|
||||
if (mdsz >= SHA256_DIGEST_LENGTH
|
||||
&& SHA256_Final(md, ctx)) {
|
||||
*mdl = SHA256_DIGEST_LENGTH;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -55,11 +74,10 @@ static size_t sha256_block_size(void)
|
||||
return SHA256_CBLOCK;
|
||||
}
|
||||
|
||||
extern const OSSL_DISPATCH sha256_functions[];
|
||||
const OSSL_DISPATCH sha256_functions[] = {
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))sha256_newctx },
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))SHA256_Init },
|
||||
{ OSSL_FUNC_DIGEST_UPDDATE, (void (*)(void))SHA256_Update },
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))SHA256_Update },
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))sha256_final },
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))sha256_freectx },
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))sha256_dupctx },
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Digests */
|
||||
extern const OSSL_DISPATCH sha256_functions[];
|
||||
|
||||
/* Ciphers */
|
||||
extern const OSSL_DISPATCH aes256ecb_functions[];
|
||||
extern const OSSL_DISPATCH aes192ecb_functions[];
|
||||
extern const OSSL_DISPATCH aes128ecb_functions[];
|
||||
extern const OSSL_DISPATCH aes256cbc_functions[];
|
||||
extern const OSSL_DISPATCH aes192cbc_functions[];
|
||||
extern const OSSL_DISPATCH aes128cbc_functions[];
|
||||
extern const OSSL_DISPATCH aes256ofb_functions[];
|
||||
extern const OSSL_DISPATCH aes192ofb_functions[];
|
||||
extern const OSSL_DISPATCH aes128ofb_functions[];
|
||||
extern const OSSL_DISPATCH aes256cfb_functions[];
|
||||
extern const OSSL_DISPATCH aes192cfb_functions[];
|
||||
extern const OSSL_DISPATCH aes128cfb_functions[];
|
||||
extern const OSSL_DISPATCH aes256cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aes192cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aes128cfb1_functions[];
|
||||
extern const OSSL_DISPATCH aes256cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aes192cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aes128cfb8_functions[];
|
||||
extern const OSSL_DISPATCH aes256ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes192ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes128ctr_functions[];
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-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
|
||||
*/
|
||||
|
||||
#ifndef HEADER_PROVERR_H
|
||||
# define HEADER_PROVERR_H
|
||||
|
||||
# ifndef HEADER_SYMHACKS_H
|
||||
# include <openssl/symhacks.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
int ERR_load_PROV_strings(void);
|
||||
|
||||
/*
|
||||
* PROV function codes.
|
||||
*/
|
||||
# define PROV_F_AESNI_INIT_KEY 101
|
||||
# define PROV_F_AES_BLOCK_FINAL 102
|
||||
# define PROV_F_AES_BLOCK_UPDATE 103
|
||||
# define PROV_F_AES_CIPHER 104
|
||||
# define PROV_F_AES_CTX_GET_PARAMS 105
|
||||
# define PROV_F_AES_CTX_SET_PARAMS 106
|
||||
# define PROV_F_AES_DINIT 107
|
||||
# define PROV_F_AES_DUPCTX 108
|
||||
# define PROV_F_AES_EINIT 109
|
||||
# define PROV_F_AES_INIT_KEY 110
|
||||
# define PROV_F_AES_STREAM_UPDATE 111
|
||||
# define PROV_F_AES_T4_INIT_KEY 112
|
||||
# define PROV_F_PROV_AES_KEY_GENERIC_INIT 113
|
||||
# define PROV_F_TRAILINGDATA 114
|
||||
# define PROV_F_UNPADBLOCK 100
|
||||
|
||||
/*
|
||||
* PROV reason codes.
|
||||
*/
|
||||
# define PROV_R_AES_KEY_SETUP_FAILED 101
|
||||
# define PROV_R_BAD_DECRYPT 100
|
||||
# define PROV_R_CIPHER_OPERATION_FAILED 102
|
||||
# define PROV_R_FAILED_TO_GET_PARAMETER 103
|
||||
# define PROV_R_FAILED_TO_SET_PARAMETER 104
|
||||
# define PROV_R_INVALID_KEYLEN 105
|
||||
# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
|
||||
# define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-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/err.h>
|
||||
#include "internal/providercommonerr.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA PROV_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AESNI_INIT_KEY, 0), "aesni_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_FINAL, 0), "aes_block_final"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_UPDATE, 0), "aes_block_update"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CIPHER, 0), "aes_cipher"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_GET_PARAMS, 0),
|
||||
"aes_ctx_get_params"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_SET_PARAMS, 0),
|
||||
"aes_ctx_set_params"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DINIT, 0), "aes_dinit"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DUPCTX, 0), "aes_dupctx"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_EINIT, 0), "aes_einit"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_INIT_KEY, 0), "aes_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_STREAM_UPDATE, 0), "aes_stream_update"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_AES_T4_INIT_KEY, 0), "aes_t4_init_key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_PROV_AES_KEY_GENERIC_INIT, 0),
|
||||
"PROV_AES_KEY_generic_init"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_TRAILINGDATA, 0), "trailingdata"},
|
||||
{ERR_PACK(ERR_LIB_PROV, PROV_F_UNPADBLOCK, 0), "unpadblock"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED),
|
||||
"aes key setup failed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
|
||||
"cipher operation failed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GET_PARAMETER),
|
||||
"failed to get parameter"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
|
||||
"failed to set parameter"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEYLEN), "invalid keylen"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
|
||||
"output buffer too small"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
|
||||
"wrong final block length"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ERR_load_PROV_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(PROV_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(PROV_str_functs);
|
||||
ERR_load_strings_const(PROV_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
/* Functions provided by the core */
|
||||
static OSSL_core_get_param_types_fn *c_get_param_types = NULL;
|
||||
@@ -49,13 +50,36 @@ static int deflt_get_params(const OSSL_PROVIDER *prov,
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern const OSSL_DISPATCH sha256_functions[];
|
||||
|
||||
static const OSSL_ALGORITHM deflt_digests[] = {
|
||||
{ "SHA256", "default=yes", sha256_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_ciphers[] = {
|
||||
{ "AES-256-ECB", "default=yes", aes256ecb_functions },
|
||||
{ "AES-192-ECB", "default=yes", aes192ecb_functions },
|
||||
{ "AES-128-ECB", "default=yes", aes128ecb_functions },
|
||||
{ "AES-256-CBC", "default=yes", aes256cbc_functions },
|
||||
{ "AES-192-CBC", "default=yes", aes192cbc_functions },
|
||||
{ "AES-128-CBC", "default=yes", aes128cbc_functions },
|
||||
{ "AES-256-OFB", "default=yes", aes256ofb_functions },
|
||||
{ "AES-192-OFB", "default=yes", aes192ofb_functions },
|
||||
{ "AES-128-OFB", "default=yes", aes128ofb_functions },
|
||||
{ "AES-256-CFB", "default=yes", aes256cfb_functions },
|
||||
{ "AES-192-CFB", "default=yes", aes192cfb_functions },
|
||||
{ "AES-128-CFB", "default=yes", aes128cfb_functions },
|
||||
{ "AES-256-CFB1", "default=yes", aes256cfb1_functions },
|
||||
{ "AES-192-CFB1", "default=yes", aes192cfb1_functions },
|
||||
{ "AES-128-CFB1", "default=yes", aes128cfb1_functions },
|
||||
{ "AES-256-CFB8", "default=yes", aes256cfb8_functions },
|
||||
{ "AES-192-CFB8", "default=yes", aes192cfb8_functions },
|
||||
{ "AES-128-CFB8", "default=yes", aes128cfb8_functions },
|
||||
{ "AES-256-CTR", "default=yes", aes256ctr_functions },
|
||||
{ "AES-192-CTR", "default=yes", aes192ctr_functions },
|
||||
{ "AES-128-CTR", "default=yes", aes128ctr_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
|
||||
int operation_id,
|
||||
int *no_cache)
|
||||
@@ -64,6 +88,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
|
||||
switch (operation_id) {
|
||||
case OSSL_OP_DIGEST:
|
||||
return deflt_digests;
|
||||
case OSSL_OP_CIPHER:
|
||||
return deflt_ciphers;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const OSSL_DISPATCH md2_functions[];
|
||||
const OSSL_DISPATCH md2_functions[] = {
|
||||
{ OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))md2_newctx },
|
||||
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))MD2_Init },
|
||||
{ OSSL_FUNC_DIGEST_UPDDATE, (void (*)(void))MD2_Update },
|
||||
{ OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))MD2_Update },
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))md2_final },
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))md2_freectx },
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))md2_dupctx },
|
||||
|
||||
@@ -211,9 +211,9 @@ int ssl3_get_record(SSL *s)
|
||||
SSL3_BUFFER_get_len(rbuf), 0,
|
||||
num_recs == 0 ? 1 : 0, &n);
|
||||
if (rret <= 0) {
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
if (!BIO_get_ktls_recv(s->rbio))
|
||||
return rret; /* error or non-blocking */
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
switch (errno) {
|
||||
case EBADMSG:
|
||||
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
|
||||
@@ -233,8 +233,8 @@ int ssl3_get_record(SSL *s)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rret;
|
||||
#endif
|
||||
return rret;
|
||||
}
|
||||
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
|
||||
|
||||
|
||||
@@ -5201,6 +5201,11 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen)
|
||||
if (ext->present)
|
||||
num++;
|
||||
}
|
||||
if (num == 0) {
|
||||
*out = NULL;
|
||||
*outlen = 0;
|
||||
return 1;
|
||||
}
|
||||
if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) {
|
||||
SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
|
||||
+154
-8
@@ -18,28 +18,170 @@ static int test_bio_memleak(void)
|
||||
int ok = 0;
|
||||
BIO *bio;
|
||||
BUF_MEM bufmem;
|
||||
const char *str = "BIO test\n";
|
||||
static const char str[] = "BIO test\n";
|
||||
char buf[100];
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (bio == NULL)
|
||||
if (!TEST_ptr(bio))
|
||||
goto finish;
|
||||
bufmem.length = strlen(str) + 1;
|
||||
bufmem.length = sizeof(str);
|
||||
bufmem.data = (char *) str;
|
||||
bufmem.max = bufmem.length;
|
||||
BIO_set_mem_buf(bio, &bufmem, BIO_NOCLOSE);
|
||||
BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
|
||||
|
||||
if (BIO_read(bio, buf, sizeof(buf)) <= 0)
|
||||
goto finish;
|
||||
|
||||
ok = strcmp(buf, str) == 0;
|
||||
if (!TEST_int_eq(BIO_read(bio, buf, sizeof(buf)), sizeof(str)))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(buf, sizeof(str), str, sizeof(str)))
|
||||
goto finish;
|
||||
ok = 1;
|
||||
|
||||
finish:
|
||||
BIO_free(bio);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int test_bio_get_mem(void)
|
||||
{
|
||||
int ok = 0;
|
||||
BIO *bio = NULL;
|
||||
BUF_MEM *bufmem = NULL;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (!TEST_ptr(bio))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
|
||||
goto finish;
|
||||
BIO_get_mem_ptr(bio, &bufmem);
|
||||
if (!TEST_ptr(bufmem))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_set_close(bio, BIO_NOCLOSE), 0))
|
||||
goto finish;
|
||||
BIO_free(bio);
|
||||
bio = NULL;
|
||||
if (!TEST_mem_eq(bufmem->data, bufmem->length, "Hello World\n", 12))
|
||||
goto finish;
|
||||
ok = 1;
|
||||
|
||||
finish:
|
||||
BIO_free(bio);
|
||||
BUF_MEM_free(bufmem);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int test_bio_new_mem_buf(void)
|
||||
{
|
||||
int ok = 0;
|
||||
BIO *bio;
|
||||
BUF_MEM *bufmem;
|
||||
char data[16];
|
||||
|
||||
bio = BIO_new_mem_buf("Hello World\n", 12);
|
||||
if (!TEST_ptr(bio))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 5, "Hello", 5))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
|
||||
goto finish;
|
||||
if (!TEST_int_lt(BIO_write(bio, "test", 4), 0))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 16), 7))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 7, " World\n", 7))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_reset(bio), 0))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
|
||||
goto finish;
|
||||
ok = 1;
|
||||
|
||||
finish:
|
||||
BIO_free(bio);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int test_bio_rdonly_mem_buf(void)
|
||||
{
|
||||
int ok = 0;
|
||||
BIO *bio, *bio2 = NULL;
|
||||
BUF_MEM *bufmem;
|
||||
char data[16];
|
||||
|
||||
bio = BIO_new_mem_buf("Hello World\n", 12);
|
||||
if (!TEST_ptr(bio))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 5, "Hello", 5))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
|
||||
goto finish;
|
||||
(void)BIO_set_close(bio, BIO_NOCLOSE);
|
||||
|
||||
bio2 = BIO_new(BIO_s_mem());
|
||||
if (!TEST_ptr(bio2))
|
||||
goto finish;
|
||||
BIO_set_mem_buf(bio2, bufmem, BIO_CLOSE);
|
||||
BIO_set_flags(bio2, BIO_FLAGS_MEM_RDONLY);
|
||||
|
||||
if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 7, " World\n", 7))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_reset(bio2), 0))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 7, " World\n", 7))
|
||||
goto finish;
|
||||
ok = 1;
|
||||
|
||||
finish:
|
||||
BIO_free(bio);
|
||||
BIO_free(bio2);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int test_bio_rdwr_rdonly(void)
|
||||
{
|
||||
int ok = 0;
|
||||
BIO *bio = NULL;
|
||||
char data[16];
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (!TEST_ptr(bio))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
|
||||
goto finish;
|
||||
|
||||
BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
|
||||
goto finish;
|
||||
if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
|
||||
goto finish;
|
||||
if (!TEST_int_gt(BIO_reset(bio), 0))
|
||||
goto finish;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_MEM_RDONLY);
|
||||
if (!TEST_int_eq(BIO_puts(bio, "Hi!\n"), 4))
|
||||
goto finish;
|
||||
if (!TEST_int_eq(BIO_read(bio, data, 16), 16))
|
||||
goto finish;
|
||||
|
||||
if (!TEST_mem_eq(data, 16, "Hello World\nHi!\n", 16))
|
||||
goto finish;
|
||||
|
||||
ok = 1;
|
||||
|
||||
finish:
|
||||
BIO_free(bio);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
int global_init(void)
|
||||
{
|
||||
CRYPTO_set_mem_debug(1);
|
||||
@@ -50,5 +192,9 @@ int global_init(void)
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_bio_memleak);
|
||||
ADD_TEST(test_bio_get_mem);
|
||||
ADD_TEST(test_bio_new_mem_buf);
|
||||
ADD_TEST(test_bio_rdonly_mem_buf);
|
||||
ADD_TEST(test_bio_rdwr_rdonly);
|
||||
return 1;
|
||||
}
|
||||
@@ -1954,6 +1954,73 @@ static int test_rand(void)
|
||||
return st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run some statistical tests to provide a degree confidence that the
|
||||
* BN_rand_range() function works as expected. The critical value
|
||||
* is computed using the R statistical suite:
|
||||
*
|
||||
* qchisq(alpha, df=iterations - 1)
|
||||
*
|
||||
* where alpha is the significance level (0.95 is used here) and iterations
|
||||
* is the number of samples being drawn.
|
||||
*/
|
||||
static const struct {
|
||||
unsigned int range;
|
||||
unsigned int iterations;
|
||||
double critical;
|
||||
} rand_range_cases[] = {
|
||||
{ 2, 100, 123.2252 /* = qchisq(.95, df=99) */ },
|
||||
{ 12, 1000, 1073.643 /* = qchisq(.95, df=999) */ },
|
||||
{ 1023, 100000, 100735.7 /* = qchisq(.95, df=99999) */ },
|
||||
};
|
||||
|
||||
static int test_rand_range(int n)
|
||||
{
|
||||
const unsigned int range = rand_range_cases[n].range;
|
||||
const unsigned int iterations = rand_range_cases[n].iterations;
|
||||
const double critical = rand_range_cases[n].critical;
|
||||
const double expected = iterations / (double)range;
|
||||
double sum = 0;
|
||||
BIGNUM *rng = NULL, *val = NULL;
|
||||
size_t *counts;
|
||||
unsigned int i, v;
|
||||
int res = 0;
|
||||
|
||||
if (!TEST_ptr(counts = OPENSSL_zalloc(sizeof(*counts) * range))
|
||||
|| !TEST_ptr(rng = BN_new())
|
||||
|| !TEST_ptr(val = BN_new())
|
||||
|| !TEST_true(BN_set_word(rng, range)))
|
||||
goto err;
|
||||
for (i = 0; i < iterations; i++) {
|
||||
if (!TEST_true(BN_rand_range(val, rng))
|
||||
|| !TEST_uint_lt(v = (unsigned int)BN_get_word(val), range))
|
||||
goto err;
|
||||
counts[v]++;
|
||||
}
|
||||
|
||||
TEST_note("range %u iterations %u critical %.4f", range, iterations,
|
||||
critical);
|
||||
if (range < 20) {
|
||||
TEST_note("frequencies (expected %.2f)", expected);
|
||||
for (i = 0; i < range; i++)
|
||||
TEST_note(" %2u %6zu", i, counts[i]);
|
||||
}
|
||||
for (i = 0; i < range; i++) {
|
||||
const double delta = counts[i] - expected;
|
||||
sum += delta * delta;
|
||||
}
|
||||
sum /= expected;
|
||||
TEST_note("test statistic %.4f", sum);
|
||||
|
||||
if (TEST_double_lt(sum, critical))
|
||||
res = 1;
|
||||
err:
|
||||
BN_free(rng);
|
||||
BN_free(val);
|
||||
OPENSSL_free(counts);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int test_negzero(void)
|
||||
{
|
||||
BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL;
|
||||
@@ -2432,6 +2499,7 @@ int setup_tests(void)
|
||||
#endif
|
||||
ADD_ALL_TESTS(test_is_prime, (int)OSSL_NELEM(primes));
|
||||
ADD_ALL_TESTS(test_not_prime, (int)OSSL_NELEM(not_primes));
|
||||
ADD_ALL_TESTS(test_rand_range, OSSL_NELEM(rand_range_cases));
|
||||
} else {
|
||||
ADD_ALL_TESTS(run_file_tests, n);
|
||||
}
|
||||
|
||||
+4
-1
@@ -1884,11 +1884,14 @@ static int check_ec_key_field_public_range_test(int id)
|
||||
* be the same point on the curve). The add is different for char2 fields.
|
||||
*/
|
||||
type = EC_METHOD_get_field_type(meth);
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
if (type == NID_X9_62_characteristic_two_field) {
|
||||
/* test for binary curves */
|
||||
if (!TEST_true(BN_GF2m_add(x, x, field)))
|
||||
goto err;
|
||||
} else if (type == NID_X9_62_prime_field) {
|
||||
} else
|
||||
#endif
|
||||
if (type == NID_X9_62_prime_field) {
|
||||
/* test for prime curves */
|
||||
if (!TEST_true(BN_add(x, x, field)))
|
||||
goto err;
|
||||
|
||||
@@ -253,6 +253,60 @@ static int test_kdf_ss_kmac(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_kdf_sshkdf(void)
|
||||
{
|
||||
int ret;
|
||||
EVP_KDF_CTX *kctx;
|
||||
unsigned char out[8];
|
||||
/* Test data from NIST CAVS 14.1 test vectors */
|
||||
const unsigned char key[] = {
|
||||
0x00, 0x00, 0x00, 0x81, 0x00, 0x87, 0x5c, 0x55, 0x1c, 0xef, 0x52, 0x6a,
|
||||
0x4a, 0x8b, 0xe1, 0xa7, 0xdf, 0x27, 0xe9, 0xed, 0x35, 0x4b, 0xac, 0x9a,
|
||||
0xfb, 0x71, 0xf5, 0x3d, 0xba, 0xe9, 0x05, 0x67, 0x9d, 0x14, 0xf9, 0xfa,
|
||||
0xf2, 0x46, 0x9c, 0x53, 0x45, 0x7c, 0xf8, 0x0a, 0x36, 0x6b, 0xe2, 0x78,
|
||||
0x96, 0x5b, 0xa6, 0x25, 0x52, 0x76, 0xca, 0x2d, 0x9f, 0x4a, 0x97, 0xd2,
|
||||
0x71, 0xf7, 0x1e, 0x50, 0xd8, 0xa9, 0xec, 0x46, 0x25, 0x3a, 0x6a, 0x90,
|
||||
0x6a, 0xc2, 0xc5, 0xe4, 0xf4, 0x8b, 0x27, 0xa6, 0x3c, 0xe0, 0x8d, 0x80,
|
||||
0x39, 0x0a, 0x49, 0x2a, 0xa4, 0x3b, 0xad, 0x9d, 0x88, 0x2c, 0xca, 0xc2,
|
||||
0x3d, 0xac, 0x88, 0xbc, 0xad, 0xa4, 0xb4, 0xd4, 0x26, 0xa3, 0x62, 0x08,
|
||||
0x3d, 0xab, 0x65, 0x69, 0xc5, 0x4c, 0x22, 0x4d, 0xd2, 0xd8, 0x76, 0x43,
|
||||
0xaa, 0x22, 0x76, 0x93, 0xe1, 0x41, 0xad, 0x16, 0x30, 0xce, 0x13, 0x14,
|
||||
0x4e
|
||||
};
|
||||
const unsigned char xcghash[] = {
|
||||
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23,
|
||||
0xb2, 0x74, 0x5e, 0xbc, 0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7,
|
||||
0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
|
||||
};
|
||||
const unsigned char sessid[] = {
|
||||
0x0e, 0x68, 0x3f, 0xc8, 0xa9, 0xed, 0x7c, 0x2f, 0xf0, 0x2d, 0xef, 0x23,
|
||||
0xb2, 0x74, 0x5e, 0xbc, 0x99, 0xb2, 0x67, 0xda, 0xa8, 0x6a, 0x4a, 0xa7,
|
||||
0x69, 0x72, 0x39, 0x08, 0x82, 0x53, 0xf6, 0x42
|
||||
};
|
||||
const unsigned char expected[sizeof(out)] = {
|
||||
0x41, 0xff, 0x2e, 0xad, 0x16, 0x83, 0xf1, 0xe6
|
||||
};
|
||||
|
||||
ret = TEST_ptr(kctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF))
|
||||
&& TEST_int_gt(EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()),
|
||||
0)
|
||||
&& TEST_int_gt(EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, key,
|
||||
sizeof(key)), 0)
|
||||
&& TEST_int_gt(EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH,
|
||||
xcghash, sizeof(xcghash)), 0)
|
||||
&& TEST_int_gt(EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
|
||||
sessid, sizeof(sessid)), 0)
|
||||
&& TEST_int_gt(
|
||||
EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE,
|
||||
(int)EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV),
|
||||
0)
|
||||
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out)), 0)
|
||||
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
|
||||
|
||||
EVP_KDF_CTX_free(kctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_kdf_tls1_prf);
|
||||
@@ -264,5 +318,6 @@ int setup_tests(void)
|
||||
ADD_TEST(test_kdf_ss_hash);
|
||||
ADD_TEST(test_kdf_ss_hmac);
|
||||
ADD_TEST(test_kdf_ss_kmac);
|
||||
ADD_TEST(test_kdf_sshkdf);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use OpenSSL::Test;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_kdf");
|
||||
|
||||
my @kdf_tests = (
|
||||
{ cmd => [qw{openssl kdf -keylen 16 -kdfopt digest:SHA256 -kdfopt secret:secret -kdfopt seed:seed TLS1-PRF}],
|
||||
expected => '8E:4D:93:25:30:D7:65:A0:AA:E9:74:C3:04:73:5E:CC',
|
||||
desc => 'TLS1-PRF SHA256' },
|
||||
{ cmd => [qw{openssl kdf -keylen 16 -kdfopt digest:MD5-SHA1 -kdfopt secret:secret -kdfopt seed:seed TLS1-PRF}],
|
||||
expected => '65:6F:31:CB:04:03:D6:51:E2:E8:71:F8:20:04:AB:BA',
|
||||
desc => 'TLS1-PRF MD5-SHA1' },
|
||||
{ cmd => [qw{openssl kdf -keylen 10 -kdfopt digest:SHA256 -kdfopt key:secret -kdfopt salt:salt -kdfopt info:label HKDF}],
|
||||
expected => '2a:c4:36:9f:52:59:96:f8:de:13',
|
||||
desc => 'HKDF SHA256' },
|
||||
{ cmd => [qw{openssl kdf -keylen 32 -kdfopt digest:SHA256 -kdfopt pass:password -kdfopt salt:salt -kdfopt iter:2 PBKDF2}],
|
||||
expected => 'ae:4d:0c:95:af:6b:46:d3:2d:0a:df:f9:28:f0:6d:d0:2a:30:3f:8e:f3:c2:51:df:d6:e2:d8:5a:95:47:4c:43',
|
||||
desc => 'PBKDF2 SHA256'},
|
||||
{ cmd => [qw{openssl kdf -keylen 64 -kdfopt mac:KMAC128 -kdfopt maclen:20 -kdfopt hexkey:b74a149a161546f8c20b06ac4ed4 -kdfopt hexinfo:348a37a27ef1282f5f020dcc -kdfopt hexsalt:3638271ccd68a25dc24ecddd39ef3f89 SSKDF}],
|
||||
expected => 'e9:c1:84:53:a0:62:b5:3b:db:fc:bb:5a:34:bd:b8:e5:e7:07:ee:bb:5d:d1:34:42:43:d8:cf:c2:c2:e6:33:2f:91:bd:a5:86:f3:7d:e4:8a:65:d4:c5:14:fd:ef:aa:1e:67:54:f3:73:d2:38:e1:95:ae:15:7e:1d:e8:14:98:03',
|
||||
desc => 'SSKDF KMAC128'},
|
||||
{ cmd => [qw{openssl kdf -keylen 16 -kdfopt mac:HMAC -kdfopt digest:SHA256 -kdfopt hexkey:b74a149a161546f8c20b06ac4ed4 -kdfopt hexinfo:348a37a27ef1282f5f020dcc -kdfopt hexsalt:3638271ccd68a25dc24ecddd39ef3f89 SSKDF}],
|
||||
expected => '44:f6:76:e8:5c:1b:1a:8b:bc:3d:31:92:18:63:1c:a3',
|
||||
desc => 'SSKDF HMAC SHA256'},
|
||||
{ cmd => [qw{openssl kdf -keylen 14 -kdfopt digest:SHA224 -kdfopt hexkey:6dbdc23f045488e4062757b06b9ebae183fc5a5946d80db93fec6f62ec07e3727f0126aed12ce4b262f47d48d54287f81d474c7c3b1850e9 -kdfopt hexinfo:a1b2c3d4e54341565369643c832e9849dcdba71e9a3139e606e095de3c264a66e98a165854cd07989b1ee0ec3f8dbe SSKDF}],
|
||||
expected => 'a4:62:de:16:a8:9d:e8:46:6e:f5:46:0b:47:b8',
|
||||
desc => 'SSKDF HASH SHA224'},
|
||||
{ cmd => [qw{openssl kdf -keylen 16 -kdfopt md:SHA256 -kdfopt hexkey:0102030405 -kdfopt hexxcghash:06090A -kdfopt hexsession_id:01020304 -kdfopt type:A SSHKDF}],
|
||||
expected => '5C:49:94:47:3B:B1:53:3A:58:EB:19:42:04:D3:78:16',
|
||||
desc => 'SSHKDF SHA256'},
|
||||
);
|
||||
|
||||
my @scrypt_tests = (
|
||||
{ cmd => [qw{openssl kdf -keylen 64 -kdfopt pass:password -kdfopt salt:NaCl -kdfopt N:1024 -kdfopt r:8 -kdfopt p:16 -kdfopt maxmem_bytes:10485760 id-scrypt}],
|
||||
expected => 'fd:ba:be:1c:9d:34:72:00:78:56:e7:19:0d:01:e9:fe:7c:6a:d7:cb:c8:23:78:30:e7:73:76:63:4b:37:31:62:2e:af:30:d9:2e:22:a3:88:6f:f1:09:27:9d:98:30:da:c7:27:af:b9:4a:83:ee:6d:83:60:cb:df:a2:cc:06:40',
|
||||
desc => 'SCRYPT' },
|
||||
);
|
||||
|
||||
push @kdf_tests, @scrypt_tests unless disabled("scrypt");
|
||||
|
||||
plan tests => scalar @kdf_tests;
|
||||
|
||||
foreach (@kdf_tests) {
|
||||
ok(compareline($_->{cmd}, $_->{expected}), $_->{desc});
|
||||
}
|
||||
|
||||
# Check that the stdout output matches the expected value.
|
||||
sub compareline {
|
||||
my ($cmdarray, $expect) = @_;
|
||||
if (defined($expect)) {
|
||||
$expect = uc $expect;
|
||||
}
|
||||
|
||||
my @lines = run(app($cmdarray), capture => 1);
|
||||
|
||||
if (defined($expect)) {
|
||||
if ($lines[0] =~ m|^\Q${expect}\E\R$|) {
|
||||
return 1;
|
||||
} else {
|
||||
print "Got: $lines[0]";
|
||||
print "Exp: $expect\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2388,14 +2388,41 @@ Operation = ENCRYPT
|
||||
Plaintext = B41E6BE2EBA84A148E2EED84593C5EC7
|
||||
Ciphertext = 9B9B7BFCD1813CB95D0B3618F40F5122
|
||||
|
||||
Title = Chacha20
|
||||
Title = Chacha20 test vectors from RFC7539
|
||||
|
||||
# A.1 Test Vector 1
|
||||
Cipher = chacha20
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
IV = 00000000000000000000000000000000
|
||||
Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
Ciphertext = 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586
|
||||
|
||||
# A.1 Test Vector 2
|
||||
Cipher = chacha20
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000000
|
||||
IV = 01000000000000000000000000000000
|
||||
Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
Ciphertext = 9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f
|
||||
|
||||
# A.2 Test Vector 1 is the same as A.1 Test Vector 1
|
||||
# A.2 Test Vector 2
|
||||
Cipher = chacha20
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000001
|
||||
#Counter (first 4 bytes) expressed in little-endian order
|
||||
IV = 01000000000000000000000000000002
|
||||
Plaintext = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
|
||||
Ciphertext = a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221
|
||||
|
||||
# A.2 Test Vector 3
|
||||
Cipher = chacha20
|
||||
Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
|
||||
#Counter (first 4 bytes) expressed in little-endian order
|
||||
IV = 2a000000000000000000000000000002
|
||||
Plaintext = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
|
||||
Ciphertext = 62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1
|
||||
|
||||
Title = Chacha20
|
||||
|
||||
Cipher = chacha20
|
||||
Key = 0000000000000000000000000000000000000000000000000000000000000001
|
||||
IV = 00000000000000000000000000000000
|
||||
|
||||
+2
-1
@@ -72,7 +72,8 @@ if ( $internal ) {
|
||||
die "Extra parameters given.\n" if @ARGV;
|
||||
$config = "crypto/err/openssl.ec" unless defined $config;
|
||||
@source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
|
||||
glob('ssl/*.c'), glob('ssl/*/*.c') );
|
||||
glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'),
|
||||
glob('providers/*/*.c'), glob('providers/*/*/*.c') );
|
||||
} else {
|
||||
die "Configuration file not given.\nSee '$0 -help' for information\n"
|
||||
unless defined $config;
|
||||
|
||||
+5
-1
@@ -4796,4 +4796,8 @@ EVP_MD_fetch 4743 3_0_0 EXIST::FUNCTION:
|
||||
EVP_set_default_properties 4744 3_0_0 EXIST::FUNCTION:
|
||||
OSSL_PARAM_construct_end 4745 3_0_0 EXIST::FUNCTION:
|
||||
EC_GROUP_check_named_curve 4746 3_0_0 EXIST::FUNCTION:EC
|
||||
EVP_chacha20_poly1305_draft 4747 3_0_0 EXIST::FUNCTION:CHACHA,POLY1305
|
||||
EVP_CIPHER_upref 4747 3_0_0 EXIST::FUNCTION:
|
||||
EVP_CIPHER_fetch 4748 3_0_0 EXIST::FUNCTION:
|
||||
EVP_CIPHER_mode 4749 3_0_0 EXIST::FUNCTION:
|
||||
OPENSSL_info 4750 3_0_0 EXIST::FUNCTION:
|
||||
EVP_chacha20_poly1305_draft 4751 3_0_0 EXIST::FUNCTION:CHACHA,POLY1305
|
||||
+2
-1
@@ -114,7 +114,8 @@ if ( $internal ) {
|
||||
die "Cannot mix -internal and -static\n" if $static;
|
||||
die "Extra parameters given.\n" if @ARGV;
|
||||
@source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
|
||||
glob('ssl/*.c'), glob('ssl/*/*.c') );
|
||||
glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'),
|
||||
glob('providers/*/*.c'), glob('providers/*/*/*.c') );
|
||||
} else {
|
||||
die "-module isn't useful without -internal\n" if scalar keys %modules > 0;
|
||||
@source = @ARGV;
|
||||
|
||||
Reference in New Issue
Block a user