Latest update

This commit is contained in:
2019-02-22 12:53:31 +09:00
parent 6523a76e2e
commit 25fbda8e8b
186 changed files with 9758 additions and 1640 deletions
+33
View File
@@ -9,6 +9,26 @@
Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
*) Added property based algorithm implementation selection framework to
the core.
[Paul Dale]
*) Added SCA hardening for modular field inversion in EC_GROUP through
a new dedicated field_inv() pointer in EC_METHOD.
This also addresses a leakage affecting conversions from projective
to affine coordinates.
[Billy Bob Brumley, Nicola Tuveri]
*) Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF
implementations. This includes an EVP_PKEY to EVP_KDF bridge for
those algorithms that were already supported through the EVP_PKEY API
(scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2
and scrypt are now wrappers that call EVP_KDF.
[David Makepeace]
*) Build devcrypto engine as a dynamic engine.
[Eneas U de Queiroz]
*) Add keyed BLAKE2 to EVP_MAC.
[Antoine Salon]
@@ -109,6 +129,19 @@
applications with zero-copy system calls such as sendfile and splice.
[Boris Pismenny]
Changes between 1.1.1a and 1.1.1b [xx XXX xxxx]
*) Change the info callback signals for the start and end of a post-handshake
message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START
and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get
confused by this and assume that a TLSv1.2 renegotiation has started. This
can break KeyUpdate handling. Instead we no longer signal the start and end
of a post handshake message exchange (although the messages themselves are
still signalled). This could break some applications that were expecting
the old signals. However without this KeyUpdate is not usable for many
applications.
[Matt Caswell]
Changes between 1.1.1 and 1.1.1a [20 Nov 2018]
*) Timing vulnerability in DSA signature generation
+1 -1
View File
@@ -1098,7 +1098,7 @@ my %targets = (
dso_scheme => "dlfcn",
shared_target => "aix",
module_ldflags => "-Wl,-G,-bsymbolic,-bexpall",
shared_ldflag => "-Wl,-G,-bsymbolic",
shared_ldflag => "-Wl,-G,-bsymbolic,-bnoentry",
shared_defflag => "-Wl,-bE:",
perl_platform => 'AIX',
},
+2 -2
View File
@@ -622,7 +622,7 @@ install_runtime_libs: build_libs
: {- output_off() unless windowsdll(); "" -}; \
$(ECHO) "install $$s -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
cp $$s $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
chmod 644 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \
$(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
: {- output_on() unless windowsdll(); "" -}{- output_off() if windowsdll(); "" -}; \
@@ -721,7 +721,7 @@ generate: generate_apps generate_crypto_bn generate_crypto_objects \
generate_crypto_conf generate_crypto_asn1 generate_fuzz_oids
.PHONY: doc-nits
doc-nits:
doc-nits: build_generated
(cd $(SRCDIR); $(PERL) util/find-doc-nits -n -p ) >doc-nits
@if [ -s doc-nits ] ; then cat doc-nits ; exit 1; \
else echo 'doc-nits: no errors.'; rm doc-nits ; fi
+19 -20
View File
@@ -145,6 +145,8 @@ my $gcc_devteam_warn = "-DDEBUG_UNUSED"
# -Wlanguage-extension-token -- no, we use asm()
# -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
# -Wextended-offsetof -- no, needed in CMS ASN1 code
# -Wunused-function -- no, it forces header use of safestack et al
# DEFINE macros
my $clang_devteam_warn = ""
. " -Wswitch-default"
. " -Wno-parentheses-equality"
@@ -154,6 +156,7 @@ my $clang_devteam_warn = ""
. " -Wincompatible-pointer-types-discards-qualifiers"
. " -Wmissing-variable-declarations"
. " -Wno-unknown-warning-option"
. " -Wno-unused-function"
;
# This adds backtrace information to the memory leak info. Is only used
@@ -749,7 +752,11 @@ while (@argvcopy)
}
elsif (/^--strict-warnings$/)
{
$strict_warnings = 1;
# Pretend that our strict flags is a C flag, and replace it
# with the proper flags later on
push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
push @{$useradd{CXXFLAGS}}, '--ossl-strict-warnings';
$strict_warnings=1;
}
elsif (/^--debug$/)
{
@@ -1500,6 +1507,7 @@ $config{openssl_api_defines} = [
"OPENSSL_MIN_API=".($apitable->{$config{api} // ""} // -1)
];
my @strict_warnings_collection=();
if ($strict_warnings)
{
my $wopt;
@@ -1507,26 +1515,17 @@ if ($strict_warnings)
die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike"
unless $gccver >= 4;
foreach $wopt (split /\s+/, $gcc_devteam_warn)
{
push @{$config{cflags}}, $wopt
unless grep { $_ eq $wopt } @{$config{cflags}};
push @{$config{cxxflags}}, $wopt
if ($config{CXX}
&& !grep { $_ eq $wopt } @{$config{cxxflags}});
}
if (defined($predefined{__clang__}))
{
foreach $wopt (split /\s+/, $clang_devteam_warn)
{
push @{$config{cflags}}, $wopt
unless grep { $_ eq $wopt } @{$config{cflags}};
push @{$config{cxxflags}}, $wopt
if ($config{CXX}
&& !grep { $_ eq $wopt } @{$config{cxxflags}});
}
}
push @strict_warnings_collection, (split /\s+/, $gcc_devteam_warn);
push @strict_warnings_collection, (split /\s+/, $clang_devteam_warn)
if (defined($predefined{__clang__}));
}
foreach (qw(CFLAGS CXXFLAGS))
{
$useradd{$_} = [ map { $_ eq '--ossl-strict-warnings'
? @strict_warnings_collection
: ( $_ ) }
@{$useradd{$_}} ];
}
unless ($disabled{"crypto-mdebug-backtrace"})
{
+2 -2
View File
@@ -15,12 +15,12 @@
IF[{- !$disabled{apps} -}]
LIBS{noinst}=libapps.a
SOURCE[libapps.a]={- join(" ", @apps_lib_src) -}
INCLUDE[libapps.a]=.. ../include
INCLUDE[libapps.a]=.. ../include include
PROGRAMS=openssl
SOURCE[openssl]={- join(" ", @apps_init_src) -}
SOURCE[openssl]={- join(" ", @apps_openssl_src) -}
INCLUDE[openssl]=.. ../include
INCLUDE[openssl]=.. ../include include
DEPEND[openssl]=libapps.a ../libssl
IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-)/ -}]
View File
View File
View File
+2 -2
View File
@@ -24,7 +24,7 @@
#define COOKIE_SECRET_LENGTH 16
VERIFY_CB_ARGS verify_args = { 0, 0, X509_V_OK, 0 };
VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 };
#ifndef OPENSSL_NO_SOCK
static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
@@ -63,7 +63,7 @@ int verify_callback(int ok, X509_STORE_CTX *ctx)
if (!ok) {
BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
X509_verify_cert_error_string(err));
if (verify_args.depth >= depth) {
if (verify_args.depth < 0 || verify_args.depth >= depth) {
if (!verify_args.return_error)
ok = 1;
verify_args.error = err;
+73 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
@@ -75,6 +75,7 @@ static int ocsp_resp_cb(SSL *s, void *arg);
#endif
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
static char *base64encode (const void *buf, size_t len);
static int is_dNS_name(const char *host);
static int saved_errno;
@@ -1138,6 +1139,7 @@ int s_client_main(int argc, char **argv)
goto opthelp;
break;
case OPT_VERIFY_RET_ERROR:
verify = SSL_VERIFY_PEER;
verify_args.return_error = 1;
break;
case OPT_VERIFY_QUIET:
@@ -2012,9 +2014,11 @@ int s_client_main(int argc, char **argv)
SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV);
if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
if (servername == NULL)
servername = (host == NULL) ? "localhost" : host;
if (!SSL_set_tlsext_host_name(con, servername)) {
if (servername == NULL) {
if(host == NULL || is_dNS_name(host))
servername = (host == NULL) ? "localhost" : host;
}
if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) {
BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
ERR_print_errors(bio_err);
goto end;
@@ -3553,4 +3557,69 @@ static char *base64encode (const void *buf, size_t len)
return out;
}
/*
* Host dNS Name verifier: used for checking that the hostname is in dNS format
* before setting it as SNI
*/
static int is_dNS_name(const char *host)
{
const size_t MAX_LABEL_LENGTH = 63;
size_t i;
int isdnsname = 0;
size_t length = strlen(host);
size_t label_length = 0;
int all_numeric = 1;
/*
* Deviation from strict DNS name syntax, also check names with '_'
* Check DNS name syntax, any '-' or '.' must be internal,
* and on either side of each '.' we can't have a '-' or '.'.
*
* If the name has just one label, we don't consider it a DNS name.
*/
for (i = 0; i < length && label_length < MAX_LABEL_LENGTH; ++i) {
char c = host[i];
if ((c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| c == '_') {
label_length += 1;
all_numeric = 0;
continue;
}
if (c >= '0' && c <= '9') {
label_length += 1;
continue;
}
/* Dot and hyphen cannot be first or last. */
if (i > 0 && i < length - 1) {
if (c == '-') {
label_length += 1;
continue;
}
/*
* Next to a dot the preceding and following characters must not be
* another dot or a hyphen. Otherwise, record that the name is
* plausible, since it has two or more labels.
*/
if (c == '.'
&& host[i + 1] != '.'
&& host[i - 1] != '-'
&& host[i + 1] != '-') {
label_length = 0;
isdnsname = 1;
continue;
}
}
isdnsname = 0;
break;
}
/* dNS name must not be all numeric and labels must be shorter than 64 characters. */
isdnsname &= !all_numeric && !(label_length == MAX_LABEL_LENGTH);
return isdnsname;
}
#endif /* OPENSSL_NO_SOCK */
+155
View File
@@ -0,0 +1,155 @@
The sparse_array.c file contains an implementation of a sparse array that
attempts to be both space and time efficient.
The sparse array is represented using a tree structure. Each node in the
tree contains a block of pointers to either the user supplied leaf values or
to another node.
There are a number of parameters used to define the block size:
OPENSSL_SA_BLOCK_BITS Specifies the number of bits covered by each block
SA_BLOCK_MAX Specifies the number of pointers in each block
SA_BLOCK_MASK Specifies a bit mask to perform modulo block size
SA_BLOCK_MAX_LEVELS Indicates the maximum possible height of the tree
These constants are inter-related:
SA_BLOCK_MAX = 2 ^ OPENSSL_SA_BLOCK_BITS
SA_BLOCK_MASK = SA_BLOCK_MAX - 1
SA_BLOCK_MAX_LEVELS = number of bits in size_t divided by
OPENSSL_SA_BLOCK_BITS rounded up to the next multiple
of OPENSSL_SA_BLOCK_BITS
OPENSSL_SA_BLOCK_BITS can be defined at compile time and this overrides the
built in setting.
As a space and performance optimisation, the height of the tree is usually
less than the maximum possible height. Only sufficient height is allocated to
accommodate the largest index added to the data structure.
The largest index used to add a value to the array determines the tree height:
+----------------------+---------------------+
| Largest Added Index | Height of Tree |
+----------------------+---------------------+
| SA_BLOCK_MAX - 1 | 1 |
| SA_BLOCK_MAX ^ 2 - 1 | 2 |
| SA_BLOCK_MAX ^ 3 - 1 | 3 |
| ... | ... |
| size_t max | SA_BLOCK_MAX_LEVELS |
+----------------------+---------------------+
The tree height is dynamically increased as needed based on additions.
An empty tree is represented by a NULL root pointer. Inserting a value at
index 0 results in the allocation of a top level node full of null pointers
except for the single pointer to the user's data (N = SA_BLOCK_MAX for
breviety):
+----+
|Root|
|Node|
+-+--+
|
|
|
v
+-+-+---+---+---+---+
| 0 | 1 | 2 |...|N-1|
| |nil|nil|...|nil|
+-+-+---+---+---+---+
|
|
|
v
+-+--+
|User|
|Data|
+----+
Index 0
Inserting at element 2N+1 creates a new root node and pushes down the old root
node. It then creates a second second level node to hold the pointer to the
user's new data:
+----+
|Root|
|Node|
+-+--+
|
|
|
v
+-+-+---+---+---+---+
| 0 | 1 | 2 |...|N-1|
| |nil| |...|nil|
+-+-+---+-+-+---+---+
| |
| +------------------+
| |
v v
+-+-+---+---+---+---+ +-+-+---+---+---+---+
| 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1|
|nil| |nil|...|nil| |nil| |nil|...|nil|
+-+-+---+---+---+---+ +---+-+-+---+---+---+
| |
| |
| |
v v
+-+--+ +-+--+
|User| |User|
|Data| |Data|
+----+ +----+
Index 0 Index 2N+1
The nodes themselves are allocated in a sparse manner. Only nodes which exist
along a path from the root of the tree to an added leaf will be allocated.
The complexity is hidden and nodes are allocated on an as needed basis.
Because the data is expected to be sparse this doesn't result in a large waste
of space.
Values can be removed from the sparse array by setting their index position to
NULL. The data structure does not attempt to reclaim nodes or reduce the
height of the tree on removal. For example, now setting index 0 to NULL would
result in:
+----+
|Root|
|Node|
+-+--+
|
|
|
v
+-+-+---+---+---+---+
| 0 | 1 | 2 |...|N-1|
| |nil| |...|nil|
+-+-+---+-+-+---+---+
| |
| +------------------+
| |
v v
+-+-+---+---+---+---+ +-+-+---+---+---+---+
| 0 | 1 | 2 |...|N-1| | 0 | 1 | 2 |...|N-1|
|nil|nil|nil|...|nil| |nil| |nil|...|nil|
+---+---+---+---+---+ +---+-+-+---+---+---+
|
|
|
v
+-+--+
|User|
|Data|
+----+
Index 2N+1
Accesses to elements in the sparse array take O(log n) time where n is the
largest element. The base of the logarithm is SA_BLOCK_MAX, so for moderately
small indices (e.g. NIDs), single level (constant time) access is achievable.
Space usage is O(minimum(m, n log(n)) where m is the number of elements in the
array.
Note: sparse arrays only include pointers to types. Thus, SPARSE_ARRAY_OF(char)
can be used to store a string.
+2 -1
View File
@@ -76,7 +76,6 @@ $code=<<___;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
#endif
.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
.thumb
@@ -85,6 +84,8 @@ $code=<<___;
#undef __thumb2__
#endif
.text
.type AES_Te,%object
.align 5
AES_Te:
+85 -49
View File
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
# Copyright 2010-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
@@ -34,6 +34,11 @@
# instead, code path is chosen upon pre-process time, pass -mips32r2
# or/and -msmartmips.
# February 2019
#
# Normalize MIPS32R2 AES table address calculation by always using EXT
# instruction. This reduces the standard codebase by another 10%.
######################################################################
# There is a number of MIPS ABI in use, O32 and N32/64 are most
# widely used. Then there is a new contender: NUBI. It appears that if
@@ -223,6 +228,33 @@ _mips_AES_encrypt:
ext $i0,$s1,16,8
_xtr $i0,$s1,16-2
#else
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
move $i0,$Tbl
move $i1,$Tbl
move $i2,$Tbl
move $i3,$Tbl
ext $t0,$s1,16,8
.Loop_enc:
ext $t1,$s2,16,8
ext $t2,$s3,16,8
ext $t3,$s0,16,8
$PTR_INS $i0,$t0,2,8
$PTR_INS $i1,$t1,2,8
$PTR_INS $i2,$t2,2,8
$PTR_INS $i3,$t3,2,8
lw $t0,0($i0) # Te1[s1>>16]
ext $t4,$s2,8,8
lw $t1,0($i1) # Te1[s2>>16]
ext $t5,$s3,8,8
lw $t2,0($i2) # Te1[s3>>16]
ext $t6,$s0,8,8
lw $t3,0($i3) # Te1[s0>>16]
ext $t7,$s1,8,8
$PTR_INS $i0,$t4,2,8
$PTR_INS $i1,$t5,2,8
$PTR_INS $i2,$t6,2,8
$PTR_INS $i3,$t7,2,8
#else
_xtr $i0,$s1,16-2
.Loop_enc:
@@ -237,16 +269,6 @@ _mips_AES_encrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
lw $t0,0($i0) # Te1[s1>>16]
_xtr $i0,$s2,8-2
lw $t1,0($i1) # Te1[s2>>16]
_xtr $i1,$s3,8-2
lw $t2,0($i2) # Te1[s3>>16]
_xtr $i2,$s0,8-2
lw $t3,0($i3) # Te1[s0>>16]
_xtr $i3,$s1,8-2
#else
lwl $t0,3($i0) # Te1[s1>>16]
lwl $t1,3($i1) # Te1[s2>>16]
lwl $t2,3($i2) # Te1[s3>>16]
@@ -259,7 +281,6 @@ _mips_AES_encrypt:
_xtr $i2,$s0,8-2
lwr $t3,2($i3) # Te1[s0>>16]
_xtr $i3,$s1,8-2
#endif
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
@@ -268,6 +289,7 @@ _mips_AES_encrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
#endif
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
rotr $t0,$t0,8
rotr $t1,$t1,8
@@ -275,22 +297,18 @@ _mips_AES_encrypt:
rotr $t3,$t3,8
# if defined(_MIPSEL)
lw $t4,0($i0) # Te2[s2>>8]
_xtr $i0,$s3,0-2
ext $t8,$s3,0,8
lw $t5,0($i1) # Te2[s3>>8]
_xtr $i1,$s0,0-2
ext $t9,$s0,0,8
lw $t6,0($i2) # Te2[s0>>8]
_xtr $i2,$s1,0-2
ext $t10,$s1,0,8
lw $t7,0($i3) # Te2[s1>>8]
_xtr $i3,$s2,0-2
ext $t11,$s2,0,8
$PTR_INS $i0,$t8,2,8
$PTR_INS $i1,$t9,2,8
$PTR_INS $i2,$t10,2,8
$PTR_INS $i3,$t11,2,8
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
and $i3,0x3fc
$PTR_ADD $i0,$Tbl
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
lw $t8,0($i0) # Te3[s3]
$PTR_INS $i0,$s0,2,8
lw $t9,0($i1) # Te3[s0]
@@ -411,6 +429,9 @@ _mips_AES_encrypt:
xor $s3,$t3
.set noreorder
bnez $cnt,.Loop_enc
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
ext $t0,$s1,16,8
#endif
_xtr $i0,$s1,16-2
#endif
@@ -811,6 +832,33 @@ _mips_AES_decrypt:
ext $i0,$s3,16,8
_xtr $i0,$s3,16-2
#else
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
move $i0,$Tbl
move $i1,$Tbl
move $i2,$Tbl
move $i3,$Tbl
ext $t0,$s3,16,8
.Loop_dec:
ext $t1,$s0,16,8
ext $t2,$s1,16,8
ext $t3,$s2,16,8
$PTR_INS $i0,$t0,2,8
$PTR_INS $i1,$t1,2,8
$PTR_INS $i2,$t2,2,8
$PTR_INS $i3,$t3,2,8
lw $t0,0($i0) # Td1[s3>>16]
ext $t4,$s2,8,8
lw $t1,0($i1) # Td1[s0>>16]
ext $t5,$s3,8,8
lw $t2,0($i2) # Td1[s1>>16]
ext $t6,$s0,8,8
lw $t3,0($i3) # Td1[s2>>16]
ext $t7,$s1,8,8
$PTR_INS $i0,$t4,2,8
$PTR_INS $i1,$t5,2,8
$PTR_INS $i2,$t6,2,8
$PTR_INS $i3,$t7,2,8
#else
_xtr $i0,$s3,16-2
.Loop_dec:
@@ -825,16 +873,6 @@ _mips_AES_decrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
lw $t0,0($i0) # Td1[s3>>16]
_xtr $i0,$s2,8-2
lw $t1,0($i1) # Td1[s0>>16]
_xtr $i1,$s3,8-2
lw $t2,0($i2) # Td1[s1>>16]
_xtr $i2,$s0,8-2
lw $t3,0($i3) # Td1[s2>>16]
_xtr $i3,$s1,8-2
#else
lwl $t0,3($i0) # Td1[s3>>16]
lwl $t1,3($i1) # Td1[s0>>16]
lwl $t2,3($i2) # Td1[s1>>16]
@@ -847,8 +885,6 @@ _mips_AES_decrypt:
_xtr $i2,$s0,8-2
lwr $t3,2($i3) # Td1[s2>>16]
_xtr $i3,$s1,8-2
#endif
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
@@ -857,6 +893,7 @@ _mips_AES_decrypt:
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
#endif
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
rotr $t0,$t0,8
rotr $t1,$t1,8
@@ -864,22 +901,17 @@ _mips_AES_decrypt:
rotr $t3,$t3,8
# if defined(_MIPSEL)
lw $t4,0($i0) # Td2[s2>>8]
_xtr $i0,$s1,0-2
ext $t8,$s1,0,8
lw $t5,0($i1) # Td2[s3>>8]
_xtr $i1,$s2,0-2
ext $t9,$s2,0,8
lw $t6,0($i2) # Td2[s0>>8]
_xtr $i2,$s3,0-2
ext $t10,$s3,0,8
lw $t7,0($i3) # Td2[s1>>8]
_xtr $i3,$s0,0-2
and $i0,0x3fc
and $i1,0x3fc
and $i2,0x3fc
and $i3,0x3fc
$PTR_ADD $i0,$Tbl
$PTR_ADD $i1,$Tbl
$PTR_ADD $i2,$Tbl
$PTR_ADD $i3,$Tbl
ext $t11,$s0,0,8
$PTR_INS $i0,$t8,2,8
$PTR_INS $i1,$t9,2,8
$PTR_INS $i2,$t10,2,8
$PTR_INS $i3,$t11,2,8
lw $t8,0($i0) # Td3[s1]
$PTR_INS $i0,$s0,2,8
lw $t9,0($i1) # Td3[s2]
@@ -1001,6 +1033,10 @@ _mips_AES_decrypt:
xor $s3,$t3
.set noreorder
bnez $cnt,.Loop_dec
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
ext $t0,$s3,16,8
#endif
_xtr $i0,$s3,16-2
#endif
+16 -2
View File
@@ -554,6 +554,7 @@ $code.=<<___;
.type _x86_64_AES_encrypt_compact,\@abi-omnipotent
.align 16
_x86_64_AES_encrypt_compact:
.cfi_startproc
lea 128($sbox),$inp # size optimization
mov 0-128($inp),$acc1 # prefetch Te4
mov 32-128($inp),$acc2
@@ -587,6 +588,7 @@ $code.=<<___;
xor 8($key),$s2
xor 12($key),$s3
.byte 0xf3,0xc3 # rep ret
.cfi_endproc
.size _x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact
___
@@ -1161,6 +1163,7 @@ $code.=<<___;
.type _x86_64_AES_decrypt_compact,\@abi-omnipotent
.align 16
_x86_64_AES_decrypt_compact:
.cfi_startproc
lea 128($sbox),$inp # size optimization
mov 0-128($inp),$acc1 # prefetch Td4
mov 32-128($inp),$acc2
@@ -1203,6 +1206,7 @@ $code.=<<___;
xor 8($key),$s2
xor 12($key),$s3
.byte 0xf3,0xc3 # rep ret
.cfi_endproc
.size _x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact
___
@@ -1365,6 +1369,7 @@ AES_set_encrypt_key:
.type _x86_64_AES_set_encrypt_key,\@abi-omnipotent
.align 16
_x86_64_AES_set_encrypt_key:
.cfi_startproc
mov %esi,%ecx # %ecx=bits
mov %rdi,%rsi # %rsi=userKey
mov %rdx,%rdi # %rdi=key
@@ -1546,6 +1551,7 @@ $code.=<<___;
mov \$-1,%rax
.Lexit:
.byte 0xf3,0xc3 # rep ret
.cfi_endproc
.size _x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key
___
@@ -1728,7 +1734,9 @@ AES_cbc_encrypt:
cmp \$0,%rdx # check length
je .Lcbc_epilogue
pushfq
.cfi_push 49 # %rflags
# This could be .cfi_push 49, but libunwind fails on registers it does not
# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087.
.cfi_adjust_cfa_offset 8
push %rbx
.cfi_push %rbx
push %rbp
@@ -1751,6 +1759,7 @@ AES_cbc_encrypt:
cmp \$0,%r9
cmoveq %r10,$sbox
.cfi_remember_state
mov OPENSSL_ia32cap_P(%rip),%r10d
cmp \$$speed_limit,%rdx
jb .Lcbc_slow_prologue
@@ -1986,6 +1995,7 @@ AES_cbc_encrypt:
#--------------------------- SLOW ROUTINE ---------------------------#
.align 16
.Lcbc_slow_prologue:
.cfi_restore_state
# allocate aligned stack frame...
lea -88(%rsp),%rbp
and \$-64,%rbp
@@ -1997,8 +2007,10 @@ AES_cbc_encrypt:
sub %r10,%rbp
xchg %rsp,%rbp
.cfi_def_cfa_register %rbp
#add \$8,%rsp # reserve for return address!
mov %rbp,$_rsp # save %rsp
.cfi_cfa_expression $_rsp,deref,+64
.Lcbc_slow_body:
#mov %rdi,$_inp # save copy of inp
#mov %rsi,$_out # save copy of out
@@ -2187,7 +2199,9 @@ AES_cbc_encrypt:
.cfi_def_cfa %rsp,16
.Lcbc_popfq:
popfq
.cfi_pop 49 # %rflags
# This could be .cfi_pop 49, but libunwind fails on registers it does not
# recognize. See https://bugzilla.redhat.com/show_bug.cgi?id=217087.
.cfi_adjust_cfa_offset -8
.Lcbc_epilogue:
ret
.cfi_endproc
+16
View File
@@ -274,6 +274,7 @@ $code.=<<___;
.type ${PREFIX}_encrypt,\@abi-omnipotent
.align 16
${PREFIX}_encrypt:
.cfi_startproc
movups ($inp),$inout0 # load input
mov 240($key),$rounds # key->rounds
___
@@ -284,12 +285,14 @@ $code.=<<___;
movups $inout0,($out) # output
pxor $inout0,$inout0
ret
.cfi_endproc
.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
.globl ${PREFIX}_decrypt
.type ${PREFIX}_decrypt,\@abi-omnipotent
.align 16
${PREFIX}_decrypt:
.cfi_startproc
movups ($inp),$inout0 # load input
mov 240($key),$rounds # key->rounds
___
@@ -300,6 +303,7 @@ $code.=<<___;
movups $inout0,($out) # output
pxor $inout0,$inout0
ret
.cfi_endproc
.size ${PREFIX}_decrypt, .-${PREFIX}_decrypt
___
}
@@ -325,6 +329,7 @@ $code.=<<___;
.type _aesni_${dir}rypt2,\@abi-omnipotent
.align 16
_aesni_${dir}rypt2:
.cfi_startproc
$movkey ($key),$rndkey0
shl \$4,$rounds
$movkey 16($key),$rndkey1
@@ -350,6 +355,7 @@ _aesni_${dir}rypt2:
aes${dir}last $rndkey0,$inout0
aes${dir}last $rndkey0,$inout1
ret
.cfi_endproc
.size _aesni_${dir}rypt2,.-_aesni_${dir}rypt2
___
}
@@ -361,6 +367,7 @@ $code.=<<___;
.type _aesni_${dir}rypt3,\@abi-omnipotent
.align 16
_aesni_${dir}rypt3:
.cfi_startproc
$movkey ($key),$rndkey0
shl \$4,$rounds
$movkey 16($key),$rndkey1
@@ -391,6 +398,7 @@ _aesni_${dir}rypt3:
aes${dir}last $rndkey0,$inout1
aes${dir}last $rndkey0,$inout2
ret
.cfi_endproc
.size _aesni_${dir}rypt3,.-_aesni_${dir}rypt3
___
}
@@ -406,6 +414,7 @@ $code.=<<___;
.type _aesni_${dir}rypt4,\@abi-omnipotent
.align 16
_aesni_${dir}rypt4:
.cfi_startproc
$movkey ($key),$rndkey0
shl \$4,$rounds
$movkey 16($key),$rndkey1
@@ -442,6 +451,7 @@ _aesni_${dir}rypt4:
aes${dir}last $rndkey0,$inout2
aes${dir}last $rndkey0,$inout3
ret
.cfi_endproc
.size _aesni_${dir}rypt4,.-_aesni_${dir}rypt4
___
}
@@ -453,6 +463,7 @@ $code.=<<___;
.type _aesni_${dir}rypt6,\@abi-omnipotent
.align 16
_aesni_${dir}rypt6:
.cfi_startproc
$movkey ($key),$rndkey0
shl \$4,$rounds
$movkey 16($key),$rndkey1
@@ -503,6 +514,7 @@ _aesni_${dir}rypt6:
aes${dir}last $rndkey0,$inout4
aes${dir}last $rndkey0,$inout5
ret
.cfi_endproc
.size _aesni_${dir}rypt6,.-_aesni_${dir}rypt6
___
}
@@ -514,6 +526,7 @@ $code.=<<___;
.type _aesni_${dir}rypt8,\@abi-omnipotent
.align 16
_aesni_${dir}rypt8:
.cfi_startproc
$movkey ($key),$rndkey0
shl \$4,$rounds
$movkey 16($key),$rndkey1
@@ -574,6 +587,7 @@ _aesni_${dir}rypt8:
aes${dir}last $rndkey0,$inout6
aes${dir}last $rndkey0,$inout7
ret
.cfi_endproc
.size _aesni_${dir}rypt8,.-_aesni_${dir}rypt8
___
}
@@ -598,6 +612,7 @@ $code.=<<___;
.type aesni_ecb_encrypt,\@function,5
.align 16
aesni_ecb_encrypt:
.cfi_startproc
___
$code.=<<___ if ($win64);
lea -0x58(%rsp),%rsp
@@ -943,6 +958,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size aesni_ecb_encrypt,.-aesni_ecb_encrypt
___
+20 -6
View File
@@ -53,18 +53,27 @@ open OUT,"| \"$^X\" $xlate $flavour $output";
$prefix="aes_v8";
$_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=7
.text
___
$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
.arch armv7-a // don't confuse not-so-latest binutils with argv8 :-)
.fpu neon
#ifdef __thumb2__
.syntax unified
.thumb
# define INST(a,b,c,d) $_byte c,d|0xc,a,b
#else
.code 32
#undef __thumb2__
# define INST(a,b,c,d) $_byte a,b,c,d
#endif
.text
___
# Assembler mnemonics are an eclectic mix of 32- and 64-bit syntax,
@@ -262,6 +271,7 @@ $code.=<<___;
${prefix}_set_decrypt_key:
___
$code.=<<___ if ($flavour =~ /64/);
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
___
@@ -305,6 +315,7 @@ $code.=<<___ if ($flavour !~ /64/);
___
$code.=<<___ if ($flavour =~ /64/);
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
___
$code.=<<___;
@@ -953,7 +964,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
@@ -994,14 +1005,17 @@ if ($flavour =~ /64/) { ######## 64-bit code
s/\],#[0-9]+/]!/o;
s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or
s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vtbl\.8\s+(.*)/unvtbl($1)/geo or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/vmov\.32\s+(.*)/unvmov32($1)/geo or
s/^(\s+)b\./$1b/o or
s/^(\s+)mov\./$1mov/o or
s/^(\s+)ret/$1bx\tlr/o;
if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
print " it $2\n";
}
print $_,"\n";
}
}
+4 -3
View File
@@ -728,7 +728,6 @@ $code.=<<___;
.arch armv7-a
.fpu neon
.text
.syntax unified @ ARMv7-capable assembler is expected to handle this
#if defined(__thumb2__) && !defined(__APPLE__)
.thumb
@@ -737,6 +736,8 @@ $code.=<<___;
# undef __thumb2__
#endif
.text
.type _bsaes_decrypt8,%function
.align 4
_bsaes_decrypt8:
@@ -1125,9 +1126,9 @@ bsaes_cbc_encrypt:
#ifndef __thumb__
blo AES_cbc_encrypt
#else
bhs 1f
bhs .Lcbc_do_bsaes
b AES_cbc_encrypt
1:
.Lcbc_do_bsaes:
#endif
#endif
+6
View File
@@ -816,6 +816,7 @@ $code.=<<___;
.type _bsaes_encrypt8,\@abi-omnipotent
.align 64
_bsaes_encrypt8:
.cfi_startproc
lea .LBS0(%rip), $const # constants table
movdqa ($key), @XMM[9] # round 0 key
@@ -875,11 +876,13 @@ $code.=<<___;
pxor @XMM[8], @XMM[0]
pxor @XMM[8], @XMM[1]
ret
.cfi_endproc
.size _bsaes_encrypt8,.-_bsaes_encrypt8
.type _bsaes_decrypt8,\@abi-omnipotent
.align 64
_bsaes_decrypt8:
.cfi_startproc
lea .LBS0(%rip), $const # constants table
movdqa ($key), @XMM[9] # round 0 key
@@ -937,6 +940,7 @@ $code.=<<___;
pxor @XMM[8], @XMM[0]
pxor @XMM[8], @XMM[1]
ret
.cfi_endproc
.size _bsaes_decrypt8,.-_bsaes_decrypt8
___
}
@@ -971,6 +975,7 @@ $code.=<<___;
.type _bsaes_key_convert,\@abi-omnipotent
.align 16
_bsaes_key_convert:
.cfi_startproc
lea .Lmasks(%rip), $const
movdqu ($inp), %xmm7 # load round 0 key
lea 0x10($inp), $inp
@@ -1049,6 +1054,7 @@ _bsaes_key_convert:
movdqa 0x50($const), %xmm7 # .L63
#movdqa %xmm6, ($out) # don't save last round key
ret
.cfi_endproc
.size _bsaes_key_convert,.-_bsaes_key_convert
___
}
+156 -138
View File
@@ -150,12 +150,12 @@ my ($sb1u,$sb1t,$sb2u,$sb2t) = map("v$_.16b",(24..27));
my ($sb9u,$sb9t,$sbdu,$sbdt,$sbbu,$sbbt,$sbeu,$sbet)=map("v$_.16b",(24..31));
$code.=<<___;
##
## _aes_preheat
##
## Fills register %r10 -> .aes_consts (so you can -fPIC)
## and %xmm9-%xmm15 as specified below.
##
//
// _aes_preheat
//
// Fills register %r10 -> .aes_consts (so you can -fPIC)
// and %xmm9-%xmm15 as specified below.
//
.type _vpaes_encrypt_preheat,%function
.align 4
_vpaes_encrypt_preheat:
@@ -167,21 +167,21 @@ _vpaes_encrypt_preheat:
ret
.size _vpaes_encrypt_preheat,.-_vpaes_encrypt_preheat
##
## _aes_encrypt_core
##
## AES-encrypt %xmm0.
##
## Inputs:
## %xmm0 = input
## %xmm9-%xmm15 as in _vpaes_preheat
## (%rdx) = scheduled keys
##
## Output in %xmm0
## Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax
## Preserves %xmm6 - %xmm8 so you get some local vectors
##
##
//
// _aes_encrypt_core
//
// AES-encrypt %xmm0.
//
// Inputs:
// %xmm0 = input
// %xmm9-%xmm15 as in _vpaes_preheat
// (%rdx) = scheduled keys
//
// Output in %xmm0
// Clobbers %xmm1-%xmm5, %r9, %r10, %r11, %rax
// Preserves %xmm6 - %xmm8 so you get some local vectors
//
//
.type _vpaes_encrypt_core,%function
.align 4
_vpaes_encrypt_core:
@@ -255,6 +255,7 @@ _vpaes_encrypt_core:
.type vpaes_encrypt,%function
.align 4
vpaes_encrypt:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -264,6 +265,7 @@ vpaes_encrypt:
st1 {v0.16b}, [$out]
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_encrypt,.-vpaes_encrypt
@@ -385,11 +387,11 @@ _vpaes_decrypt_preheat:
ret
.size _vpaes_decrypt_preheat,.-_vpaes_decrypt_preheat
##
## Decryption core
##
## Same API as encryption core.
##
//
// Decryption core
//
// Same API as encryption core.
//
.type _vpaes_decrypt_core,%function
.align 4
_vpaes_decrypt_core:
@@ -486,6 +488,7 @@ _vpaes_decrypt_core:
.type vpaes_decrypt,%function
.align 4
vpaes_decrypt:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -495,6 +498,7 @@ vpaes_decrypt:
st1 {v0.16b}, [$out]
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_decrypt,.-vpaes_decrypt
@@ -639,11 +643,11 @@ my ($inp,$bits,$out,$dir)=("x0","w1","x2","w3");
my ($invlo,$invhi,$iptlo,$ipthi,$rcon) = map("v$_.16b",(18..21,8));
$code.=<<___;
########################################################
## ##
## AES key schedule ##
## ##
########################################################
////////////////////////////////////////////////////////
// //
// AES key schedule //
// //
////////////////////////////////////////////////////////
.type _vpaes_key_preheat,%function
.align 4
_vpaes_key_preheat:
@@ -665,6 +669,7 @@ _vpaes_key_preheat:
.type _vpaes_schedule_core,%function
.align 4
_vpaes_schedule_core:
.inst 0xd503233f // paciasp
stp x29, x30, [sp,#-16]!
add x29,sp,#0
@@ -698,14 +703,14 @@ _vpaes_schedule_core:
b.eq .Lschedule_192
// 128: fall though
##
## .schedule_128
##
## 128-bit specific part of key schedule.
##
## This schedule is really simple, because all its parts
## are accomplished by the subroutines.
##
//
// .schedule_128
//
// 128-bit specific part of key schedule.
//
// This schedule is really simple, because all its parts
// are accomplished by the subroutines.
//
.Lschedule_128:
mov $inp, #10 // mov \$10, %esi
@@ -716,21 +721,21 @@ _vpaes_schedule_core:
bl _vpaes_schedule_mangle // write output
b .Loop_schedule_128
##
## .aes_schedule_192
##
## 192-bit specific part of key schedule.
##
## The main body of this schedule is the same as the 128-bit
## schedule, but with more smearing. The long, high side is
## stored in %xmm7 as before, and the short, low side is in
## the high bits of %xmm6.
##
## This schedule is somewhat nastier, however, because each
## round produces 192 bits of key material, or 1.5 round keys.
## Therefore, on each cycle we do 2 rounds and produce 3 round
## keys.
##
//
// .aes_schedule_192
//
// 192-bit specific part of key schedule.
//
// The main body of this schedule is the same as the 128-bit
// schedule, but with more smearing. The long, high side is
// stored in %xmm7 as before, and the short, low side is in
// the high bits of %xmm6.
//
// This schedule is somewhat nastier, however, because each
// round produces 192 bits of key material, or 1.5 round keys.
// Therefore, on each cycle we do 2 rounds and produce 3 round
// keys.
//
.align 4
.Lschedule_192:
sub $inp, $inp, #8
@@ -754,16 +759,16 @@ _vpaes_schedule_core:
bl _vpaes_schedule_192_smear
b .Loop_schedule_192
##
## .aes_schedule_256
##
## 256-bit specific part of key schedule.
##
## The structure here is very similar to the 128-bit
## schedule, but with an additional "low side" in
## %xmm6. The low side's rounds are the same as the
## high side's, except no rcon and no rotation.
##
//
// .aes_schedule_256
//
// 256-bit specific part of key schedule.
//
// The structure here is very similar to the 128-bit
// schedule, but with an additional "low side" in
// %xmm6. The low side's rounds are the same as the
// high side's, except no rcon and no rotation.
//
.align 4
.Lschedule_256:
ld1 {v0.16b}, [$inp] // vmovdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
@@ -790,16 +795,16 @@ _vpaes_schedule_core:
b .Loop_schedule_256
##
## .aes_schedule_mangle_last
##
## Mangler for last round of key schedule
## Mangles %xmm0
## when encrypting, outputs out(%xmm0) ^ 63
## when decrypting, outputs unskew(%xmm0)
##
## Always called right before return... jumps to cleanup and exits
##
//
// .aes_schedule_mangle_last
//
// Mangler for last round of key schedule
// Mangles %xmm0
// when encrypting, outputs out(%xmm0) ^ 63
// when decrypting, outputs unskew(%xmm0)
//
// Always called right before return... jumps to cleanup and exits
//
.align 4
.Lschedule_mangle_last:
// schedule last round key from xmm0
@@ -829,23 +834,24 @@ _vpaes_schedule_core:
eor v6.16b, v6.16b, v6.16b // vpxor %xmm6, %xmm6, %xmm6
eor v7.16b, v7.16b, v7.16b // vpxor %xmm7, %xmm7, %xmm7
ldp x29, x30, [sp],#16
.inst 0xd50323bf // autiasp
ret
.size _vpaes_schedule_core,.-_vpaes_schedule_core
##
## .aes_schedule_192_smear
##
## Smear the short, low side in the 192-bit key schedule.
##
## Inputs:
## %xmm7: high side, b a x y
## %xmm6: low side, d c 0 0
## %xmm13: 0
##
## Outputs:
## %xmm6: b+c+d b+c 0 0
## %xmm0: b+c+d b+c b a
##
//
// .aes_schedule_192_smear
//
// Smear the short, low side in the 192-bit key schedule.
//
// Inputs:
// %xmm7: high side, b a x y
// %xmm6: low side, d c 0 0
// %xmm13: 0
//
// Outputs:
// %xmm6: b+c+d b+c 0 0
// %xmm0: b+c+d b+c b a
//
.type _vpaes_schedule_192_smear,%function
.align 4
_vpaes_schedule_192_smear:
@@ -861,24 +867,24 @@ _vpaes_schedule_192_smear:
ret
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
##
## .aes_schedule_round
##
## Runs one main round of the key schedule on %xmm0, %xmm7
##
## Specifically, runs subbytes on the high dword of %xmm0
## then rotates it by one byte and xors into the low dword of
## %xmm7.
##
## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
## next rcon.
##
## Smears the dwords of %xmm7 by xoring the low into the
## second low, result into third, result into highest.
##
## Returns results in %xmm7 = %xmm0.
## Clobbers %xmm1-%xmm4, %r11.
##
//
// .aes_schedule_round
//
// Runs one main round of the key schedule on %xmm0, %xmm7
//
// Specifically, runs subbytes on the high dword of %xmm0
// then rotates it by one byte and xors into the low dword of
// %xmm7.
//
// Adds rcon from low byte of %xmm8, then rotates %xmm8 for
// next rcon.
//
// Smears the dwords of %xmm7 by xoring the low into the
// second low, result into third, result into highest.
//
// Returns results in %xmm7 = %xmm0.
// Clobbers %xmm1-%xmm4, %r11.
//
.type _vpaes_schedule_round,%function
.align 4
_vpaes_schedule_round:
@@ -926,15 +932,15 @@ _vpaes_schedule_low_round:
ret
.size _vpaes_schedule_round,.-_vpaes_schedule_round
##
## .aes_schedule_transform
##
## Linear-transform %xmm0 according to tables at (%r11)
##
## Requires that %xmm9 = 0x0F0F... as in preheat
## Output in %xmm0
## Clobbers %xmm1, %xmm2
##
//
// .aes_schedule_transform
//
// Linear-transform %xmm0 according to tables at (%r11)
//
// Requires that %xmm9 = 0x0F0F... as in preheat
// Output in %xmm0
// Clobbers %xmm1, %xmm2
//
.type _vpaes_schedule_transform,%function
.align 4
_vpaes_schedule_transform:
@@ -948,29 +954,29 @@ _vpaes_schedule_transform:
ret
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
##
## .aes_schedule_mangle
##
## Mangle xmm0 from (basis-transformed) standard version
## to our version.
##
## On encrypt,
## xor with 0x63
## multiply by circulant 0,1,1,1
## apply shiftrows transform
##
## On decrypt,
## xor with 0x63
## multiply by "inverse mixcolumns" circulant E,B,D,9
## deskew
## apply shiftrows transform
##
##
## Writes out to (%rdx), and increments or decrements it
## Keeps track of round number mod 4 in %r8
## Preserves xmm0
## Clobbers xmm1-xmm5
##
//
// .aes_schedule_mangle
//
// Mangle xmm0 from (basis-transformed) standard version
// to our version.
//
// On encrypt,
// xor with 0x63
// multiply by circulant 0,1,1,1
// apply shiftrows transform
//
// On decrypt,
// xor with 0x63
// multiply by "inverse mixcolumns" circulant E,B,D,9
// deskew
// apply shiftrows transform
//
//
// Writes out to (%rdx), and increments or decrements it
// Keeps track of round number mod 4 in %r8
// Preserves xmm0
// Clobbers xmm1-xmm5
//
.type _vpaes_schedule_mangle,%function
.align 4
_vpaes_schedule_mangle:
@@ -1041,6 +1047,7 @@ _vpaes_schedule_mangle:
.type vpaes_set_encrypt_key,%function
.align 4
vpaes_set_encrypt_key:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
stp d8,d9,[sp,#-16]! // ABI spec says so
@@ -1056,6 +1063,7 @@ vpaes_set_encrypt_key:
ldp d8,d9,[sp],#16
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
@@ -1063,6 +1071,7 @@ vpaes_set_encrypt_key:
.type vpaes_set_decrypt_key,%function
.align 4
vpaes_set_decrypt_key:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
stp d8,d9,[sp,#-16]! // ABI spec says so
@@ -1082,6 +1091,7 @@ vpaes_set_decrypt_key:
ldp d8,d9,[sp],#16
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
___
@@ -1098,6 +1108,7 @@ vpaes_cbc_encrypt:
cmp w5, #0 // check direction
b.eq vpaes_cbc_decrypt
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -1120,6 +1131,7 @@ vpaes_cbc_encrypt:
st1 {v0.16b}, [$ivec] // write ivec
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
.Lcbc_abort:
ret
.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
@@ -1127,6 +1139,7 @@ vpaes_cbc_encrypt:
.type vpaes_cbc_decrypt,%function
.align 4
vpaes_cbc_decrypt:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
stp d8,d9,[sp,#-16]! // ABI spec says so
@@ -1168,6 +1181,7 @@ vpaes_cbc_decrypt:
ldp d10,d11,[sp],#16
ldp d8,d9,[sp],#16
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_cbc_decrypt,.-vpaes_cbc_decrypt
___
@@ -1177,6 +1191,7 @@ $code.=<<___;
.type vpaes_ecb_encrypt,%function
.align 4
vpaes_ecb_encrypt:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
stp d8,d9,[sp,#-16]! // ABI spec says so
@@ -1210,6 +1225,7 @@ vpaes_ecb_encrypt:
ldp d10,d11,[sp],#16
ldp d8,d9,[sp],#16
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_ecb_encrypt,.-vpaes_ecb_encrypt
@@ -1217,6 +1233,7 @@ vpaes_ecb_encrypt:
.type vpaes_ecb_decrypt,%function
.align 4
vpaes_ecb_decrypt:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
stp d8,d9,[sp,#-16]! // ABI spec says so
@@ -1250,6 +1267,7 @@ vpaes_ecb_decrypt:
ldp d10,d11,[sp],#16
ldp d8,d9,[sp],#16
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size vpaes_ecb_decrypt,.-vpaes_ecb_decrypt
___
+26
View File
@@ -91,6 +91,7 @@ $code.=<<___;
.type _vpaes_encrypt_core,\@abi-omnipotent
.align 16
_vpaes_encrypt_core:
.cfi_startproc
mov %rdx, %r9
mov \$16, %r11
mov 240(%rdx),%eax
@@ -171,6 +172,7 @@ _vpaes_encrypt_core:
pxor %xmm4, %xmm0 # 0 = A
pshufb %xmm1, %xmm0
ret
.cfi_endproc
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
##
@@ -181,6 +183,7 @@ _vpaes_encrypt_core:
.type _vpaes_decrypt_core,\@abi-omnipotent
.align 16
_vpaes_decrypt_core:
.cfi_startproc
mov %rdx, %r9 # load key
mov 240(%rdx),%eax
movdqa %xmm9, %xmm1
@@ -277,6 +280,7 @@ _vpaes_decrypt_core:
pxor %xmm4, %xmm0 # 0 = A
pshufb %xmm2, %xmm0
ret
.cfi_endproc
.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
########################################################
@@ -287,6 +291,7 @@ _vpaes_decrypt_core:
.type _vpaes_schedule_core,\@abi-omnipotent
.align 16
_vpaes_schedule_core:
.cfi_startproc
# rdi = key
# rsi = size in bits
# rdx = buffer
@@ -453,6 +458,7 @@ _vpaes_schedule_core:
pxor %xmm6, %xmm6
pxor %xmm7, %xmm7
ret
.cfi_endproc
.size _vpaes_schedule_core,.-_vpaes_schedule_core
##
@@ -472,6 +478,7 @@ _vpaes_schedule_core:
.type _vpaes_schedule_192_smear,\@abi-omnipotent
.align 16
_vpaes_schedule_192_smear:
.cfi_startproc
pshufd \$0x80, %xmm6, %xmm1 # d c 0 0 -> c 0 0 0
pshufd \$0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a
pxor %xmm1, %xmm6 # -> c+d c 0 0
@@ -480,6 +487,7 @@ _vpaes_schedule_192_smear:
movdqa %xmm6, %xmm0
movhlps %xmm1, %xmm6 # clobber low side with zeros
ret
.cfi_endproc
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
##
@@ -503,6 +511,7 @@ _vpaes_schedule_192_smear:
.type _vpaes_schedule_round,\@abi-omnipotent
.align 16
_vpaes_schedule_round:
.cfi_startproc
# extract rcon from xmm8
pxor %xmm1, %xmm1
palignr \$15, %xmm8, %xmm1
@@ -556,6 +565,7 @@ _vpaes_schedule_low_round:
pxor %xmm7, %xmm0
movdqa %xmm0, %xmm7
ret
.cfi_endproc
.size _vpaes_schedule_round,.-_vpaes_schedule_round
##
@@ -570,6 +580,7 @@ _vpaes_schedule_low_round:
.type _vpaes_schedule_transform,\@abi-omnipotent
.align 16
_vpaes_schedule_transform:
.cfi_startproc
movdqa %xmm9, %xmm1
pandn %xmm0, %xmm1
psrld \$4, %xmm1
@@ -580,6 +591,7 @@ _vpaes_schedule_transform:
pshufb %xmm1, %xmm0
pxor %xmm2, %xmm0
ret
.cfi_endproc
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
##
@@ -608,6 +620,7 @@ _vpaes_schedule_transform:
.type _vpaes_schedule_mangle,\@abi-omnipotent
.align 16
_vpaes_schedule_mangle:
.cfi_startproc
movdqa %xmm0, %xmm4 # save xmm0 for later
movdqa .Lk_mc_forward(%rip),%xmm5
test %rcx, %rcx
@@ -672,6 +685,7 @@ _vpaes_schedule_mangle:
and \$0x30, %r8
movdqu %xmm3, (%rdx)
ret
.cfi_endproc
.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
#
@@ -681,6 +695,7 @@ _vpaes_schedule_mangle:
.type ${PREFIX}_set_encrypt_key,\@function,3
.align 16
${PREFIX}_set_encrypt_key:
.cfi_startproc
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -723,12 +738,14 @@ ___
$code.=<<___;
xor %eax,%eax
ret
.cfi_endproc
.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
.globl ${PREFIX}_set_decrypt_key
.type ${PREFIX}_set_decrypt_key,\@function,3
.align 16
${PREFIX}_set_decrypt_key:
.cfi_startproc
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -776,12 +793,14 @@ ___
$code.=<<___;
xor %eax,%eax
ret
.cfi_endproc
.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
.globl ${PREFIX}_encrypt
.type ${PREFIX}_encrypt,\@function,3
.align 16
${PREFIX}_encrypt:
.cfi_startproc
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -819,12 +838,14 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size ${PREFIX}_encrypt,.-${PREFIX}_encrypt
.globl ${PREFIX}_decrypt
.type ${PREFIX}_decrypt,\@function,3
.align 16
${PREFIX}_decrypt:
.cfi_startproc
___
$code.=<<___ if ($win64);
lea -0xb8(%rsp),%rsp
@@ -862,6 +883,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size ${PREFIX}_decrypt,.-${PREFIX}_decrypt
___
{
@@ -874,6 +896,7 @@ $code.=<<___;
.type ${PREFIX}_cbc_encrypt,\@function,6
.align 16
${PREFIX}_cbc_encrypt:
.cfi_startproc
xchg $key,$len
___
($len,$key)=($key,$len);
@@ -944,6 +967,7 @@ ___
$code.=<<___;
.Lcbc_abort:
ret
.cfi_endproc
.size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
___
}
@@ -957,6 +981,7 @@ $code.=<<___;
.type _vpaes_preheat,\@abi-omnipotent
.align 16
_vpaes_preheat:
.cfi_startproc
lea .Lk_s0F(%rip), %r10
movdqa -0x20(%r10), %xmm10 # .Lk_inv
movdqa -0x10(%r10), %xmm11 # .Lk_inv+16
@@ -966,6 +991,7 @@ _vpaes_preheat:
movdqa 0x50(%r10), %xmm15 # .Lk_sb2
movdqa 0x60(%r10), %xmm14 # .Lk_sb2+16
ret
.cfi_endproc
.size _vpaes_preheat,.-_vpaes_preheat
########################################################
## ##
+2 -1
View File
@@ -21,7 +21,6 @@ open OUT,"| \"$^X\" $xlate $flavour $output";
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__) && !defined(__APPLE__)
.syntax unified
.thumb
@@ -30,6 +29,8 @@ $code.=<<___;
#undef __thumb2__
#endif
.text
.align 5
.global OPENSSL_atomic_add
.type OPENSSL_atomic_add,%function
+5 -4
View File
@@ -253,9 +253,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
}
# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
int fd = fileno((FILE *)ptr);
if (num & BIO_FP_TEXT)
setmode(fd, O_TEXT);
else
if (!(num & BIO_FP_TEXT))
setmode(fd, O_BINARY);
# endif
}
@@ -279,11 +277,14 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = 0;
break;
}
# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32_CYGWIN)
# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS)
if (!(num & BIO_FP_TEXT))
OPENSSL_strlcat(p, "b", sizeof(p));
else
OPENSSL_strlcat(p, "t", sizeof(p));
# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
if (!(num & BIO_FP_TEXT))
OPENSSL_strlcat(p, "b", sizeof(p));
# endif
fp = openssl_fopen(ptr, p);
if (fp == NULL) {
+10 -3
View File
@@ -57,13 +57,14 @@ if ($flavour && $flavour ne "void") {
$code=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
#else
.code 32
#endif
.text
___
################
# private interface to mul_1x1_ialu
@@ -176,11 +177,13 @@ bn_GF2m_mul_2x2:
#if __ARM_MAX_ARCH__>=7
stmdb sp!,{r10,lr}
ldr r12,.LOPENSSL_armcap
# if !defined(_WIN32)
adr r10,.LOPENSSL_armcap
ldr r12,[r12,r10]
#ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
#endif
# endif
tst r12,#ARMV7_NEON
itt ne
ldrne r10,[sp],#8
@@ -310,7 +313,11 @@ $code.=<<___;
#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.
# endif
#endif
.asciz "GF(2^m) Multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 5
+12 -5
View File
@@ -97,7 +97,6 @@ $_num="$num,#15*4"; $_bpend=$_num;
$code=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -105,10 +104,16 @@ $code=<<___;
.code 32
#endif
.text
#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.Lbn_mul_mont
# endif
#endif
.global bn_mul_mont
@@ -122,12 +127,14 @@ bn_mul_mont:
#if __ARM_MAX_ARCH__>=7
tst ip,#7
bne .Lialu
adr r0,.Lbn_mul_mont
ldr r2,.LOPENSSL_armcap
ldr r0,.LOPENSSL_armcap
#if !defined(_WIN32)
adr r2,.Lbn_mul_mont
ldr r0,[r0,r2]
#ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r0,[r0]
#endif
# endif
tst r0,#ARMV7_NEON @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
+12 -8
View File
@@ -197,7 +197,7 @@ bn_mul_mont:
mul $nlo,$nj,$m1 // np[j]*m1
adds $lo1,$lo1,$lo0
umulh $nhi,$nj,$m1
str $lo1,[$tp,#-16] // tp[j-1]
stur $lo1,[$tp,#-16] // tp[j-1]
cbnz $j,.Linner
.Linner_skip:
@@ -253,13 +253,13 @@ bn_mul_mont:
csel $nj,$tj,$aj,lo // did it borrow?
ldr $tj,[$tp],#8
ldr $aj,[$rp],#8
str xzr,[$tp,#-16] // wipe tp
str $nj,[$rp,#-16]
stur xzr,[$tp,#-16] // wipe tp
stur $nj,[$rp,#-16]
cbnz $num,.Lcond_copy
csel $nj,$tj,$aj,lo
str xzr,[$tp,#-8] // wipe tp
str $nj,[$rp,#-8]
stur xzr,[$tp,#-8] // wipe tp
stur $nj,[$rp,#-8]
ldp x19,x20,[x29,#16]
mov sp,x29
@@ -287,6 +287,7 @@ __bn_sqr8x_mont:
cmp $ap,$bp
b.ne __bn_mul4x_mont
.Lsqr8x_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -595,7 +596,7 @@ __bn_sqr8x_mont:
ldp $a4,$a5,[$tp,#8*4]
ldp $a6,$a7,[$tp,#8*6]
adds $acc0,$acc0,$a0
ldr $n0,[$rp,#-8*8]
ldur $n0,[$rp,#-8*8]
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$ap,#8*0]
adcs $acc2,$acc2,$a2
@@ -793,7 +794,7 @@ $code.=<<___;
//adc $carry,xzr,xzr // moved below
cbz $cnt,.Lsqr8x8_post_condition
ldr $n0,[$tp,#-8*8]
ldur $n0,[$tp,#-8*8]
ldp $a0,$a1,[$np,#8*0]
ldp $a2,$a3,[$np,#8*2]
ldp $a4,$a5,[$np,#8*4]
@@ -851,7 +852,7 @@ $code.=<<___;
ldp $a6,$a7,[$tp,#8*6]
cbz $cnt,.Lsqr8x_tail_break
ldr $n0,[$rp,#-8*8]
ldur $n0,[$rp,#-8*8]
adds $acc0,$acc0,$a0
adcs $acc1,$acc1,$a1
ldp $a0,$a1,[$np,#8*0]
@@ -1040,6 +1041,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldr x29,[sp],#128
.inst 0xd50323bf // autiasp
ret
.size __bn_sqr8x_mont,.-__bn_sqr8x_mont
___
@@ -1063,6 +1065,7 @@ $code.=<<___;
.type __bn_mul4x_mont,%function
.align 5
__bn_mul4x_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -1496,6 +1499,7 @@ __bn_mul4x_mont:
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldr x29,[sp],#128
.inst 0xd50323bf // autiasp
ret
.size __bn_mul4x_mont,.-__bn_mul4x_mont
___
+6
View File
@@ -1492,6 +1492,7 @@ $code.=<<___;
.type rsaz_1024_red2norm_avx2,\@abi-omnipotent
.align 32
rsaz_1024_red2norm_avx2:
.cfi_startproc
sub \$-128,$inp # size optimization
xor %rax,%rax
___
@@ -1525,12 +1526,14 @@ ___
}
$code.=<<___;
ret
.cfi_endproc
.size rsaz_1024_red2norm_avx2,.-rsaz_1024_red2norm_avx2
.globl rsaz_1024_norm2red_avx2
.type rsaz_1024_norm2red_avx2,\@abi-omnipotent
.align 32
rsaz_1024_norm2red_avx2:
.cfi_startproc
sub \$-128,$out # size optimization
mov ($inp),@T[0]
mov \$0x1fffffff,%eax
@@ -1562,6 +1565,7 @@ $code.=<<___;
mov @T[0],`8*($j+2)-128`($out)
mov @T[0],`8*($j+3)-128`($out)
ret
.cfi_endproc
.size rsaz_1024_norm2red_avx2,.-rsaz_1024_norm2red_avx2
___
}
@@ -1573,6 +1577,7 @@ $code.=<<___;
.type rsaz_1024_scatter5_avx2,\@abi-omnipotent
.align 32
rsaz_1024_scatter5_avx2:
.cfi_startproc
vzeroupper
vmovdqu .Lscatter_permd(%rip),%ymm5
shl \$4,$power
@@ -1592,6 +1597,7 @@ rsaz_1024_scatter5_avx2:
vzeroupper
ret
.cfi_endproc
.size rsaz_1024_scatter5_avx2,.-rsaz_1024_scatter5_avx2
.globl rsaz_1024_gather5_avx2
+2
View File
@@ -2910,6 +2910,7 @@ bn_powerx5:
.align 32
bn_sqrx8x_internal:
__bn_sqrx8x_internal:
.cfi_startproc
##################################################################
# Squaring part:
#
@@ -3542,6 +3543,7 @@ __bn_sqrx8x_reduction:
cmp 8+8(%rsp),%r8 # end of t[]?
jb .Lsqrx8x_reduction_loop
ret
.cfi_endproc
.size bn_sqrx8x_internal,.-bn_sqrx8x_internal
___
}
+3 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -227,6 +227,8 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx)
}
/* OK, make sure the returned bignum is "zero" */
BN_zero(ret);
/* clear BN_FLG_CONSTTIME if leaked from previous frames */
ret->flags &= (~BN_FLG_CONSTTIME);
ctx->used++;
CTXDBG_RET(ctx, ret);
return ret;
+3 -3
View File
@@ -1,7 +1,7 @@
# Note that these directories are filtered in Configure. Look for %skipdir
# there for further explanations.
SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
txt_db pkcs7 pkcs12 ui kdf store \
txt_db pkcs7 pkcs12 ui kdf store property \
md2 md4 md5 sha mdc2 gmac hmac ripemd whrlpool poly1305 blake2 \
siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
@@ -12,8 +12,8 @@ SOURCE[../libcrypto]=\
cryptlib.c mem.c mem_dbg.c cversion.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 {- $target{cpuid_asm_src} -} \
{- $target{uplink_aux_src} -}
o_init.c o_fips.c mem_sec.c init.c context.c sparse_array.c \
{- $target{cpuid_asm_src} -} {- $target{uplink_aux_src} -}
DEPEND[cversion.o]=buildinf.h
GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
+9 -2
View File
@@ -171,7 +171,6 @@ my @ret;
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__) || defined(__clang__)
.syntax unified
#endif
@@ -185,6 +184,8 @@ $code.=<<___;
#define ldrhsb ldrbhs
#endif
.text
.align 5
.Lsigma:
.long 0x61707865,0x3320646e,0x79622d32,0x6b206574 @ endian-neutral
@@ -192,7 +193,11 @@ $code.=<<___;
.long 1,0,0,0
#if __ARM_MAX_ARCH__>=7
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.LChaCha20_ctr32
# endif
#else
.word -1
#endif
@@ -219,8 +224,10 @@ ChaCha20_ctr32:
cmp r2,#192 @ test len
bls .Lshort
ldr r4,[r14,#-32]
# if !defined(_WIN32)
ldr r4,[r14,r4]
# ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r4,[r4]
# endif
tst r4,#ARMV7_NEON
+13 -14
View File
@@ -131,12 +131,6 @@ $code.=<<___;
.quad 0x3320646e61707865,0x6b20657479622d32 // endian-neutral
.Lone:
.long 1,0,0,0
.LOPENSSL_armcap_P:
#ifdef __ILP32__
.long OPENSSL_armcap_P-.
#else
.quad OPENSSL_armcap_P-.
#endif
.asciz "ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.globl ChaCha20_ctr32
@@ -144,19 +138,16 @@ $code.=<<___;
.align 5
ChaCha20_ctr32:
cbz $len,.Labort
adr @x[0],.LOPENSSL_armcap_P
cmp $len,#192
b.lo .Lshort
#ifdef __ILP32__
ldrsw @x[1],[@x[0]]
#else
ldr @x[1],[@x[0]]
#endif
ldr w17,[@x[1],@x[0]]
adrp x17,OPENSSL_armcap_P
ldr w17,[x17,#:lo12:OPENSSL_armcap_P]
tst w17,#ARMV7_NEON
b.ne ChaCha20_neon
b.ne .LChaCha20_neon
.Lshort:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-96]!
add x29,sp,#0
@@ -276,6 +267,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#96
.inst 0xd50323bf // autiasp
.Labort:
ret
@@ -332,6 +324,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#96
.inst 0xd50323bf // autiasp
ret
.size ChaCha20_ctr32,.-ChaCha20_ctr32
___
@@ -377,6 +370,8 @@ $code.=<<___;
.type ChaCha20_neon,%function
.align 5
ChaCha20_neon:
.LChaCha20_neon:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-96]!
add x29,sp,#0
@@ -575,6 +570,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#96
.inst 0xd50323bf // autiasp
ret
.Ltail_neon:
@@ -684,6 +680,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#96
.inst 0xd50323bf // autiasp
ret
.size ChaCha20_neon,.-ChaCha20_neon
___
@@ -696,6 +693,7 @@ $code.=<<___;
.type ChaCha20_512_neon,%function
.align 5
ChaCha20_512_neon:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-96]!
add x29,sp,#0
@@ -1114,6 +1112,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#96
.inst 0xd50323bf // autiasp
ret
.size ChaCha20_512_neon,.-ChaCha20_512_neon
___
+1 -1
View File
@@ -225,7 +225,7 @@ LABEL ("ChaCha20_ctr32");
larl ("%r1","OPENSSL_s390xcap_P");
lghi ("%r0",64);
&{$z? \&cgr:\&cr} ($len,"%r0");
&{$z? \&clgr:\&clr} ($len,"%r0");
jle ("_s390x_chacha_novx");
lg ("%r0","S390X_STFLE+16(%r1)");
+4 -1
View File
@@ -282,7 +282,7 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
return rv;
}
/* Initialise a ktri based on passed certificate and key */
/* Initialise a kari based on passed certificate and key */
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *pk, unsigned int flags)
@@ -299,6 +299,9 @@ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
kari->version = 3;
rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
if (rek == NULL)
return 0;
if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
M_ASN1_free_of(rek, CMS_RecipientEncryptedKey);
return 0;
+110
View File
@@ -0,0 +1,110 @@
/*
* 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 "internal/cryptlib.h"
#include "internal/thread_once.h"
struct openssl_ctx_st {
CRYPTO_RWLOCK *lock;
CRYPTO_EX_DATA data;
};
static OPENSSL_CTX default_context;
static int context_init(OPENSSL_CTX *ctx)
{
return (ctx->lock = CRYPTO_THREAD_lock_new()) != NULL
&& CRYPTO_new_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data);
}
static int context_deinit(OPENSSL_CTX *ctx)
{
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data);
CRYPTO_THREAD_lock_free(ctx->lock);
return 1;
}
static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
static void do_default_context_deinit(void)
{
context_deinit(&default_context);
}
DEFINE_RUN_ONCE_STATIC(do_default_context_init)
{
return OPENSSL_init_crypto(0, NULL)
&& context_init(&default_context)
&& OPENSSL_atexit(do_default_context_deinit);
}
OPENSSL_CTX *OPENSSL_CTX_new(void)
{
OPENSSL_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL && !context_init(ctx)) {
OPENSSL_CTX_free(ctx);
ctx = NULL;
}
return ctx;
}
void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
{
if (ctx != NULL)
context_deinit(ctx);
OPENSSL_free(ctx);
}
static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
CRYPTO_EX_DATA *ad, int index,
long argl_ign, void *argp)
{
const OPENSSL_CTX_METHOD *meth = argp;
void *ptr = meth->new_func();
if (ptr != NULL)
CRYPTO_set_ex_data(ad, index, ptr);
}
static void openssl_ctx_generic_free(void *parent_ign, void *ptr,
CRYPTO_EX_DATA *ad, int index,
long argl_ign, void *argp)
{
const OPENSSL_CTX_METHOD *meth = argp;
meth->free_func(ptr);
}
int openssl_ctx_new_index(const OPENSSL_CTX_METHOD *meth)
{
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_OPENSSL_CTX, 0, (void *)meth,
openssl_ctx_generic_new, NULL,
openssl_ctx_generic_free);
}
void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index)
{
void *data = NULL;
if (ctx == NULL) {
if (!RUN_ONCE(&default_context_init, do_default_context_init))
return 0;
ctx = &default_context;
}
CRYPTO_THREAD_read_lock(ctx->lock);
/* The alloc call ensures there's a value there */
if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
&ctx->data, index))
data = CRYPTO_get_ex_data(&ctx->data, index);
CRYPTO_THREAD_unlock(ctx->lock);
return data;
}
+3 -1
View File
@@ -51,7 +51,6 @@ if ($flavour && $flavour ne "void") {
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -80,6 +79,7 @@ close TABLE;
die "insane number of elements" if ($#arr != 64*16*37-1);
$code.=<<___;
.rodata
.globl ecp_nistz256_precomputed
.type ecp_nistz256_precomputed,%object
.align 12
@@ -104,6 +104,8 @@ for(1..37) {
}
$code.=<<___;
.size ecp_nistz256_precomputed,.-ecp_nistz256_precomputed
.text
.align 5
.LRR: @ 2^512 mod P precomputed for NIST P256 polynomial
.long 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb
+30 -4
View File
@@ -119,6 +119,7 @@ $code.=<<___;
.type ecp_nistz256_to_mont,%function
.align 6
ecp_nistz256_to_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-32]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -134,6 +135,7 @@ ecp_nistz256_to_mont:
ldp x19,x20,[sp,#16]
ldp x29,x30,[sp],#32
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont
@@ -142,6 +144,7 @@ ecp_nistz256_to_mont:
.type ecp_nistz256_from_mont,%function
.align 4
ecp_nistz256_from_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-32]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -157,6 +160,7 @@ ecp_nistz256_from_mont:
ldp x19,x20,[sp,#16]
ldp x29,x30,[sp],#32
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
@@ -166,6 +170,7 @@ ecp_nistz256_from_mont:
.type ecp_nistz256_mul_mont,%function
.align 4
ecp_nistz256_mul_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-32]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -180,6 +185,7 @@ ecp_nistz256_mul_mont:
ldp x19,x20,[sp,#16]
ldp x29,x30,[sp],#32
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont
@@ -188,6 +194,7 @@ ecp_nistz256_mul_mont:
.type ecp_nistz256_sqr_mont,%function
.align 4
ecp_nistz256_sqr_mont:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-32]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -201,6 +208,7 @@ ecp_nistz256_sqr_mont:
ldp x19,x20,[sp,#16]
ldp x29,x30,[sp],#32
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont
@@ -210,6 +218,7 @@ ecp_nistz256_sqr_mont:
.type ecp_nistz256_add,%function
.align 4
ecp_nistz256_add:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -223,6 +232,7 @@ ecp_nistz256_add:
bl __ecp_nistz256_add
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_add,.-ecp_nistz256_add
@@ -231,6 +241,7 @@ ecp_nistz256_add:
.type ecp_nistz256_div_by_2,%function
.align 4
ecp_nistz256_div_by_2:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -242,6 +253,7 @@ ecp_nistz256_div_by_2:
bl __ecp_nistz256_div_by_2
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2
@@ -250,6 +262,7 @@ ecp_nistz256_div_by_2:
.type ecp_nistz256_mul_by_2,%function
.align 4
ecp_nistz256_mul_by_2:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -265,6 +278,7 @@ ecp_nistz256_mul_by_2:
bl __ecp_nistz256_add // ret = a+a // 2*a
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
@@ -273,6 +287,7 @@ ecp_nistz256_mul_by_2:
.type ecp_nistz256_mul_by_3,%function
.align 4
ecp_nistz256_mul_by_3:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -299,6 +314,7 @@ ecp_nistz256_mul_by_3:
bl __ecp_nistz256_add // ret += a // 2*a+a=3*a
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3
@@ -308,6 +324,7 @@ ecp_nistz256_mul_by_3:
.type ecp_nistz256_sub,%function
.align 4
ecp_nistz256_sub:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -319,6 +336,7 @@ ecp_nistz256_sub:
bl __ecp_nistz256_sub_from
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_sub,.-ecp_nistz256_sub
@@ -327,6 +345,7 @@ ecp_nistz256_sub:
.type ecp_nistz256_neg,%function
.align 4
ecp_nistz256_neg:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
@@ -341,6 +360,7 @@ ecp_nistz256_neg:
bl __ecp_nistz256_sub_from
ldp x29,x30,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_neg,.-ecp_nistz256_neg
@@ -701,6 +721,7 @@ $code.=<<___;
.type ecp_nistz256_point_double,%function
.align 5
ecp_nistz256_point_double:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -835,6 +856,7 @@ ecp_nistz256_point_double:
ldp x19,x20,[x29,#16]
ldp x21,x22,[x29,#32]
ldp x29,x30,[sp],#80
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_point_double,.-ecp_nistz256_point_double
___
@@ -857,6 +879,7 @@ $code.=<<___;
.type ecp_nistz256_point_add,%function
.align 5
ecp_nistz256_point_add:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -1094,12 +1117,13 @@ $code.=<<___;
stp $acc2,$acc3,[$rp_real,#$i+16]
.Ladd_done:
add sp,x29,#0 // destroy frame
add sp,x29,#0 // destroy frame
ldp x19,x20,[x29,#16]
ldp x21,x22,[x29,#32]
ldp x23,x24,[x29,#48]
ldp x25,x26,[x29,#64]
ldp x29,x30,[sp],#80
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_point_add,.-ecp_nistz256_point_add
___
@@ -1121,6 +1145,7 @@ $code.=<<___;
.type ecp_nistz256_point_add_affine,%function
.align 5
ecp_nistz256_point_add_affine:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -1309,6 +1334,7 @@ $code.=<<___;
ldp x23,x24,[x29,#48]
ldp x25,x26,[x29,#64]
ldp x29,x30,[sp],#80
.inst 0xd50323bf // autiasp
ret
.size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine
___
@@ -1628,7 +1654,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp] // X
ldp x6,x7,[$inp,#16]
str w4,[$out,#64*0-4]
stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
@@ -1644,7 +1670,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp,#32] // Y
ldp x6,x7,[$inp,#48]
str w4,[$out,#64*0-4]
stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
@@ -1660,7 +1686,7 @@ ecp_nistz256_scatter_w5:
ldp x4,x5,[$inp,#64] // Z
ldp x6,x7,[$inp,#80]
str w4,[$out,#64*0-4]
stur w4,[$out,#64*0-4]
lsr x4,x4,#32
str w5,[$out,#64*1-4]
lsr x5,x5,#32
+34
View File
@@ -1674,6 +1674,7 @@ $code.=<<___;
.type __ecp_nistz256_mul_montq,\@abi-omnipotent
.align 32
__ecp_nistz256_mul_montq:
.cfi_startproc
########################################################################
# Multiply a by b[0]
mov %rax, $t1
@@ -1885,6 +1886,7 @@ __ecp_nistz256_mul_montq:
mov $acc1, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_mul_montq,.-__ecp_nistz256_mul_montq
################################################################################
@@ -1968,6 +1970,7 @@ $code.=<<___;
.type __ecp_nistz256_sqr_montq,\@abi-omnipotent
.align 32
__ecp_nistz256_sqr_montq:
.cfi_startproc
mov %rax, $acc5
mulq $acc6 # a[1]*a[0]
mov %rax, $acc1
@@ -2125,6 +2128,7 @@ __ecp_nistz256_sqr_montq:
mov $acc7, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq
___
@@ -2133,6 +2137,7 @@ $code.=<<___;
.type __ecp_nistz256_mul_montx,\@abi-omnipotent
.align 32
__ecp_nistz256_mul_montx:
.cfi_startproc
########################################################################
# Multiply by b[0]
mulx $acc1, $acc0, $acc1
@@ -2295,11 +2300,13 @@ __ecp_nistz256_mul_montx:
mov $acc1, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_mul_montx,.-__ecp_nistz256_mul_montx
.type __ecp_nistz256_sqr_montx,\@abi-omnipotent
.align 32
__ecp_nistz256_sqr_montx:
.cfi_startproc
mulx $acc6, $acc1, $acc2 # a[0]*a[1]
mulx $acc7, $t0, $acc3 # a[0]*a[2]
xor %eax, %eax
@@ -2423,6 +2430,7 @@ __ecp_nistz256_sqr_montx:
mov $acc7, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_sqr_montx,.-__ecp_nistz256_sqr_montx
___
}
@@ -2578,6 +2586,7 @@ ecp_nistz256_scatter_w5:
.type ecp_nistz256_gather_w5,\@abi-omnipotent
.align 32
ecp_nistz256_gather_w5:
.cfi_startproc
___
$code.=<<___ if ($avx>1);
mov OPENSSL_ia32cap_P+8(%rip), %eax
@@ -2666,6 +2675,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.LSEH_end_ecp_nistz256_gather_w5:
.size ecp_nistz256_gather_w5,.-ecp_nistz256_gather_w5
@@ -2694,6 +2704,7 @@ ecp_nistz256_scatter_w7:
.type ecp_nistz256_gather_w7,\@abi-omnipotent
.align 32
ecp_nistz256_gather_w7:
.cfi_startproc
___
$code.=<<___ if ($avx>1);
mov OPENSSL_ia32cap_P+8(%rip), %eax
@@ -2771,6 +2782,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.LSEH_end_ecp_nistz256_gather_w7:
.size ecp_nistz256_gather_w7,.-ecp_nistz256_gather_w7
___
@@ -2787,6 +2799,7 @@ $code.=<<___;
.type ecp_nistz256_avx2_gather_w5,\@abi-omnipotent
.align 32
ecp_nistz256_avx2_gather_w5:
.cfi_startproc
.Lavx2_gather_w5:
vzeroupper
___
@@ -2874,6 +2887,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.LSEH_end_ecp_nistz256_avx2_gather_w5:
.size ecp_nistz256_avx2_gather_w5,.-ecp_nistz256_avx2_gather_w5
___
@@ -2893,6 +2907,7 @@ $code.=<<___;
.type ecp_nistz256_avx2_gather_w7,\@abi-omnipotent
.align 32
ecp_nistz256_avx2_gather_w7:
.cfi_startproc
.Lavx2_gather_w7:
vzeroupper
___
@@ -2995,6 +3010,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.LSEH_end_ecp_nistz256_avx2_gather_w7:
.size ecp_nistz256_avx2_gather_w7,.-ecp_nistz256_avx2_gather_w7
___
@@ -3064,6 +3080,7 @@ $code.=<<___;
.type __ecp_nistz256_add_toq,\@abi-omnipotent
.align 32
__ecp_nistz256_add_toq:
.cfi_startproc
xor $t4,$t4
add 8*0($b_ptr), $a0
adc 8*1($b_ptr), $a1
@@ -3091,11 +3108,13 @@ __ecp_nistz256_add_toq:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_add_toq,.-__ecp_nistz256_add_toq
.type __ecp_nistz256_sub_fromq,\@abi-omnipotent
.align 32
__ecp_nistz256_sub_fromq:
.cfi_startproc
sub 8*0($b_ptr), $a0
sbb 8*1($b_ptr), $a1
mov $a0, $t0
@@ -3122,11 +3141,13 @@ __ecp_nistz256_sub_fromq:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_sub_fromq,.-__ecp_nistz256_sub_fromq
.type __ecp_nistz256_subq,\@abi-omnipotent
.align 32
__ecp_nistz256_subq:
.cfi_startproc
sub $a0, $t0
sbb $a1, $t1
mov $t0, $a0
@@ -3149,11 +3170,13 @@ __ecp_nistz256_subq:
cmovnz $t3, $a3
ret
.cfi_endproc
.size __ecp_nistz256_subq,.-__ecp_nistz256_subq
.type __ecp_nistz256_mul_by_2q,\@abi-omnipotent
.align 32
__ecp_nistz256_mul_by_2q:
.cfi_startproc
xor $t4, $t4
add $a0, $a0 # a0:a3+a0:a3
adc $a1, $a1
@@ -3181,6 +3204,7 @@ __ecp_nistz256_mul_by_2q:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_mul_by_2q,.-__ecp_nistz256_mul_by_2q
___
}
@@ -3620,7 +3644,9 @@ $code.=<<___;
movq %xmm1, $a_ptr # restore $a_ptr
movq %xmm0, $r_ptr # restore $r_ptr
add \$`32*(18-5)`, %rsp # difference in frame sizes
.cfi_adjust_cfa_offset `-32*(18-5)`
jmp .Lpoint_double_shortcut$x
.cfi_adjust_cfa_offset `32*(18-5)`
.align 32
.Ladd_proceed$x:
@@ -4156,6 +4182,7 @@ $code.=<<___;
.type __ecp_nistz256_add_tox,\@abi-omnipotent
.align 32
__ecp_nistz256_add_tox:
.cfi_startproc
xor $t4, $t4
adc 8*0($b_ptr), $a0
adc 8*1($b_ptr), $a1
@@ -4184,11 +4211,13 @@ __ecp_nistz256_add_tox:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_add_tox,.-__ecp_nistz256_add_tox
.type __ecp_nistz256_sub_fromx,\@abi-omnipotent
.align 32
__ecp_nistz256_sub_fromx:
.cfi_startproc
xor $t4, $t4
sbb 8*0($b_ptr), $a0
sbb 8*1($b_ptr), $a1
@@ -4217,11 +4246,13 @@ __ecp_nistz256_sub_fromx:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_sub_fromx,.-__ecp_nistz256_sub_fromx
.type __ecp_nistz256_subx,\@abi-omnipotent
.align 32
__ecp_nistz256_subx:
.cfi_startproc
xor $t4, $t4
sbb $a0, $t0
sbb $a1, $t1
@@ -4246,11 +4277,13 @@ __ecp_nistz256_subx:
cmovc $t3, $a3
ret
.cfi_endproc
.size __ecp_nistz256_subx,.-__ecp_nistz256_subx
.type __ecp_nistz256_mul_by_2x,\@abi-omnipotent
.align 32
__ecp_nistz256_mul_by_2x:
.cfi_startproc
xor $t4, $t4
adc $a0, $a0 # a0:a3+a0:a3
adc $a1, $a1
@@ -4279,6 +4312,7 @@ __ecp_nistz256_mul_by_2x:
mov $a3, 8*3($r_ptr)
ret
.cfi_endproc
.size __ecp_nistz256_mul_by_2x,.-__ecp_nistz256_mul_by_2x
___
}
+17 -1
View File
@@ -810,7 +810,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
|| !group->meth->field_mul(group, t2, t2, t0, ctx)
|| !BN_GF2m_add(t1, t2, t1)
|| !group->meth->field_mul(group, t2, p->X, t0, ctx)
|| !BN_GF2m_mod_inv(t2, t2, group->field, ctx)
|| !group->meth->field_inv(group, t2, t2, ctx)
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|| !group->meth->field_mul(group, r->X, r->Z, t2, ctx)
|| !BN_GF2m_add(t2, p->X, r->X)
@@ -889,6 +889,21 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
return ret;
}
/*-
* Computes the multiplicative inverse of a in GF(2^m), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* SCA hardening is with blinding: BN_GF2m_mod_inv does that.
*/
static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, BN_CTX *ctx)
{
int ret;
if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx)))
ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
return ret;
}
const EC_METHOD *EC_GF2m_simple_method(void)
{
static const EC_METHOD ret = {
@@ -929,6 +944,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
ec_GF2m_simple_field_mul,
ec_GF2m_simple_field_sqr,
ec_GF2m_simple_field_div,
ec_GF2m_simple_field_inv,
0, /* field_encode */
0, /* field_decode */
0, /* field_set_to_one */
+8 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* 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
@@ -66,6 +66,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
"ec_asn1_group2fieldid"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, 0),
"ec_GF2m_montgomery_point_multiply"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_FIELD_INV, 0),
"ec_GF2m_simple_field_inv"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
"ec_GF2m_simple_group_check_discriminant"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0),
@@ -90,6 +92,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
"ec_GFp_mont_field_decode"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_ENCODE, 0),
"ec_GFp_mont_field_encode"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_INV, 0),
"ec_GFp_mont_field_inv"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_MUL, 0),
"ec_GFp_mont_field_mul"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, 0),
@@ -124,6 +128,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
"ec_GFp_nist_group_set_curve"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0),
"ec_GFp_simple_blind_coordinates"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_FIELD_INV, 0),
"ec_GFp_simple_field_inv"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
"ec_GFp_simple_group_check_discriminant"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0),
@@ -287,6 +293,7 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BAD_SIGNATURE), "bad signature"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_BUFFER_TOO_SMALL), "buffer too small"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CANNOT_INVERT), "cannot invert"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_COORDINATES_OUT_OF_RANGE),
"coordinates out of range"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH),
+11
View File
@@ -154,6 +154,13 @@ struct ec_method_st {
int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
/*-
* 'field_inv' computes the multipicative inverse of a in the field,
* storing the result in r.
*
* If 'a' is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error.
*/
int (*field_inv) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
/* e.g. to Montgomery */
int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
@@ -390,6 +397,8 @@ int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
BN_CTX *ctx);
int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
@@ -413,6 +422,8 @@ int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+5
View File
@@ -364,6 +364,11 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group)
return group->curve_name;
}
const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
{
return group->field;
}
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
{
group->asn1_flag = flag;
+49
View File
@@ -50,6 +50,7 @@ const EC_METHOD *EC_GFp_mont_method(void)
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
0 /* field_div */ ,
ec_GFp_mont_field_inv,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
ec_GFp_mont_field_set_to_one,
@@ -206,6 +207,54 @@ int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
}
/*-
* Computes the multiplicative inverse of a in GF(p), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* We have a Mont structure, so SCA hardening is FLT inversion.
*/
int ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
if (group->field_data1 == NULL)
return 0;
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
return 0;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
/* Inverse in constant time with Fermats Little Theorem */
if (!BN_set_word(e, 2))
goto err;
if (!BN_sub(e, group->field, e))
goto err;
/*-
* Exponent e is public.
* No need for scatter-gather or BN_FLG_CONSTTIME.
*/
if (!BN_mod_exp_mont(r, a, e, group->field, ctx, group->field_data1))
goto err;
/* throw an error on zero */
if (BN_is_zero(r)) {
ECerr(EC_F_EC_GFP_MONT_FIELD_INV, EC_R_CANNOT_INVERT);
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, BN_CTX *ctx)
{
+1
View File
@@ -52,6 +52,7 @@ const EC_METHOD *EC_GFp_nist_method(void)
ec_GFp_nist_field_mul,
ec_GFp_nist_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
+1
View File
@@ -279,6 +279,7 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
ec_GFp_nist_field_mul,
ec_GFp_nist_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
+1
View File
@@ -1810,6 +1810,7 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
ec_GFp_nist_field_mul,
ec_GFp_nist_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
+1
View File
@@ -1647,6 +1647,7 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
ec_GFp_nist_field_mul,
ec_GFp_nist_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
+1
View File
@@ -1677,6 +1677,7 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
0, /* field_div */
ec_GFp_mont_field_inv,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
ec_GFp_mont_field_set_to_one,
+47 -2
View File
@@ -51,6 +51,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
ec_GFp_simple_field_mul,
ec_GFp_simple_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
@@ -553,7 +554,7 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
}
}
} else {
if (!BN_mod_inverse(Z_1, Z_, group->field, ctx)) {
if (!group->meth->field_inv(group, Z_1, Z_, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
ERR_R_BN_LIB);
goto err;
@@ -1266,7 +1267,7 @@ int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
* points[i]->Z by its inverse.
*/
if (!BN_mod_inverse(tmp, prod_Z[num - 1], group->field, ctx)) {
if (!group->meth->field_inv(group, tmp, prod_Z[num - 1], ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
goto err;
}
@@ -1369,6 +1370,50 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return BN_mod_sqr(r, a, group->field, ctx);
}
/*-
* Computes the multiplicative inverse of a in GF(p), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* Since we don't have a Mont structure here, SCA hardening is with blinding.
*/
int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
return 0;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
do {
if (!BN_priv_rand_range(e, group->field))
goto err;
} while (BN_is_zero(e));
/* r := a * e */
if (!group->meth->field_mul(group, r, a, e, ctx))
goto err;
/* r := 1/(a * e) */
if (!BN_mod_inverse(r, r, group->field, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
goto err;
}
/* r := e/(a * e) = 1/a */
if (!group->meth->field_mul(group, r, r, e, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*-
* Apply randomization of EC point projective coordinates:
*
-3
View File
@@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\
tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \
eng_openssl.c eng_cnf.c eng_dyn.c \
eng_rdrand.c
IF[{- !$disabled{devcryptoeng} -}]
SOURCE[../../libcrypto]=eng_devcrypto.c
ENDIF
+3 -1
View File
@@ -39,6 +39,7 @@
#include <openssl/kdferr.h>
#include <openssl/storeerr.h>
#include <openssl/esserr.h>
#include "internal/propertyerr.h"
int err_load_crypto_strings_int(void)
{
@@ -96,7 +97,8 @@ int err_load_crypto_strings_int(void)
ERR_load_ASYNC_strings() == 0 ||
#endif
ERR_load_KDF_strings() == 0 ||
ERR_load_OSSL_STORE_strings() == 0)
ERR_load_OSSL_STORE_strings() == 0 ||
ERR_load_PROP_strings() == 0)
return 0;
return 1;
+1
View File
@@ -35,6 +35,7 @@ L KDF include/openssl/kdf.h crypto/kdf/kdf_err.c
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
# additional header files to be scanned for function names
L NONE include/openssl/x509_vfy.h NONE
+50 -4
View File
@@ -521,6 +521,7 @@ EC_F_ECX_PUB_ENCODE:268:ecx_pub_encode
EC_F_EC_ASN1_GROUP2CURVE:153:ec_asn1_group2curve
EC_F_EC_ASN1_GROUP2FIELDID:154:ec_asn1_group2fieldid
EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY:208:ec_GF2m_montgomery_point_multiply
EC_F_EC_GF2M_SIMPLE_FIELD_INV:296:ec_GF2m_simple_field_inv
EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT:159:\
ec_GF2m_simple_group_check_discriminant
EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE:195:ec_GF2m_simple_group_set_curve
@@ -537,6 +538,7 @@ EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES:164:\
ec_GF2m_simple_set_compressed_coordinates
EC_F_EC_GFP_MONT_FIELD_DECODE:133:ec_GFp_mont_field_decode
EC_F_EC_GFP_MONT_FIELD_ENCODE:134:ec_GFp_mont_field_encode
EC_F_EC_GFP_MONT_FIELD_INV:297:ec_GFp_mont_field_inv
EC_F_EC_GFP_MONT_FIELD_MUL:131:ec_GFp_mont_field_mul
EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE:209:ec_GFp_mont_field_set_to_one
EC_F_EC_GFP_MONT_FIELD_SQR:132:ec_GFp_mont_field_sqr
@@ -557,6 +559,7 @@ EC_F_EC_GFP_NIST_FIELD_MUL:200:ec_GFp_nist_field_mul
EC_F_EC_GFP_NIST_FIELD_SQR:201:ec_GFp_nist_field_sqr
EC_F_EC_GFP_NIST_GROUP_SET_CURVE:202:ec_GFp_nist_group_set_curve
EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES:287:ec_GFp_simple_blind_coordinates
EC_F_EC_GFP_SIMPLE_FIELD_INV:298:ec_GFp_simple_field_inv
EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT:165:\
ec_GFp_simple_group_check_discriminant
EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE:166:ec_GFp_simple_group_set_curve
@@ -753,6 +756,9 @@ EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl
EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str
EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id
EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy
@@ -823,6 +829,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
EVP_F_PKEY_KDF_CTRL:227:pkey_kdf_ctrl
EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
EVP_F_PKEY_SET_TYPE:158:pkey_set_type
EVP_F_POLY1305_CTRL:216:poly1305_ctrl
@@ -830,7 +837,25 @@ EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
EVP_F_RC5_CTRL:125:rc5_ctrl
EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl
EVP_F_S390X_AES_GCM_TLS_CIPHER:208:s390x_aes_gcm_tls_cipher
EVP_F_SCRYPT_ALG:228:scrypt_alg
EVP_F_UPDATE:173:update
KDF_F_HKDF_EXTRACT:112:HKDF_Extract
KDF_F_KDF_HKDF_DERIVE:113:kdf_hkdf_derive
KDF_F_KDF_HKDF_NEW:114:kdf_hkdf_new
KDF_F_KDF_HKDF_SIZE:115:kdf_hkdf_size
KDF_F_KDF_MD2CTRL:116:kdf_md2ctrl
KDF_F_KDF_PBKDF2_CTRL_STR:117:kdf_pbkdf2_ctrl_str
KDF_F_KDF_PBKDF2_DERIVE:118:kdf_pbkdf2_derive
KDF_F_KDF_PBKDF2_NEW:119:kdf_pbkdf2_new
KDF_F_KDF_SCRYPT_CTRL_STR:120:kdf_scrypt_ctrl_str
KDF_F_KDF_SCRYPT_CTRL_UINT32:121:kdf_scrypt_ctrl_uint32
KDF_F_KDF_SCRYPT_CTRL_UINT64:122:kdf_scrypt_ctrl_uint64
KDF_F_KDF_SCRYPT_DERIVE:123:kdf_scrypt_derive
KDF_F_KDF_SCRYPT_NEW:124:kdf_scrypt_new
KDF_F_KDF_TLS1_PRF_CTRL_STR:125:kdf_tls1_prf_ctrl_str
KDF_F_KDF_TLS1_PRF_DERIVE:126:kdf_tls1_prf_derive
KDF_F_KDF_TLS1_PRF_NEW:127:kdf_tls1_prf_new
KDF_F_PBKDF2_SET_MEMBUF:128:pbkdf2_set_membuf
KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str
KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive
KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init
@@ -842,6 +867,7 @@ KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf
KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf
KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
@@ -1018,6 +1044,14 @@ PKCS7_F_PKCS7_SIGNER_INFO_SIGN:139:PKCS7_SIGNER_INFO_sign
PKCS7_F_PKCS7_SIGN_ADD_SIGNER:137:PKCS7_sign_add_signer
PKCS7_F_PKCS7_SIMPLE_SMIMECAP:119:PKCS7_simple_smimecap
PKCS7_F_PKCS7_VERIFY:117:PKCS7_verify
PROP_F_OSSL_PARSE_PROPERTY:100:ossl_parse_property
PROP_F_OSSL_PARSE_QUERY:101:ossl_parse_query
PROP_F_PARSE_HEX:102:parse_hex
PROP_F_PARSE_NAME:103:parse_name
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
RAND_F_DRBG_BYTES:101:drbg_bytes
RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
RAND_F_DRBG_SETUP:117:drbg_setup
@@ -2134,6 +2168,7 @@ EC_R_ASN1_ERROR:115:asn1 error
EC_R_BAD_SIGNATURE:156:bad signature
EC_R_BIGNUM_OUT_OF_RANGE:144:bignum out of range
EC_R_BUFFER_TOO_SMALL:100:buffer too small
EC_R_CANNOT_INVERT:165:cannot invert
EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range
EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh
EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing
@@ -2284,6 +2319,7 @@ EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized
EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
EVP_R_PBKDF2_ERROR:181:pbkdf2 error
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
@@ -2320,6 +2356,7 @@ KDF_R_MISSING_SEED:106:missing seed
KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
KDF_R_VALUE_ERROR:108:value error
KDF_R_VALUE_MISSING:102:value missing
KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size
OBJ_R_OID_EXISTS:102:oid exists
OBJ_R_UNKNOWN_NID:101:unknown nid
OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
@@ -2468,6 +2505,17 @@ PKCS7_R_UNSUPPORTED_CIPHER_TYPE:111:unsupported cipher type
PKCS7_R_UNSUPPORTED_CONTENT_TYPE:112:unsupported content type
PKCS7_R_WRONG_CONTENT_TYPE:113:wrong content type
PKCS7_R_WRONG_PKCS7_TYPE:114:wrong pkcs7 type
PROP_R_NAME_TOO_LONG:100:name too long
PROP_R_NOT_AN_ASCII_CHARACTER:101:not an ascii character
PROP_R_NOT_AN_HEXADECIMAL_DIGIT:102:not an hexadecimal digit
PROP_R_NOT_AN_IDENTIFIER:103:not an identifier
PROP_R_NOT_AN_OCTAL_DIGIT:104:not an octal digit
PROP_R_NOT_A_DECIMAL_DIGIT:105:not a decimal digit
PROP_R_NO_MATCHING_STRING_DELIMETER:106:no matching string delimeter
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
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
@@ -2748,8 +2796,8 @@ SSL_R_MISSING_SRP_PARAM:358:can't find SRP server param
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION:209:missing supported groups extension
SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key
SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key
SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS:293:mixed special operator with groups
SSL_R_NESTED_GROUP:294:nested group
SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA:293:\
mixed handshake and non handshake data
SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary
SSL_R_NOT_REPLACING_CERTIFICATE:289:not replacing certificate
SSL_R_NOT_SERVER:284:not server
@@ -2858,9 +2906,7 @@ SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines
SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines
SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message
SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data
SSL_R_UNEXPECTED_GROUP_CLOSE:295:unexpected group close
SSL_R_UNEXPECTED_MESSAGE:244:unexpected message
SSL_R_UNEXPECTED_OPERATOR_IN_GROUP:296:unexpected operator in group
SSL_R_UNEXPECTED_RECORD:245:unexpected record
SSL_R_UNINITIALIZED:276:uninitialized
SSL_R_UNKNOWN_ALERT_TYPE:246:unknown alert type
+2 -1
View File
@@ -9,7 +9,8 @@ SOURCE[../../libcrypto]=\
p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_allc.c c_alld.c evp_lib.c bio_ok.c \
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
pkey_kdf.c \
e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
e_chacha20_poly1305.c cmeth_lib.c \
+1 -1
View File
@@ -14,8 +14,8 @@
# include <openssl/evp.h>
# include <openssl/objects.h>
# include "evp_locl.h"
# include "internal/evp_int.h"
# include "evp_locl.h"
# include "internal/chacha.h"
typedef struct {
+1 -1
View File
@@ -11,8 +11,8 @@
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include "evp_locl.h"
#include "internal/evp_int.h"
#include "evp_locl.h"
static unsigned char conv_ascii2bin(unsigned char a,
const unsigned char *table);
+8 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* 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
@@ -60,6 +60,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
"EVP_EncryptFinal_ex"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL, 0), "EVP_KDF_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL_STR, 0), "EVP_KDF_ctrl_str"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW_ID, 0), "EVP_KDF_CTX_new_id"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
@@ -159,6 +162,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
"PKCS5_v2_PBKDF2_keyivgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
"PKCS5_v2_scrypt_keyivgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_KDF_CTRL, 0), "pkey_kdf_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_POLY1305_CTRL, 0), "poly1305_ctrl"},
@@ -167,6 +171,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
{ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_TLS_CIPHER, 0),
"s390x_aes_gcm_tls_cipher"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_SCRYPT_ALG, 0), "scrypt_alg"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"},
{0, NULL}
};
@@ -254,6 +259,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"operation not supported for this keytype"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED),
"operaton not initialized"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE),
"parameter too large"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING),
"partially overlapping buffers"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"},
+5
View File
@@ -46,6 +46,11 @@ struct evp_mac_ctx_st {
void *data; /* Individual method data */
} /* EVP_MAC_CTX */;
struct evp_kdf_ctx_st {
const EVP_KDF_METHOD *kmeth;
EVP_KDF_IMPL *impl; /* Algorithm-specific data */
} /* EVP_KDF_CTX */ ;
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md,
+1
View File
@@ -12,6 +12,7 @@
#include <openssl/evp.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
/* Password based encryption (PBE) functions */
+165
View File
@@ -0,0 +1,165 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include <openssl/kdf.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "evp_locl.h"
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
/* This array needs to be in order of NIDs */
static const EVP_KDF_METHOD *standard_methods[] = {
&pbkdf2_kdf_meth,
#ifndef OPENSSL_NO_SCRYPT
&scrypt_kdf_meth,
#endif
&tls1_prf_kdf_meth,
&hkdf_kdf_meth
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);
static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
const EVP_KDF_METHOD *const *b)
{
return ((*a)->type - (*b)->type);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);
static const EVP_KDF_METHOD *kdf_meth_find(int type)
{
EVP_KDF_METHOD tmp;
const EVP_KDF_METHOD *t = &tmp, **ret;
tmp.type = type;
ret = OBJ_bsearch_kmeth(&t, standard_methods,
OSSL_NELEM(standard_methods));
if (ret == NULL || *ret == NULL)
return NULL;
return *ret;
}
EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
{
EVP_KDF_CTX *ret;
const EVP_KDF_METHOD *kmeth;
kmeth = kdf_meth_find(id);
if (kmeth == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
EVP_KDF_CTX_free(ret);
return NULL;
}
ret->kmeth = kmeth;
return ret;
}
void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return;
ctx->kmeth->free(ctx->impl);
OPENSSL_free(ctx);
}
void EVP_KDF_reset(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->kmeth->reset != NULL)
ctx->kmeth->reset(ctx->impl);
}
int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
{
int ret;
va_list args;
va_start(args, cmd);
ret = EVP_KDF_vctrl(ctx, cmd, args);
va_end(args);
if (ret == -2)
EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
{
if (ctx == NULL)
return 0;
return ctx->kmeth->ctrl(ctx->impl, cmd, args);
}
int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
{
int ret;
if (ctx == NULL)
return 0;
if (ctx->kmeth->ctrl_str == NULL) {
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
if (ret == -2)
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return 0;
if (ctx->kmeth->size == NULL)
return SIZE_MAX;
return ctx->kmeth->size(ctx->impl);
}
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
{
if (ctx == NULL)
return 0;
return ctx->kmeth->derive(ctx->impl, key, keylen);
}
+28 -82
View File
@@ -1,5 +1,5 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1999-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
@@ -10,105 +10,51 @@
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
# include <openssl/x509.h>
# include <openssl/evp.h>
# include <openssl/hmac.h>
# include "evp_locl.h"
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/hmac.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
/* set this to print out info about the keygen algorithm */
/* #define OPENSSL_DEBUG_PKCS5V2 */
# ifdef OPENSSL_DEBUG_PKCS5V2
#ifdef OPENSSL_DEBUG_PKCS5V2
static void h__dump(const unsigned char *p, int len);
# endif
/*
* This is an implementation of PKCS#5 v2.0 password based encryption key
* derivation function PBKDF2. SHA1 version verified against test vectors
* posted by Peter Gutmann to the PKCS-TNG mailing list.
*/
#endif
int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, int keylen, unsigned char *out)
{
const char *empty = "";
unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
int cplen, j, k, tkeylen, mdlen;
unsigned long i = 1;
HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
int rv = 1;
EVP_KDF_CTX *kctx;
mdlen = EVP_MD_size(digest);
if (mdlen < 0)
return 0;
hctx_tpl = HMAC_CTX_new();
if (hctx_tpl == NULL)
return 0;
p = out;
tkeylen = keylen;
/* Keep documented behaviour. */
if (pass == NULL) {
pass = empty;
passlen = 0;
} else if (passlen == -1) {
passlen = strlen(pass);
}
if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) {
HMAC_CTX_free(hctx_tpl);
if (salt == NULL && saltlen == 0)
salt = (unsigned char *)empty;
kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2);
if (kctx == NULL)
return 0;
}
hctx = HMAC_CTX_new();
if (hctx == NULL) {
HMAC_CTX_free(hctx_tpl);
return 0;
}
while (tkeylen) {
if (tkeylen > mdlen)
cplen = mdlen;
else
cplen = tkeylen;
/*
* We are unlikely to ever use more than 256 blocks (5120 bits!) but
* just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return 0;
}
if (!HMAC_Update(hctx, salt, saltlen)
|| !HMAC_Update(hctx, itmp, 4)
|| !HMAC_Final(hctx, digtmp, NULL)) {
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return 0;
}
memcpy(p, digtmp, cplen);
for (j = 1; j < iter; j++) {
if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return 0;
}
if (!HMAC_Update(hctx, digtmp, mdlen)
|| !HMAC_Final(hctx, digtmp, NULL)) {
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return 0;
}
for (k = 0; k < cplen; k++)
p[k] ^= digtmp[k];
}
tkeylen -= cplen;
i++;
p += cplen;
}
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT,
salt, (size_t)saltlen) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, iter) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, digest) != 1
|| EVP_KDF_derive(kctx, out, keylen) != 1)
rv = 0;
EVP_KDF_CTX_free(kctx);
# ifdef OPENSSL_DEBUG_PKCS5V2
fprintf(stderr, "Password:\n");
h__dump(pass, passlen);
@@ -118,7 +64,7 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
fprintf(stderr, "Key:\n");
h__dump(out, keylen);
# endif
return 1;
return rv;
}
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
+23 -214
View File
@@ -7,135 +7,12 @@
* https://www.openssl.org/source/license.html
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/numbers.h"
#include <openssl/kdf.h>
#ifndef OPENSSL_NO_SCRYPT
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
static void salsa208_word_specification(uint32_t inout[16])
{
int i;
uint32_t x[16];
memcpy(x, inout, sizeof(x));
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i)
inout[i] += x[i];
OPENSSL_cleanse(x, sizeof(x));
}
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
{
uint64_t i, j;
uint32_t X[16], *pB;
memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
pB = B;
for (i = 0; i < r * 2; i++) {
for (j = 0; j < 16; j++)
X[j] ^= *pB++;
salsa208_word_specification(X);
memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
}
OPENSSL_cleanse(X, sizeof(X));
}
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
uint32_t *X, uint32_t *T, uint32_t *V)
{
unsigned char *pB;
uint32_t *pV;
uint64_t i, k;
/* Convert from little endian input */
for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
*pV = *pB++;
*pV |= *pB++ << 8;
*pV |= *pB++ << 16;
*pV |= (uint32_t)*pB++ << 24;
}
for (i = 1; i < N; i++, pV += 32 * r)
scryptBlockMix(pV, pV - 32 * r, r);
scryptBlockMix(X, V + (N - 1) * 32 * r, r);
for (i = 0; i < N; i++) {
uint32_t j;
j = X[16 * (2 * r - 1)] % N;
pV = V + 32 * r * j;
for (k = 0; k < 32 * r; k++)
T[k] = X[k] ^ *pV++;
scryptBlockMix(X, T, r);
}
/* Convert output to little endian */
for (i = 0, pB = B; i < 32 * r; i++) {
uint32_t xtmp = X[i];
*pB++ = xtmp & 0xff;
*pB++ = (xtmp >> 8) & 0xff;
*pB++ = (xtmp >> 16) & 0xff;
*pB++ = (xtmp >> 24) & 0xff;
}
}
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
/*
* Maximum power of two that will fit in uint64_t: this should work on
* most (all?) platforms.
*/
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
/*
* Maximum value of p * r:
* p <= ((2^32-1) * hLen) / MFLen =>
* p <= ((2^32-1) * 32) / (128 * r) =>
* p * r <= (2^30-1)
*
*/
#define SCRYPT_PR_MAX ((1 << 30) - 1)
/*
* Maximum permitted memory allow this to be overridden with Configuration
* option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible.
@@ -160,107 +37,39 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen)
{
int rv = 0;
unsigned char *B;
uint32_t *X, *V, *T;
uint64_t i, Blen, Vlen;
const char *empty = "";
int rv = 1;
EVP_KDF_CTX *kctx;
/* Sanity check parameters */
/* initial check, r,p must be non zero, N >= 2 and a power of 2 */
if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
return 0;
/* Check p * r < SCRYPT_PR_MAX avoiding overflow */
if (p > SCRYPT_PR_MAX / r) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
if (r > UINT32_MAX || p > UINT32_MAX) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PARAMETER_TOO_LARGE);
return 0;
}
/*
* Need to check N: if 2^(128 * r / 8) overflows limit this is
* automatically satisfied since N <= UINT64_MAX.
*/
if (16 * r <= LOG2_UINT64_MAX) {
if (N >= (((uint64_t)1) << (16 * r))) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* Maintain existing behaviour. */
if (pass == NULL) {
pass = empty;
passlen = 0;
}
/* Memory checks: check total allocated buffer size fits in uint64_t */
/*
* B size in section 5 step 1.S
* Note: we know p * 128 * r < UINT64_MAX because we already checked
* p * r < SCRYPT_PR_MAX
*/
Blen = p * 128 * r;
/*
* Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
* have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
*/
if (Blen > INT_MAX) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
* This is combined size V, X and T (section 4)
*/
i = UINT64_MAX / (32 * sizeof(uint32_t));
if (N + 2 > i / r) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
/* check total allocated size fits in uint64_t */
if (Blen > UINT64_MAX - Vlen) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
if (maxmem == 0)
maxmem = SCRYPT_MAX_MEM;
/* Check that the maximum memory doesn't exceed a size_t limits */
if (maxmem > SIZE_MAX)
maxmem = SIZE_MAX;
if (Blen + Vlen > maxmem) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
if (kctx == NULL)
return 0;
}
/* If no key return to indicate parameters are OK */
if (key == NULL)
return 1;
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT,
salt, (size_t)saltlen) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, N) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)r) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)p) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, maxmem) != 1
|| EVP_KDF_derive(kctx, key, keylen) != 1)
rv = 0;
B = OPENSSL_malloc((size_t)(Blen + Vlen));
if (B == NULL) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, ERR_R_MALLOC_FAILURE);
return 0;
}
X = (uint32_t *)(B + Blen);
T = X + 32 * r;
V = T + 32 * r;
if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
(int)Blen, B) == 0)
goto err;
for (i = 0; i < p; i++)
scryptROMix(B + 128 * r * i, r, N, X, T, V);
if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
keylen, key) == 0)
goto err;
rv = 1;
err:
if (rv == 0)
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PBKDF2_ERROR);
OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
EVP_KDF_CTX_free(kctx);
return rv;
}
#endif
+255
View File
@@ -0,0 +1,255 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/kdf.h>
#include "internal/evp_int.h"
static int pkey_kdf_init(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx;
kctx = EVP_KDF_CTX_new_id(ctx->pmeth->pkey_id);
if (kctx == NULL)
return 0;
ctx->data = kctx;
return 1;
}
static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx = ctx->data;
EVP_KDF_CTX_free(kctx);
}
static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
EVP_KDF_CTX *kctx = ctx->data;
uint64_t u64_value;
int cmd;
int ret;
switch (type) {
case EVP_PKEY_CTRL_PASS:
cmd = EVP_KDF_CTRL_SET_PASS;
break;
case EVP_PKEY_CTRL_HKDF_SALT:
case EVP_PKEY_CTRL_SCRYPT_SALT:
cmd = EVP_KDF_CTRL_SET_SALT;
break;
case EVP_PKEY_CTRL_TLS_MD:
case EVP_PKEY_CTRL_HKDF_MD:
cmd = EVP_KDF_CTRL_SET_MD;
break;
case EVP_PKEY_CTRL_TLS_SECRET:
cmd = EVP_KDF_CTRL_SET_TLS_SECRET;
ret = EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_RESET_TLS_SEED);
if (ret < 1)
return ret;
break;
case EVP_PKEY_CTRL_TLS_SEED:
cmd = EVP_KDF_CTRL_ADD_TLS_SEED;
break;
case EVP_PKEY_CTRL_HKDF_KEY:
cmd = EVP_KDF_CTRL_SET_KEY;
break;
case EVP_PKEY_CTRL_HKDF_INFO:
cmd = EVP_KDF_CTRL_ADD_HKDF_INFO;
break;
case EVP_PKEY_CTRL_HKDF_MODE:
cmd = EVP_KDF_CTRL_SET_HKDF_MODE;
break;
case EVP_PKEY_CTRL_SCRYPT_N:
cmd = EVP_KDF_CTRL_SET_SCRYPT_N;
break;
case EVP_PKEY_CTRL_SCRYPT_R:
cmd = EVP_KDF_CTRL_SET_SCRYPT_R;
break;
case EVP_PKEY_CTRL_SCRYPT_P:
cmd = EVP_KDF_CTRL_SET_SCRYPT_P;
break;
case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
cmd = EVP_KDF_CTRL_SET_MAXMEM_BYTES;
break;
default:
return -2;
}
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
case EVP_KDF_CTRL_SET_SALT:
case EVP_KDF_CTRL_SET_KEY:
case EVP_KDF_CTRL_SET_TLS_SECRET:
case EVP_KDF_CTRL_ADD_TLS_SEED:
case EVP_KDF_CTRL_ADD_HKDF_INFO:
return EVP_KDF_ctrl(kctx, cmd, (const unsigned char *)p2, (size_t)p1);
case EVP_KDF_CTRL_SET_MD:
return EVP_KDF_ctrl(kctx, cmd, (const EVP_MD *)p2);
case EVP_KDF_CTRL_SET_HKDF_MODE:
return EVP_KDF_ctrl(kctx, cmd, (int)p1);
case EVP_KDF_CTRL_SET_SCRYPT_R:
case EVP_KDF_CTRL_SET_SCRYPT_P:
u64_value = *(uint64_t *)p2;
if (u64_value > UINT32_MAX) {
EVPerr(EVP_F_PKEY_KDF_CTRL, EVP_R_PARAMETER_TOO_LARGE);
return 0;
}
return EVP_KDF_ctrl(kctx, cmd, (uint32_t)u64_value);
case EVP_KDF_CTRL_SET_SCRYPT_N:
case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
return EVP_KDF_ctrl(kctx, cmd, *(uint64_t *)p2);
default:
return 0;
}
}
static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
{
EVP_KDF_CTX *kctx = ctx->data;
if (strcmp(type, "md") == 0)
return EVP_KDF_ctrl_str(kctx, "digest", value);
return EVP_KDF_ctrl_str(kctx, type, value);
}
static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx = ctx->data;
EVP_KDF_reset(kctx);
return 1;
}
/*
* For fixed-output algorithms the keylen parameter is an "out" parameter
* otherwise it is an "in" parameter.
*/
static int pkey_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
EVP_KDF_CTX *kctx = ctx->data;
size_t outlen = EVP_KDF_size(kctx);
if (outlen == 0 || outlen == SIZE_MAX) {
/* Variable-output algorithm */
if (key == NULL)
return 0;
} else {
/* Fixed-output algorithm */
*keylen = outlen;
if (key == NULL)
return 1;
}
return EVP_KDF_derive(kctx, key, *keylen);
}
#ifndef OPENSSL_NO_SCRYPT
const EVP_PKEY_METHOD scrypt_pkey_meth = {
EVP_PKEY_SCRYPT,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};
#endif
const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
EVP_PKEY_TLS1_PRF,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};
const EVP_PKEY_METHOD hkdf_pkey_meth = {
EVP_PKEY_HKDF,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};
+30
View File
@@ -362,6 +362,36 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
ad->sk = NULL;
}
/*
* Allocate a given CRYPTO_EX_DATA item using the class specific allocation
* function
*/
int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
int idx)
{
EX_CALLBACK *f;
EX_CALLBACKS *ip;
void *curval;
curval = CRYPTO_get_ex_data(ad, idx);
/* Already there, no need to allocate */
if (curval != NULL)
return 1;
ip = get_and_lock(class_index);
f = sk_EX_CALLBACK_value(ip->meth, idx);
CRYPTO_THREAD_unlock(ex_data_lock);
/*
* This should end up calling CRYPTO_set_ex_data(), which allocates
* everything necessary to support placing the new data in the right spot.
*/
f->new_func(obj, curval, ad, idx, f->argl, f->argp);
return 1;
}
/*
* For a given CRYPTO_EX_DATA variable, set the value corresponding to a
* particular index in the class used by this variable
+18
View File
@@ -151,6 +151,24 @@ const EVP_MD *evp_keccak_kmac256(void);
*/
int EVP_add_mac(const EVP_MAC *mac);
/* struct evp_kdf_impl_st is defined by the implementation */
typedef struct evp_kdf_impl_st EVP_KDF_IMPL;
typedef struct {
int type;
EVP_KDF_IMPL *(*new) (void);
void (*free) (EVP_KDF_IMPL *impl);
void (*reset) (EVP_KDF_IMPL *impl);
int (*ctrl) (EVP_KDF_IMPL *impl, int cmd, va_list args);
int (*ctrl_str) (EVP_KDF_IMPL *impl, const char *type, const char *value);
size_t (*size) (EVP_KDF_IMPL *impl);
int (*derive) (EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen);
} EVP_KDF_METHOD;
extern const EVP_KDF_METHOD pbkdf2_kdf_meth;
extern const EVP_KDF_METHOD scrypt_kdf_meth;
extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
extern const EVP_KDF_METHOD hkdf_kdf_meth;
struct evp_md_st {
int type;
int pkey_type;
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_SPARSE_ARRAY_H
# define HEADER_SPARSE_ARRAY_H
# include <openssl/e_os2.h>
# ifdef __cplusplus
extern "C" {
# endif
# define SPARSE_ARRAY_OF(type) struct sparse_array_st_ ## type
# define DEFINE_SPARSE_ARRAY_OF(type) \
SPARSE_ARRAY_OF(type); \
static ossl_unused ossl_inline SPARSE_ARRAY_OF(type) * \
ossl_sa_##type##_new(void) \
{ \
return (SPARSE_ARRAY_OF(type) *)OPENSSL_SA_new(); \
} \
static ossl_unused ossl_inline void ossl_sa_##type##_free(SPARSE_ARRAY_OF(type) *sa) \
{ \
OPENSSL_SA_free((OPENSSL_SA *)sa); \
} \
static ossl_unused ossl_inline void ossl_sa_##type##_free_leaves(SPARSE_ARRAY_OF(type) *sa) \
{ \
OPENSSL_SA_free_leaves((OPENSSL_SA *)sa); \
} \
static ossl_unused ossl_inline size_t ossl_sa_##type##_num(const SPARSE_ARRAY_OF(type) *sa) \
{ \
return OPENSSL_SA_num((OPENSSL_SA *)sa); \
} \
static ossl_unused ossl_inline void ossl_sa_##type##_doall(const SPARSE_ARRAY_OF(type) *sa, \
void (*leaf)(size_t, type *)) \
{ \
OPENSSL_SA_doall((OPENSSL_SA *)sa, (void (*)(size_t, void *))leaf); \
} \
static ossl_unused ossl_inline \
void ossl_sa_##type##_doall_arg(const SPARSE_ARRAY_OF(type) *sa, \
void (*leaf)(size_t, type *, void *), \
void *arg) \
{ \
OPENSSL_SA_doall_arg((OPENSSL_SA *)sa, (void (*)(size_t, void *, void *))leaf, \
arg); \
} \
static ossl_unused ossl_inline type *ossl_sa_##type##_get(const SPARSE_ARRAY_OF(type) *sa, \
size_t n) \
{ \
return (type *)OPENSSL_SA_get((OPENSSL_SA *)sa, n); \
} \
static ossl_unused ossl_inline int ossl_sa_##type##_set(SPARSE_ARRAY_OF(type) *sa, \
size_t n, type *val) \
{ \
return OPENSSL_SA_set((OPENSSL_SA *)sa, n, (void *)val); \
} \
SPARSE_ARRAY_OF(type)
typedef struct sparse_array_st OPENSSL_SA;
OPENSSL_SA *OPENSSL_SA_new(void);
void OPENSSL_SA_free(OPENSSL_SA *sa);
void OPENSSL_SA_free_leaves(OPENSSL_SA *sa);
size_t OPENSSL_SA_num(const OPENSSL_SA *sa);
void OPENSSL_SA_doall(const OPENSSL_SA *sa, void (*leaf)(size_t, void *));
void OPENSSL_SA_doall_arg(const OPENSSL_SA *sa,
void (*leaf)(size_t, void *, void *), void *);
void *OPENSSL_SA_get(const OPENSSL_SA *sa, size_t n);
int OPENSSL_SA_set(OPENSSL_SA *sa, size_t n, void *val);
# ifdef __cplusplus
}
# endif
#endif
+17 -17
View File
@@ -353,18 +353,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
engine_load_openssl_int();
return 1;
}
# ifndef OPENSSL_NO_DEVCRYPTOENG
static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
"engine_load_devcrypto_int()\n");
# endif
engine_load_devcrypto_int();
return 1;
}
# endif
# ifndef OPENSSL_NO_RDRAND
static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
@@ -389,6 +377,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)
return 1;
}
# ifndef OPENSSL_NO_STATIC_ENGINE
# ifndef OPENSSL_NO_DEVCRYPTOENG
static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
"engine_load_devcrypto_int()\n");
# endif
engine_load_devcrypto_int();
return 1;
}
# endif
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
@@ -747,11 +747,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
&& !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
return 0;
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
&& !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
return 0;
# endif
# ifndef OPENSSL_NO_RDRAND
if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
&& !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
@@ -761,6 +756,11 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
&& !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
return 0;
# ifndef OPENSSL_NO_STATIC_ENGINE
# ifndef OPENSSL_NO_DEVCRYPTOENG
if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
&& !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
return 0;
# endif
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
&& !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
+1 -1
View File
@@ -1,3 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
tls1_prf.c kdf_err.c hkdf.c scrypt.c
tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c
+150 -176
View File
@@ -8,32 +8,33 @@
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "kdf_local.h"
#define HKDF_MAXBUF 1024
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static void kdf_hkdf_reset(EVP_KDF_IMPL *impl);
static int HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static int HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t prk_len);
static int HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len);
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
typedef struct {
struct evp_kdf_impl_st {
int mode;
const EVP_MD *md;
unsigned char *salt;
@@ -42,230 +43,208 @@ typedef struct {
size_t key_len;
unsigned char info[HKDF_MAXBUF];
size_t info_len;
} HKDF_PKEY_CTX;
};
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_hkdf_new(void)
{
HKDF_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->data = kctx;
return 1;
if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
KDFerr(KDF_F_KDF_HKDF_NEW, ERR_R_MALLOC_FAILURE);
return impl;
}
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
static void kdf_hkdf_free(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_clear_free(kctx->key, kctx->key_len);
OPENSSL_cleanse(kctx->info, kctx->info_len);
OPENSSL_free(kctx);
kdf_hkdf_reset(impl);
OPENSSL_free(impl);
}
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static void kdf_hkdf_reset(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->key, impl->key_len);
OPENSSL_cleanse(impl->info, impl->info_len);
memset(impl, 0, sizeof(*impl));
}
switch (type) {
case EVP_PKEY_CTRL_HKDF_MD:
if (p2 == NULL)
static int kdf_hkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
kctx->md = p2;
impl->md = md;
return 1;
case EVP_PKEY_CTRL_HKDF_MODE:
kctx->mode = p1;
case EVP_KDF_CTRL_SET_HKDF_MODE:
impl->mode = va_arg(args, int);
return 1;
case EVP_PKEY_CTRL_HKDF_SALT:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0)
OPENSSL_free(impl->salt);
impl->salt = OPENSSL_memdup(p, len);
if (impl->salt == NULL)
return 0;
if (kctx->salt != NULL)
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
kctx->salt = OPENSSL_memdup(p2, p1);
if (kctx->salt == NULL)
return 0;
kctx->salt_len = p1;
impl->salt_len = len;
return 1;
case EVP_PKEY_CTRL_HKDF_KEY:
if (p1 < 0)
case EVP_KDF_CTRL_SET_KEY:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
OPENSSL_clear_free(impl->key, impl->key_len);
impl->key = OPENSSL_memdup(p, len);
if (impl->key == NULL)
return 0;
if (kctx->key != NULL)
OPENSSL_clear_free(kctx->key, kctx->key_len);
kctx->key = OPENSSL_memdup(p2, p1);
if (kctx->key == NULL)
return 0;
kctx->key_len = p1;
impl->key_len = len;
return 1;
case EVP_PKEY_CTRL_HKDF_INFO:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_RESET_HKDF_INFO:
OPENSSL_cleanse(impl->info, impl->info_len);
impl->info_len = 0;
return 1;
case EVP_KDF_CTRL_ADD_HKDF_INFO:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
if (len > (HKDF_MAXBUF - impl->info_len))
return 0;
memcpy(kctx->info + kctx->info_len, p2, p1);
kctx->info_len += p1;
memcpy(impl->info + impl->info_len, p, len);
impl->info_len += len;
return 1;
default:
return -2;
}
}
static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
static int kdf_hkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (strcmp(type, "mode") == 0) {
int mode;
if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
else if (strcmp(value, "EXTRACT_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
else if (strcmp(value, "EXPAND_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
else
return 0;
return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
return call_ctrl(kdf_hkdf_ctrl, impl, EVP_KDF_CTRL_SET_HKDF_MODE, mode);
}
if (strcmp(type, "md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MD, value);
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
if (strcmp(type, "salt") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "hexsalt") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "key") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
if (strcmp(type, "hexkey") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
if (strcmp(type, "info") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
value);
if (strcmp(type, "hexinfo") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
value);
KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
static size_t kdf_hkdf_size(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
if (impl->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
return SIZE_MAX;
OPENSSL_clear_free(kctx->key, kctx->key_len);
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_cleanse(kctx->info, kctx->info_len);
memset(kctx, 0, sizeof(*kctx));
return 1;
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_HKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
return EVP_MD_size(impl->md);
}
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
HKDF_PKEY_CTX *kctx = ctx->data;
if (kctx->md == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (kctx->key == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
if (impl->key == NULL) {
KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_KEY);
return 0;
}
switch (kctx->mode) {
case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, kctx->info, kctx->info_len, key,
*keylen) != NULL;
switch (impl->mode) {
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
return HKDF(impl->md, impl->salt, impl->salt_len, impl->key,
impl->key_len, impl->info, impl->info_len, key,
keylen);
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
if (key == NULL) {
*keylen = EVP_MD_size(kctx->md);
return 1;
}
return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, key, keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
return HKDF_Extract(impl->md, impl->salt, impl->salt_len, impl->key,
impl->key_len, key, keylen);
case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
kctx->info_len, key, *keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
return HKDF_Expand(impl->md, impl->key, impl->key_len, impl->info,
impl->info_len, key, keylen);
default:
return 0;
}
}
const EVP_PKEY_METHOD hkdf_pkey_meth = {
EVP_PKEY_HKDF,
0,
pkey_hkdf_init,
0,
pkey_hkdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_hkdf_derive_init,
pkey_hkdf_derive,
pkey_hkdf_ctrl,
pkey_hkdf_ctrl_str
const EVP_KDF_METHOD hkdf_kdf_meth = {
EVP_KDF_HKDF,
kdf_hkdf_new,
kdf_hkdf_free,
kdf_hkdf_reset,
kdf_hkdf_ctrl,
kdf_hkdf_ctrl_str,
kdf_hkdf_size,
kdf_hkdf_derive
};
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
static int HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
unsigned char prk[EVP_MAX_MD_SIZE];
unsigned char *ret;
size_t prk_len;
int ret;
size_t prk_len = EVP_MD_size(evp_md);
if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
return NULL;
if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, prk_len))
return 0;
ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
OPENSSL_cleanse(prk, sizeof(prk));
@@ -273,43 +252,38 @@ static unsigned char *HKDF(const EVP_MD *evp_md,
return ret;
}
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len)
static int HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t prk_len)
{
unsigned int tmp_len;
if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
return NULL;
*prk_len = tmp_len;
return prk;
if (prk_len != (size_t)EVP_MD_size(evp_md)) {
KDFerr(KDF_F_HKDF_EXTRACT, KDF_R_WRONG_OUTPUT_BUFFER_SIZE);
return 0;
}
return HMAC(evp_md, salt, salt_len, key, key_len, prk, NULL) != NULL;
}
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
static int HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
HMAC_CTX *hmac;
unsigned char *ret = NULL;
int ret = 0;
unsigned int i;
unsigned char prev[EVP_MAX_MD_SIZE];
size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
size_t n = okm_len / dig_len;
if (okm_len % dig_len)
n++;
if (n > 255 || okm == NULL)
return NULL;
return 0;
if ((hmac = HMAC_CTX_new()) == NULL)
return NULL;
return 0;
if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
goto err;
@@ -343,7 +317,7 @@ static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
done_len += copy_len;
}
ret = okm;
ret = 1;
err:
OPENSSL_cleanse(prev, sizeof(prev));
+27 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* 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
@@ -14,6 +14,29 @@
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA KDF_str_functs[] = {
{ERR_PACK(ERR_LIB_KDF, KDF_F_HKDF_EXTRACT, 0), "HKDF_Extract"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_DERIVE, 0), "kdf_hkdf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_NEW, 0), "kdf_hkdf_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_SIZE, 0), "kdf_hkdf_size"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_MD2CTRL, 0), "kdf_md2ctrl"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_CTRL_STR, 0),
"kdf_pbkdf2_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_DERIVE, 0), "kdf_pbkdf2_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_NEW, 0), "kdf_pbkdf2_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_STR, 0),
"kdf_scrypt_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT32, 0),
"kdf_scrypt_ctrl_uint32"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT64, 0),
"kdf_scrypt_ctrl_uint64"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_DERIVE, 0), "kdf_scrypt_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_NEW, 0), "kdf_scrypt_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_CTRL_STR, 0),
"kdf_tls1_prf_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_DERIVE, 0),
"kdf_tls1_prf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_NEW, 0), "kdf_tls1_prf_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PBKDF2_SET_MEMBUF, 0), "pbkdf2_set_membuf"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_INIT, 0), "pkey_hkdf_init"},
@@ -30,6 +53,7 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0),
"pkey_tls1_prf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_SCRYPT_SET_MEMBUF, 0), "scrypt_set_membuf"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
{0, NULL}
};
@@ -50,6 +74,8 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
"unknown parameter type"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_OUTPUT_BUFFER_SIZE),
"wrong output buffer size"},
{0, NULL}
};
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
EVP_KDF_IMPL *impl, int cmd, ...);
int kdf_str2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *str);
int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *hex);
int kdf_md2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *md_name);
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <stdarg.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "kdf_local.h"
int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
EVP_KDF_IMPL *impl, int cmd, ...)
{
int ret;
va_list args;
va_start(args, cmd);
ret = ctrl(impl, cmd, args);
va_end(args);
return ret;
}
/* Utility functions to send a string or hex string to a ctrl */
int kdf_str2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *str)
{
return call_ctrl(ctrl, impl, cmd, (const unsigned char *)str, strlen(str));
}
int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *hex)
{
unsigned char *bin;
long binlen;
int ret = -1;
bin = OPENSSL_hexstr2buf(hex, &binlen);
if (bin == NULL)
return 0;
if (binlen <= INT_MAX)
ret = call_ctrl(ctrl, impl, cmd, bin, (size_t)binlen);
OPENSSL_free(bin);
return ret;
}
/* Pass a message digest to a ctrl */
int kdf_md2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *md_name)
{
const EVP_MD *md;
if (md_name == NULL || (md = EVP_get_digestbyname(md_name)) == NULL) {
KDFerr(KDF_F_KDF_MD2CTRL, KDF_R_INVALID_DIGEST);
return 0;
}
return call_ctrl(ctrl, impl, cmd, md);
}
+264
View File
@@ -0,0 +1,264 @@
/*
* Copyright 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 <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "kdf_local.h"
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl);
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl);
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, unsigned char *key,
size_t keylen);
struct evp_kdf_impl_st {
unsigned char *pass;
size_t pass_len;
unsigned char *salt;
size_t salt_len;
int iter;
const EVP_MD *md;
};
static EVP_KDF_IMPL *kdf_pbkdf2_new(void)
{
EVP_KDF_IMPL *impl;
impl = OPENSSL_zalloc(sizeof(*impl));
if (impl == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
kdf_pbkdf2_init(impl);
return impl;
}
static void kdf_pbkdf2_free(EVP_KDF_IMPL *impl)
{
kdf_pbkdf2_reset(impl);
OPENSSL_free(impl);
}
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl)
{
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->pass, impl->pass_len);
memset(impl, 0, sizeof(*impl));
kdf_pbkdf2_init(impl);
}
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl)
{
impl->iter = PKCS5_DEFAULT_ITER;
impl->md = EVP_sha1();
}
static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
size_t new_buflen)
{
if (new_buffer == NULL)
return 1;
OPENSSL_clear_free(*buffer, *buflen);
if (new_buflen > 0) {
*buffer = OPENSSL_memdup(new_buffer, new_buflen);
} else {
*buffer = OPENSSL_malloc(1);
}
if (*buffer == NULL) {
KDFerr(KDF_F_PBKDF2_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
return 0;
}
*buflen = new_buflen;
return 1;
}
static int kdf_pbkdf2_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
int iter;
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return pbkdf2_set_membuf(&impl->pass, &impl->pass_len, p, len);
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return pbkdf2_set_membuf(&impl->salt, &impl->salt_len, p, len);
case EVP_KDF_CTRL_SET_ITER:
iter = va_arg(args, int);
if (iter < 1)
return 0;
impl->iter = iter;
return 1;
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
impl->md = md;
return 1;
default:
return -2;
}
}
static int kdf_pbkdf2_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "pass") == 0)
return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "hexpass") == 0)
return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "salt") == 0)
return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "hexsalt") == 0)
return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "iter") == 0)
return call_ctrl(kdf_pbkdf2_ctrl, impl, EVP_KDF_CTRL_SET_ITER,
atoi(value));
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_MD, value);
return -2;
}
static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
if (impl->pass == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_PASS);
return 0;
}
if (impl->salt == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_SALT);
return 0;
}
return pkcs5_pbkdf2_alg((char *)impl->pass, impl->pass_len,
impl->salt, impl->salt_len, impl->iter,
impl->md, key, keylen);
}
const EVP_KDF_METHOD pbkdf2_kdf_meth = {
EVP_KDF_PBKDF2,
kdf_pbkdf2_new,
kdf_pbkdf2_free,
kdf_pbkdf2_reset,
kdf_pbkdf2_ctrl,
kdf_pbkdf2_ctrl_str,
NULL,
kdf_pbkdf2_derive
};
/*
* This is an implementation of PKCS#5 v2.0 password based encryption key
* derivation function PBKDF2. SHA1 version verified against test vectors
* posted by Peter Gutmann to the PKCS-TNG mailing list.
*/
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, unsigned char *key,
size_t keylen)
{
int ret = 0;
unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
int cplen, j, k, tkeylen, mdlen;
unsigned long i = 1;
HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
mdlen = EVP_MD_size(digest);
if (mdlen < 0)
return 0;
hctx_tpl = HMAC_CTX_new();
if (hctx_tpl == NULL)
return 0;
p = key;
tkeylen = keylen;
if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
goto err;
hctx = HMAC_CTX_new();
if (hctx == NULL)
goto err;
while (tkeylen) {
if (tkeylen > mdlen)
cplen = mdlen;
else
cplen = tkeylen;
/*
* We are unlikely to ever use more than 256 blocks (5120 bits!) but
* just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
if (!HMAC_CTX_copy(hctx, hctx_tpl))
goto err;
if (!HMAC_Update(hctx, salt, saltlen)
|| !HMAC_Update(hctx, itmp, 4)
|| !HMAC_Final(hctx, digtmp, NULL))
goto err;
memcpy(p, digtmp, cplen);
for (j = 1; j < iter; j++) {
if (!HMAC_CTX_copy(hctx, hctx_tpl))
goto err;
if (!HMAC_Update(hctx, digtmp, mdlen)
|| !HMAC_Final(hctx, digtmp, NULL))
goto err;
for (k = 0; k < cplen; k++)
p[k] ^= digtmp[k];
}
tkeylen -= cplen;
i++;
p += cplen;
}
ret = 1;
err:
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return ret;
}
+359 -119
View File
@@ -8,25 +8,34 @@
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include "internal/cryptlib.h"
#include <openssl/kdf.h>
#include <openssl/err.h>
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "kdf_local.h"
#ifndef OPENSSL_NO_SCRYPT
static void kdf_scrypt_reset(EVP_KDF_IMPL *impl);
static void kdf_scrypt_init(EVP_KDF_IMPL *impl);
static int atou64(const char *nptr, uint64_t *result);
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen);
typedef struct {
struct evp_kdf_impl_st {
unsigned char *pass;
size_t pass_len;
unsigned char *salt;
size_t salt_len;
uint64_t N, r, p;
uint64_t N;
uint32_t r, p;
uint64_t maxmem_bytes;
} SCRYPT_PKEY_CTX;
};
/* Custom uint64_t parser since we do not have strtoull */
static int atou64(const char *nptr, uint64_t *result)
@@ -53,51 +62,53 @@ static int atou64(const char *nptr, uint64_t *result)
return 1;
}
static int pkey_scrypt_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_scrypt_new(void)
{
SCRYPT_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
kctx = OPENSSL_zalloc(sizeof(*kctx));
if (kctx == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_INIT, ERR_R_MALLOC_FAILURE);
return 0;
impl = OPENSSL_zalloc(sizeof(*impl));
if (impl == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
kdf_scrypt_init(impl);
return impl;
}
static void kdf_scrypt_free(EVP_KDF_IMPL *impl)
{
kdf_scrypt_reset(impl);
OPENSSL_free(impl);
}
static void kdf_scrypt_reset(EVP_KDF_IMPL *impl)
{
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->pass, impl->pass_len);
memset(impl, 0, sizeof(*impl));
kdf_scrypt_init(impl);
}
static void kdf_scrypt_init(EVP_KDF_IMPL *impl)
{
/* Default values are the most conservative recommendation given in the
* original paper of C. Percival. Derivation uses roughly 1 GiB of memory
* for this parameter choice (approx. 128 * r * (N + p) bytes).
* for this parameter choice (approx. 128 * r * N * p bytes).
*/
kctx->N = 1 << 20;
kctx->r = 8;
kctx->p = 1;
kctx->maxmem_bytes = 1025 * 1024 * 1024;
ctx->data = kctx;
return 1;
impl->N = 1 << 20;
impl->r = 8;
impl->p = 1;
impl->maxmem_bytes = 1025 * 1024 * 1024;
}
static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_clear_free(kctx->pass, kctx->pass_len);
OPENSSL_free(kctx);
}
static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
const int new_buflen)
static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
size_t new_buflen)
{
if (new_buffer == NULL)
return 1;
if (new_buflen < 0)
return 0;
if (*buffer != NULL)
OPENSSL_clear_free(*buffer, *buflen);
OPENSSL_clear_free(*buffer, *buflen);
if (new_buflen > 0) {
*buffer = OPENSSL_memdup(new_buffer, new_buflen);
@@ -105,7 +116,7 @@ static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
*buffer = OPENSSL_malloc(1);
}
if (*buffer == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
KDFerr(KDF_F_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -118,149 +129,378 @@ static int is_power_of_two(uint64_t value)
return (value != 0) && ((value & (value - 1)) == 0);
}
static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static int kdf_scrypt_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
uint64_t u64_value;
uint32_t value;
const unsigned char *p;
size_t len;
switch (type) {
case EVP_PKEY_CTRL_PASS:
return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1);
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return scrypt_set_membuf(&impl->pass, &impl->pass_len, p, len);
case EVP_PKEY_CTRL_SCRYPT_SALT:
return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1);
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return scrypt_set_membuf(&impl->salt, &impl->salt_len, p, len);
case EVP_PKEY_CTRL_SCRYPT_N:
u64_value = *((uint64_t *)p2);
case EVP_KDF_CTRL_SET_SCRYPT_N:
u64_value = va_arg(args, uint64_t);
if ((u64_value <= 1) || !is_power_of_two(u64_value))
return 0;
kctx->N = u64_value;
impl->N = u64_value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_R:
u64_value = *((uint64_t *)p2);
if (u64_value < 1)
case EVP_KDF_CTRL_SET_SCRYPT_R:
value = va_arg(args, uint32_t);
if (value < 1)
return 0;
kctx->r = u64_value;
impl->r = value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_P:
u64_value = *((uint64_t *)p2);
if (u64_value < 1)
case EVP_KDF_CTRL_SET_SCRYPT_P:
value = va_arg(args, uint32_t);
if (value < 1)
return 0;
kctx->p = u64_value;
impl->p = value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
u64_value = *((uint64_t *)p2);
case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
u64_value = va_arg(args, uint64_t);
if (u64_value < 1)
return 0;
kctx->maxmem_bytes = u64_value;
impl->maxmem_bytes = u64_value;
return 1;
default:
return -2;
}
}
static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type,
const char *value)
static int kdf_scrypt_ctrl_uint32(EVP_KDF_IMPL *impl, int cmd,
const char *value)
{
uint64_t int_value;
int int_value = atoi(value);
if (!atou64(value, &int_value)) {
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
if (int_value < 0 || (uint64_t)int_value > UINT32_MAX) {
KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT32, KDF_R_VALUE_ERROR);
return 0;
}
return pkey_scrypt_ctrl(ctx, type, 0, &int_value);
return call_ctrl(kdf_scrypt_ctrl, impl, cmd, (uint32_t)int_value);
}
static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
static int kdf_scrypt_ctrl_uint64(EVP_KDF_IMPL *impl, int cmd,
const char *value)
{
uint64_t u64_value;
if (!atou64(value, &u64_value)) {
KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
return 0;
}
return call_ctrl(kdf_scrypt_ctrl, impl, cmd, u64_value);
}
static int kdf_scrypt_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
KDFerr(KDF_F_KDF_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "pass") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "hexpass") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "salt") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "hexsalt") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "N") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value);
return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_SCRYPT_N, value);
if (strcmp(type, "r") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value);
return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_R, value);
if (strcmp(type, "p") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value);
return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_P, value);
if (strcmp(type, "maxmem_bytes") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
value);
return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_MAXMEM_BYTES,
value);
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_scrypt_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
if (kctx->pass == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
if (impl->pass == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
return 0;
}
if (kctx->salt == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
if (impl->salt == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
return 0;
}
return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt,
kctx->salt_len, kctx->N, kctx->r, kctx->p,
kctx->maxmem_bytes, key, *keylen);
return scrypt_alg((char *)impl->pass, impl->pass_len, impl->salt,
impl->salt_len, impl->N, impl->r, impl->p,
impl->maxmem_bytes, key, keylen);
}
const EVP_PKEY_METHOD scrypt_pkey_meth = {
EVP_PKEY_SCRYPT,
0,
pkey_scrypt_init,
0,
pkey_scrypt_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_scrypt_derive,
pkey_scrypt_ctrl,
pkey_scrypt_ctrl_str
const EVP_KDF_METHOD scrypt_kdf_meth = {
EVP_KDF_SCRYPT,
kdf_scrypt_new,
kdf_scrypt_free,
kdf_scrypt_reset,
kdf_scrypt_ctrl,
kdf_scrypt_ctrl_str,
NULL,
kdf_scrypt_derive
};
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
static void salsa208_word_specification(uint32_t inout[16])
{
int i;
uint32_t x[16];
memcpy(x, inout, sizeof(x));
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i)
inout[i] += x[i];
OPENSSL_cleanse(x, sizeof(x));
}
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
{
uint64_t i, j;
uint32_t X[16], *pB;
memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
pB = B;
for (i = 0; i < r * 2; i++) {
for (j = 0; j < 16; j++)
X[j] ^= *pB++;
salsa208_word_specification(X);
memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
}
OPENSSL_cleanse(X, sizeof(X));
}
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
uint32_t *X, uint32_t *T, uint32_t *V)
{
unsigned char *pB;
uint32_t *pV;
uint64_t i, k;
/* Convert from little endian input */
for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
*pV = *pB++;
*pV |= *pB++ << 8;
*pV |= *pB++ << 16;
*pV |= (uint32_t)*pB++ << 24;
}
for (i = 1; i < N; i++, pV += 32 * r)
scryptBlockMix(pV, pV - 32 * r, r);
scryptBlockMix(X, V + (N - 1) * 32 * r, r);
for (i = 0; i < N; i++) {
uint32_t j;
j = X[16 * (2 * r - 1)] % N;
pV = V + 32 * r * j;
for (k = 0; k < 32 * r; k++)
T[k] = X[k] ^ *pV++;
scryptBlockMix(X, T, r);
}
/* Convert output to little endian */
for (i = 0, pB = B; i < 32 * r; i++) {
uint32_t xtmp = X[i];
*pB++ = xtmp & 0xff;
*pB++ = (xtmp >> 8) & 0xff;
*pB++ = (xtmp >> 16) & 0xff;
*pB++ = (xtmp >> 24) & 0xff;
}
}
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
/*
* Maximum power of two that will fit in uint64_t: this should work on
* most (all?) platforms.
*/
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
/*
* Maximum value of p * r:
* p <= ((2^32-1) * hLen) / MFLen =>
* p <= ((2^32-1) * 32) / (128 * r) =>
* p * r <= (2^30-1)
*/
#define SCRYPT_PR_MAX ((1 << 30) - 1)
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen)
{
int rv = 0;
unsigned char *B;
uint32_t *X, *V, *T;
uint64_t i, Blen, Vlen;
/* Sanity check parameters */
/* initial check, r,p must be non zero, N >= 2 and a power of 2 */
if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
return 0;
/* Check p * r < SCRYPT_PR_MAX avoiding overflow */
if (p > SCRYPT_PR_MAX / r) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Need to check N: if 2^(128 * r / 8) overflows limit this is
* automatically satisfied since N <= UINT64_MAX.
*/
if (16 * r <= LOG2_UINT64_MAX) {
if (N >= (((uint64_t)1) << (16 * r))) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
}
/* Memory checks: check total allocated buffer size fits in uint64_t */
/*
* B size in section 5 step 1.S
* Note: we know p * 128 * r < UINT64_MAX because we already checked
* p * r < SCRYPT_PR_MAX
*/
Blen = p * 128 * r;
/*
* Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
* have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
*/
if (Blen > INT_MAX) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
* This is combined size V, X and T (section 4)
*/
i = UINT64_MAX / (32 * sizeof(uint32_t));
if (N + 2 > i / r) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
/* check total allocated size fits in uint64_t */
if (Blen > UINT64_MAX - Vlen) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* Check that the maximum memory doesn't exceed a size_t limits */
if (maxmem > SIZE_MAX)
maxmem = SIZE_MAX;
if (Blen + Vlen > maxmem) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* If no key return to indicate parameters are OK */
if (key == NULL)
return 1;
B = OPENSSL_malloc((size_t)(Blen + Vlen));
if (B == NULL) {
EVPerr(EVP_F_SCRYPT_ALG, ERR_R_MALLOC_FAILURE);
return 0;
}
X = (uint32_t *)(B + Blen);
T = X + 32 * r;
V = T + 32 * r;
if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
(int)Blen, B) == 0)
goto err;
for (i = 0; i < p; i++)
scryptROMix(B + 128 * r * i, r, N, X, T, V);
if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
keylen, key) == 0)
goto err;
rv = 1;
err:
if (rv == 0)
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_PBKDF2_ERROR);
OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
return rv;
}
#endif
+98 -103
View File
@@ -8,11 +8,15 @@
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "internal/cryptlib.h"
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/evp_int.h"
#include "kdf_local.h"
static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl);
static int tls1_prf_alg(const EVP_MD *md,
const unsigned char *sec, size_t slen,
const unsigned char *seed, size_t seed_len,
@@ -20,9 +24,9 @@ static int tls1_prf_alg(const EVP_MD *md,
#define TLS1_PRF_MAXBUF 1024
/* TLS KDF pkey context structure */
/* TLS KDF kdf context structure */
typedef struct {
struct evp_kdf_impl_st {
/* Digest to use for PRF */
const EVP_MD *md;
/* Secret value to use for PRF */
@@ -31,145 +35,137 @@ typedef struct {
/* Buffer of concatenated seed data */
unsigned char seed[TLS1_PRF_MAXBUF];
size_t seedlen;
} TLS1_PRF_PKEY_CTX;
};
static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_tls1_prf_new(void)
{
TLS1_PRF_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->data = kctx;
return 1;
if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
KDFerr(KDF_F_KDF_TLS1_PRF_NEW, ERR_R_MALLOC_FAILURE);
return impl;
}
static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
static void kdf_tls1_prf_free(EVP_KDF_IMPL *impl)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->sec, kctx->seclen);
OPENSSL_cleanse(kctx->seed, kctx->seedlen);
OPENSSL_free(kctx);
kdf_tls1_prf_reset(impl);
OPENSSL_free(impl);
}
static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_TLS_MD:
kctx->md = p2;
OPENSSL_clear_free(impl->sec, impl->seclen);
OPENSSL_cleanse(impl->seed, impl->seedlen);
memset(impl, 0, sizeof(*impl));
}
static int kdf_tls1_prf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
impl->md = md;
return 1;
case EVP_PKEY_CTRL_TLS_SECRET:
if (p1 < 0)
case EVP_KDF_CTRL_SET_TLS_SECRET:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
OPENSSL_clear_free(impl->sec, impl->seclen);
impl->sec = OPENSSL_memdup(p, len);
if (impl->sec == NULL)
return 0;
if (kctx->sec != NULL)
OPENSSL_clear_free(kctx->sec, kctx->seclen);
OPENSSL_cleanse(kctx->seed, kctx->seedlen);
kctx->seedlen = 0;
kctx->sec = OPENSSL_memdup(p2, p1);
if (kctx->sec == NULL)
return 0;
kctx->seclen = p1;
impl->seclen = len;
return 1;
case EVP_PKEY_CTRL_TLS_SEED:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_RESET_TLS_SEED:
OPENSSL_cleanse(impl->seed, impl->seedlen);
impl->seedlen = 0;
return 1;
case EVP_KDF_CTRL_ADD_TLS_SEED:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
if (len > (TLS1_PRF_MAXBUF - impl->seedlen))
return 0;
memcpy(kctx->seed + kctx->seedlen, p2, p1);
kctx->seedlen += p1;
memcpy(impl->seed + impl->seedlen, p, len);
impl->seedlen += len;
return 1;
default:
return -2;
}
}
static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
static int kdf_tls1_prf_ctrl_str(EVP_KDF_IMPL *impl,
const char *type, const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
KDFerr(KDF_F_KDF_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "md") == 0) {
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_SET_MD, value);
const EVP_MD *md = EVP_get_digestbyname(value);
if (md == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
return 0;
}
kctx->md = md;
return 1;
}
if (strcmp(type, "secret") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
if (strcmp(type, "hexsecret") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
if (strcmp(type, "seed") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
if (strcmp(type, "hexseed") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl,
EVP_KDF_CTRL_SET_TLS_SECRET, value);
if (strcmp(type, "hexsecret") == 0)
return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl,
EVP_KDF_CTRL_SET_TLS_SECRET, value);
if (strcmp(type, "seed") == 0)
return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
value);
if (strcmp(type, "hexseed") == 0)
return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
value);
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_tls1_prf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
if (kctx->md == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (kctx->sec == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
if (impl->sec == NULL) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
return 0;
}
if (kctx->seedlen == 0) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
if (impl->seedlen == 0) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
return 0;
}
return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
kctx->seed, kctx->seedlen,
key, *keylen);
return tls1_prf_alg(impl->md, impl->sec, impl->seclen,
impl->seed, impl->seedlen,
key, keylen);
}
const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
EVP_PKEY_TLS1_PRF,
0,
pkey_tls1_prf_init,
0,
pkey_tls1_prf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_tls1_prf_derive,
pkey_tls1_prf_ctrl,
pkey_tls1_prf_ctrl_str
const EVP_KDF_METHOD tls1_prf_kdf_meth = {
EVP_KDF_TLS1_PRF,
kdf_tls1_prf_new,
kdf_tls1_prf_free,
kdf_tls1_prf_reset,
kdf_tls1_prf_ctrl,
kdf_tls1_prf_ctrl_str,
NULL,
kdf_tls1_prf_derive
};
static int tls1_prf_P_hash(const EVP_MD *md,
@@ -249,12 +245,11 @@ static int tls1_prf_alg(const EVP_MD *md,
const unsigned char *seed, size_t seed_len,
unsigned char *out, size_t olen)
{
if (EVP_MD_type(md) == NID_md5_sha1) {
size_t i;
unsigned char *tmp;
if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
seed, seed_len, out, olen))
seed, seed_len, out, olen))
return 0;
if ((tmp = OPENSSL_malloc(olen)) == NULL) {
@@ -262,7 +257,7 @@ static int tls1_prf_alg(const EVP_MD *md,
return 0;
}
if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
seed, seed_len, tmp, olen)) {
seed, seed_len, tmp, olen)) {
OPENSSL_clear_free(tmp, olen);
return 0;
}
+10 -2
View File
@@ -74,6 +74,16 @@ err:
}
void OPENSSL_LH_free(OPENSSL_LHASH *lh)
{
if (lh == NULL)
return;
OPENSSL_LH_flush(lh);
OPENSSL_free(lh->b);
OPENSSL_free(lh);
}
void OPENSSL_LH_flush(OPENSSL_LHASH *lh)
{
unsigned int i;
OPENSSL_LH_NODE *n, *nn;
@@ -89,8 +99,6 @@ void OPENSSL_LH_free(OPENSSL_LHASH *lh)
n = nn;
}
}
OPENSSL_free(lh->b);
OPENSSL_free(lh);
}
void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data)
+2 -1
View File
@@ -142,7 +142,6 @@ ___
$code=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__) || defined(__clang__)
.syntax unified
#define ldrplb ldrbpl
@@ -154,6 +153,8 @@ $code=<<___;
.code 32
#endif
.text
.type rem_4bit,%object
.align 5
rem_4bit:
+14
View File
@@ -529,6 +529,7 @@ $code.=<<___;
.type gcm_init_clmul,\@abi-omnipotent
.align 16
gcm_init_clmul:
.cfi_startproc
.L_init_clmul:
___
$code.=<<___ if ($win64);
@@ -598,6 +599,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_init_clmul,.-gcm_init_clmul
___
}
@@ -609,6 +611,7 @@ $code.=<<___;
.type gcm_gmult_clmul,\@abi-omnipotent
.align 16
gcm_gmult_clmul:
.cfi_startproc
.L_gmult_clmul:
movdqu ($Xip),$Xi
movdqa .Lbswap_mask(%rip),$T3
@@ -645,6 +648,7 @@ $code.=<<___;
pshufb $T3,$Xi
movdqu $Xi,($Xip)
ret
.cfi_endproc
.size gcm_gmult_clmul,.-gcm_gmult_clmul
___
}
@@ -658,6 +662,7 @@ $code.=<<___;
.type gcm_ghash_clmul,\@abi-omnipotent
.align 32
gcm_ghash_clmul:
.cfi_startproc
.L_ghash_clmul:
___
$code.=<<___ if ($win64);
@@ -1005,6 +1010,7 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_ghash_clmul,.-gcm_ghash_clmul
___
}
@@ -1014,6 +1020,7 @@ $code.=<<___;
.type gcm_init_avx,\@abi-omnipotent
.align 32
gcm_init_avx:
.cfi_startproc
___
if ($avx) {
my ($Htbl,$Xip)=@_4args;
@@ -1142,11 +1149,13 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_init_avx,.-gcm_init_avx
___
} else {
$code.=<<___;
jmp .L_init_clmul
.cfi_endproc
.size gcm_init_avx,.-gcm_init_avx
___
}
@@ -1156,7 +1165,9 @@ $code.=<<___;
.type gcm_gmult_avx,\@abi-omnipotent
.align 32
gcm_gmult_avx:
.cfi_startproc
jmp .L_gmult_clmul
.cfi_endproc
.size gcm_gmult_avx,.-gcm_gmult_avx
___
@@ -1165,6 +1176,7 @@ $code.=<<___;
.type gcm_ghash_avx,\@abi-omnipotent
.align 32
gcm_ghash_avx:
.cfi_startproc
___
if ($avx) {
my ($Xip,$Htbl,$inp,$len)=@_4args;
@@ -1577,11 +1589,13 @@ $code.=<<___ if ($win64);
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_ghash_avx,.-gcm_ghash_avx
___
} else {
$code.=<<___;
jmp .L_ghash_clmul
.cfi_endproc
.size gcm_ghash_avx,.-gcm_ghash_avx
___
}
+19 -7
View File
@@ -66,18 +66,26 @@ $inc="x12";
{
my ($Xl,$Xm,$Xh,$IN)=map("q$_",(0..3));
my ($t0,$t1,$t2,$xC2,$H,$Hhl,$H2)=map("q$_",(8..14));
my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code=<<___;
#include "arm_arch.h"
#if __ARM_MAX_ARCH__>=7
.text
___
$code.=".arch armv8-a+crypto\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
$code.=".arch armv8-a+crypto\n.text\n" if ($flavour =~ /64/);
$code.=<<___ if ($flavour !~ /64/);
.fpu neon
.code 32
#undef __thumb2__
#ifdef __thumb2__
.syntax unified
.thumb
# define INST(a,b,c,d) $_byte c,0xef,a,b
#else
.code 32
# define INST(a,b,c,d) $_byte a,b,c,0xf2
#endif
.text
___
################################################################################
@@ -752,7 +760,7 @@ if ($flavour =~ /64/) { ######## 64-bit code
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
sprintf ".byte\t0x%02x,0x%02x,0x%02x,0x%02x\t@ %s %s",
sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
@@ -767,13 +775,17 @@ if ($flavour =~ /64/) { ######## 64-bit code
# fix up remaining new-style suffixes
s/\],#[0-9]+/]!/o;
s/cclr\s+([^,]+),\s*([a-z]+)/mov$2 $1,#0/o or
s/cclr\s+([^,]+),\s*([a-z]+)/mov.$2 $1,#0/o or
s/vdup\.32\s+(.*)/unvdup32($1)/geo or
s/v?(pmull2?)\.p64\s+(.*)/unvpmullp64($1,$2)/geo or
s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo or
s/^(\s+)b\./$1b/o or
s/^(\s+)ret/$1bx\tlr/o;
if (s/^(\s+)mov\.([a-z]+)/$1mov$2/) {
print " it $2\n";
}
print $_,"\n";
}
}
+17
View File
@@ -28,6 +28,13 @@ my $fpu = sub {
if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); }
else { ""; }
};
my $rodata = sub {
SWITCH: for ($flavour) {
/linux/ && return ".section\t.rodata";
/ios/ && return ".section\t__TEXT,__const";
last;
}
};
my $hidden = sub {
if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); }
else { ".hidden\t".join(',',@_); }
@@ -96,6 +103,12 @@ my $asciz = sub {
{ ""; }
};
my $adrp = sub {
my ($args,$comment) = split(m|\s*//|,shift);
"\tadrp\t$args\@PAGE";
} if ($flavour =~ /ios64/);
sub range {
my ($r,$sfx,$start,$end) = @_;
@@ -125,6 +138,10 @@ sub expand_line {
$line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge;
if ($flavour =~ /ios64/) {
$line =~ s/#:lo12:(\w+)/$1\@PAGEOFF/;
}
return $line;
}
+16 -1
View File
@@ -541,6 +541,7 @@ my %globals;
);
my ($cfa_reg, $cfa_rsp);
my @cfa_stack;
# [us]leb128 format is variable-length integer representation base
# 2^128, with most significant bit of each byte being 0 denoting
@@ -648,7 +649,13 @@ my %globals;
# why it starts with -8. Recall that CFA is top of caller's
# stack...
/startproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", -8); last; };
/endproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", 0); last; };
/endproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", 0);
# .cfi_remember_state directives that are not
# matched with .cfi_restore_state are
# unnecessary.
die "unpaired .cfi_remember_state" if (@cfa_stack);
last;
};
/def_cfa_register/
&& do { $cfa_reg = $$line; last; };
/def_cfa_offset/
@@ -688,6 +695,14 @@ my %globals;
cfa_expression($$line)));
last;
};
/remember_state/
&& do { push @cfa_stack, [$cfa_reg, $cfa_rsp];
last;
};
/restore_state/
&& do { ($cfa_reg, $cfa_rsp) = @{pop @cfa_stack};
last;
};
}
$self->{value} = ".cfi_$dir\t$$line" if ($dir);
+26 -26
View File
@@ -48,7 +48,6 @@ if ($flavour && $flavour ne "void") {
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -56,6 +55,8 @@ $code.=<<___;
.code 32
#endif
.text
.globl poly1305_emit
.globl poly1305_blocks
.globl poly1305_init
@@ -100,8 +101,10 @@ poly1305_init:
and r4,r4,r10
#if __ARM_MAX_ARCH__>=7
# if !defined(_WIN32)
ldr r12,[r11,r12] @ OPENSSL_armcap_P
# ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
# endif
#endif
@@ -116,31 +119,21 @@ poly1305_init:
#if __ARM_MAX_ARCH__>=7
tst r12,#ARMV7_NEON @ check for NEON
# ifdef __APPLE__
adr r9,poly1305_blocks_neon
adr r11,poly1305_blocks
# ifdef __thumb2__
it ne
# endif
movne r11,r9
adr r12,poly1305_emit
adr r10,poly1305_emit_neon
# ifdef __thumb2__
it ne
# endif
movne r12,r10
# else
# ifdef __thumb2__
itete eq
# endif
addeq r12,r11,#(poly1305_emit-.Lpoly1305_init)
addne r12,r11,#(poly1305_emit_neon-.Lpoly1305_init)
addeq r11,r11,#(poly1305_blocks-.Lpoly1305_init)
addne r11,r11,#(poly1305_blocks_neon-.Lpoly1305_init)
# endif
# ifdef __thumb2__
orr r12,r12,#1 @ thumb-ify address
orr r11,r11,#1
adr r9,.Lpoly1305_blocks_neon
adr r11,.Lpoly1305_blocks
adr r12,.Lpoly1305_emit
adr r10,.Lpoly1305_emit_neon
itt ne
movne r11,r9
movne r12,r10
orr r11,r11,#1 @ thumb-ify address
orr r12,r12,#1
# else
addeq r12,r11,#(.Lpoly1305_emit-.Lpoly1305_init)
addne r12,r11,#(.Lpoly1305_emit_neon-.Lpoly1305_init)
addeq r11,r11,#(.Lpoly1305_blocks-.Lpoly1305_init)
addne r11,r11,#(.Lpoly1305_blocks_neon-.Lpoly1305_init)
# endif
#endif
ldrb r9,[$inp,#11]
@@ -352,6 +345,7 @@ $code.=<<___;
.type poly1305_emit,%function
.align 5
poly1305_emit:
.Lpoly1305_emit:
stmdb sp!,{r4-r11}
.Lpoly1305_emit_enter:
@@ -671,6 +665,7 @@ poly1305_init_neon:
.type poly1305_blocks_neon,%function
.align 5
poly1305_blocks_neon:
.Lpoly1305_blocks_neon:
ldr ip,[$ctx,#36] @ is_base2_26
ands $len,$len,#-16
beq .Lno_data_neon
@@ -1157,6 +1152,7 @@ poly1305_blocks_neon:
.type poly1305_emit_neon,%function
.align 5
poly1305_emit_neon:
.Lpoly1305_emit_neon:
ldr ip,[$ctx,#36] @ is_base2_26
stmdb sp!,{r4-r11}
@@ -1229,7 +1225,11 @@ poly1305_emit_neon:
.Lzeros:
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.Lpoly1305_init
# endif
#endif
___
} }
+14 -19
View File
@@ -71,17 +71,12 @@ poly1305_init:
csel x0,xzr,x0,eq
b.eq .Lno_key
#ifdef __ILP32__
ldrsw $t1,.LOPENSSL_armcap_P
#else
ldr $t1,.LOPENSSL_armcap_P
#endif
adr $t0,.LOPENSSL_armcap_P
adrp x17,OPENSSL_armcap_P
ldr w17,[x17,#:lo12:OPENSSL_armcap_P]
ldp $r0,$r1,[$inp] // load key
mov $s1,#0xfffffffc0fffffff
movk $s1,#0x0fff,lsl#48
ldr w17,[$t0,$t1]
#ifdef __ARMEB__
rev $r0,$r0 // flip bytes
rev $r1,$r1
@@ -93,10 +88,10 @@ poly1305_init:
tst w17,#ARMV7_NEON
adr $d0,poly1305_blocks
adr $r0,poly1305_blocks_neon
adr $d1,poly1305_emit
adr $r1,poly1305_emit_neon
adr $d0,.Lpoly1305_blocks
adr $r0,.Lpoly1305_blocks_neon
adr $d1,.Lpoly1305_emit
adr $r1,.Lpoly1305_emit_neon
csel $d0,$d0,$r0,eq
csel $d1,$d1,$r1,eq
@@ -115,6 +110,7 @@ poly1305_init:
.type poly1305_blocks,%function
.align 5
poly1305_blocks:
.Lpoly1305_blocks:
ands $len,$len,#-16
b.eq .Lno_data
@@ -179,6 +175,7 @@ poly1305_blocks:
.type poly1305_emit,%function
.align 5
poly1305_emit:
.Lpoly1305_emit:
ldp $h0,$h1,[$ctx] // load hash base 2^64
ldr $h2,[$ctx,#16]
ldp $t0,$t1,[$nonce] // load nonce
@@ -285,12 +282,14 @@ poly1305_splat:
.type poly1305_blocks_neon,%function
.align 5
poly1305_blocks_neon:
.Lpoly1305_blocks_neon:
ldr $is_base2_26,[$ctx,#24]
cmp $len,#128
b.hs .Lblocks_neon
cbz $is_base2_26,poly1305_blocks
cbz $is_base2_26,.Lpoly1305_blocks
.Lblocks_neon:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
@@ -430,7 +429,7 @@ poly1305_blocks_neon:
csel $in2,$zeros,$in2,lo
mov x4,#1
str x4,[$ctx,#-24] // set is_base2_26
stur x4,[$ctx,#-24] // set is_base2_26
sub $ctx,$ctx,#48 // restore original $ctx
b .Ldo_neon
@@ -859,6 +858,7 @@ poly1305_blocks_neon:
st1 {$ACC4}[0],[$ctx]
.Lno_data_neon:
.inst 0xd50323bf // autiasp
ldr x29,[sp],#80
ret
.size poly1305_blocks_neon,.-poly1305_blocks_neon
@@ -866,6 +866,7 @@ poly1305_blocks_neon:
.type poly1305_emit_neon,%function
.align 5
poly1305_emit_neon:
.Lpoly1305_emit_neon:
ldr $is_base2_26,[$ctx,#24]
cbz $is_base2_26,poly1305_emit
@@ -918,12 +919,6 @@ poly1305_emit_neon:
.align 5
.Lzeros:
.long 0,0,0,0,0,0,0,0
.LOPENSSL_armcap_P:
#ifdef __ILP32__
.long OPENSSL_armcap_P-.
#else
.quad OPENSSL_armcap_P-.
#endif
.asciz "Poly1305 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
+87
View File
@@ -0,0 +1,87 @@
Properties are associated with algorithms and are used to select between different implementations dynamically.
This implementation is based on a number of assumptions:
* Property definition is uncommon. I.e. providers will be loaded and
unloaded relatively infrequently, if at all.
* The number of distinct property names will be small.
* Providers will often give the same implementation properties to most or
all of their implemented algorithms. E.g. the FIPS property would be set
across an entire provider. Likewise for, hardware, accelerated, software,
HSM and, perhaps, constant_time.
* There are a lot of algorithm implementations, therefore property
definitions should be space efficient. However...
* ... property queries are very common. These must be fast.
* Property queries come from a small set and are reused many times typically.
I.e. an application tends to use the same set of queries over and over,
rather than spanning a wide variety of queries.
* Property queries can never add new property definitions.
Some consequences of these assumptions are:
* That definition is uncommon and queries are very common, we can treat
the property definitions as almost immutable. Specifically, a query can
never change the state of the definitions.
* That definition is uncommon and needs to be space efficient, it will
be feasible to use a hash table to contain the names (and possibly also
values) of all properties and to reference these instead of duplicating
strings. Moreover, such a data structure need not be garbage collected.
By converting strings to integers using a structure such as this, string
comparison degenerates to integer comparison. Additionally, lists of
properties can be sorted by the string index which makes comparisons linear
time rather than quadratic time - the O(n log n) sort cost being amortised.
* A cache for property definitions is also viable, if only implementation
properties are used and not algorithm properties, or at least these are
maintained separately. This cache would be a hash table, indexed by
the property definition string, and algorithms with the same properties
would share their definition structure. Again, reducing space use.
* A query cache is desirable. This would be a hash table keyed by the
algorithm identifier and the entire query string and it would map to
the chosen algorithm. When a provider is loaded or unloaded, this cache
must be invalidated. The cache will also be invalidated when the global
properties are changed as doing so removes the need to index on both the
global and requested property strings.
The implementation:
* property_lock.c contains some wrapper functions to handle the global
lock more easily. The global lock is held for short periods of time with
per algorithm locking being used for longer intervals.
* property_string.c contains the string cache which converts property
names and values to small integer indices. Names and values are stored in
separate hash tables. The two Boolean values, the strings "yes" and "no",
are populated as the first two members of the value table. All property
names reserved by OpenSSL are also populated here. No functions are
provided to convert from an index back to the original string (this can be
done by maintaining parallel stacks of strings if required).
* property_parse.c contains the property definition and query parsers.
These convert ASCII strings into lists of properties. The resulting
lists are sorted by the name index. Some additional utility functions
for dealing with property lists are also included: comparison of a query
against a definition and merging two queries into a single larger query.
* property.c contains the main APIs for defining and using properties.
Algorithms are discovered from their NID and a query string.
The results are cached.
The caching of query results has to be efficient but it must also be robust
against a denial of service attack. The cache cannot be permitted to grow
without bounds and must garbage collect under-used entries. The garbage
collection does not have to be exact.
* defn_cache.c contains a cache that maps property definition strings to
parsed properties. It is used by property.c to improve performance when
the same definition appears multiple times.
+3
View File
@@ -0,0 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=property_string.c property_parse.c property.c \
property_err.c defn_cache.c
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include <openssl/lhash.h>
#include "internal/propertyerr.h"
#include "internal/property.h"
#include "property_lcl.h"
/*
* Implement a property definition cache.
* These functions assume that they are called under a write lock.
* No attempt is made to clean out the cache, except when it is shut down.
*/
typedef struct {
const char *prop;
OSSL_PROPERTY_LIST *defn;
char body[1];
} PROPERTY_DEFN_ELEM;
DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM);
static LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = NULL;
static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a)
{
return OPENSSL_LH_strhash(a->prop);
}
static int property_defn_cmp(const PROPERTY_DEFN_ELEM *a,
const PROPERTY_DEFN_ELEM *b)
{
return strcmp(a->prop, b->prop);
}
static void property_defn_free(PROPERTY_DEFN_ELEM *elem)
{
ossl_property_free(elem->defn);
OPENSSL_free(elem);
}
int ossl_prop_defn_init(void)
{
property_defns = lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash,
&property_defn_cmp);
return property_defns != NULL;
}
void ossl_prop_defn_cleanup(void)
{
if (property_defns != NULL) {
lh_PROPERTY_DEFN_ELEM_doall(property_defns, &property_defn_free);
lh_PROPERTY_DEFN_ELEM_free(property_defns);
property_defns = NULL;
}
}
OSSL_PROPERTY_LIST *ossl_prop_defn_get(const char *prop)
{
PROPERTY_DEFN_ELEM elem, *r;
elem.prop = prop;
r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem);
return r != NULL ? r->defn : NULL;
}
int ossl_prop_defn_set(const char *prop, OSSL_PROPERTY_LIST *pl)
{
PROPERTY_DEFN_ELEM elem, *old, *p = NULL;
size_t len;
if (prop == NULL)
return 1;
if (pl == NULL) {
elem.prop = prop;
lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem);
return 1;
}
len = strlen(prop);
p = OPENSSL_malloc(sizeof(*p) + len);
if (p != NULL) {
p->prop = p->body;
p->defn = pl;
memcpy(p->body, prop, len + 1);
old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p);
if (old != NULL) {
property_defn_free(old);
return 1;
}
if (!lh_PROPERTY_DEFN_ELEM_error(property_defns))
return 1;
}
OPENSSL_free(p);
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
(* https://bottlecaps.de/rr/ui *)
Definition
::= PropertyName ( '=' Value )? ( ',' PropertyName ( '=' Value )? )*
Query ::= ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value )
( ',' ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value ) )*
Value ::= NumberLiteral
| StringLiteral
StringLiteral ::= QuotedString | UnquotedString
QuotedString ::= '"' [^"]* '"'
| "'" [^']* "'"
UnquotedString ::= [^{space},]+
NumberLiteral
::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ )
| '-'? [1-9] [0-9]+
PropertyName
::= [A-Z] [A-Z0-9_]* ( '.' [A-Z] [A-Z0-9_]* )*
+685
View File
@@ -0,0 +1,685 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="generator" content="Railroad Diagram Generator 1.56.1774" />
<style type="text/css">
::-moz-selection
{
color: #FFFCF0;
background: #0F0C00;
}
::selection
{
color: #FFFCF0;
background: #0F0C00;
}
.ebnf a, .grammar a
{
text-decoration: none;
}
.ebnf a:hover, .grammar a:hover
{
color: #050400;
text-decoration: underline;
}
.signature
{
color: #806600;
font-size: 11px;
text-align: right;
}
body
{
font: normal 12px Verdana, sans-serif;
color: #0F0C00;
background: #FFFCF0;
}
a:link, a:visited
{
color: #0F0C00;
}
a:link.signature, a:visited.signature
{
color: #806600;
}
a.button, #tabs li a
{
padding: 0.25em 0.5em;
border: 1px solid #806600;
background: #F1E8C6;
color: #806600;
text-decoration: none;
font-weight: bold;
}
a.button:hover, #tabs li a:hover
{
color: #050400;
background: #FFF6D1;
border-color: #050400;
}
#tabs
{
padding: 3px 10px;
margin-left: 0;
margin-top: 58px;
border-bottom: 1px solid #0F0C00;
}
#tabs li
{
list-style: none;
margin-left: 5px;
display: inline;
}
#tabs li a
{
border-bottom: 1px solid #0F0C00;
}
#tabs li a.active
{
color: #0F0C00;
background: #FFFCF0;
border-color: #0F0C00;
border-bottom: 1px solid #FFFCF0;
outline: none;
}
#divs div
{
display: none;
overflow:auto;
}
#divs div.active
{
display: block;
}
#text
{
border-color: #806600;
background: #FFFEFA;
color: #050400;
}
.small
{
vertical-align: top;
text-align: right;
font-size: 9px;
font-weight: normal;
line-height: 120%;
}
td.small
{
padding-top: 0px;
}
.hidden
{
visibility: hidden;
}
td:hover .hidden
{
visibility: visible;
}
div.download
{
display: none;
background: #FFFCF0;
position: absolute;
right: 34px;
top: 94px;
padding: 10px;
border: 1px dotted #0F0C00;
}
#divs div.ebnf, .ebnf code
{
display: block;
padding: 10px;
background: #FFF6D1;
width: 1000px;
}
#divs div.grammar
{
display: block;
padding-left: 16px;
padding-top: 2px;
padding-bottom: 2px;
background: #FFF6D1;
}
pre
{
margin: 0px;
}
.ebnf div
{
padding-left: 13ch;
text-indent: -13ch;
}
.ebnf code, .grammar code, textarea, pre
{
font:12px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
}
tr.option-line td:first-child
{
text-align: right
}
tr.option-text td
{
padding-bottom: 10px
}
table.palette
{
border-top: 1px solid #050400;
border-right: 1px solid #050400;
margin-bottom: 4px
}
td.palette
{
border-bottom: 1px solid #050400;
border-left: 1px solid #050400;
}
a.palette
{
padding: 2px 3px 2px 10px;
text-decoration: none;
}
.palette
{
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
}
</style><svg xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs></svg></head>
<body>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Definition">Definition:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="375" height="113">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 61 1 57 1 65"/>
<polygon points="17 61 9 57 9 65"/><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
<rect x="51" y="47" width="110" height="32"/>
<rect x="49" y="45" width="110" height="32" class="nonterminal"/>
<text class="nonterminal" x="59" y="65">PropertyName</text></a><rect x="201" y="79" width="30" height="32" rx="10"/>
<rect x="199" y="77" width="30" height="32" class="terminal" rx="10"/>
<text class="terminal" x="209" y="97">=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
<rect x="251" y="79" width="56" height="32"/>
<rect x="249" y="77" width="56" height="32" class="nonterminal"/>
<text class="nonterminal" x="259" y="97">Value</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
<rect x="49" y="1" width="24" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="21">,</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m20 0 h10 m110 0 h10 m20 0 h10 m0 0 h116 m-146 0 h20 m126 0 h20 m-166 0 q10 0 10 10 m146 0 q0 -10 10 -10 m-156 10 v12 m146 0 v-12 m-146 12 q0 10 10 10 m126 0 q10 0 10 -10 m-136 10 h10 m30 0 h10 m0 0 h10 m56 0 h10 m-296 -32 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m296 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-296 0 h10 m24 0 h10 m0 0 h252 m23 44 h-3"/>
<polygon points="365 61 373 57 373 65"/>
<polygon points="365 61 357 57 357 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#Definition" title="Definition">Definition</a></div>
<div>         ::= <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? ( ',' <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? )*</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Query">Query:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="419" height="201">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 61 1 57 1 65"/>
<polygon points="17 61 9 57 9 65"/>
<rect x="91" y="79" width="26" height="32" rx="10"/>
<rect x="89" y="77" width="26" height="32" class="terminal" rx="10"/>
<text class="terminal" x="99" y="97">-</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
<rect x="157" y="47" width="110" height="32"/>
<rect x="155" y="45" width="110" height="32" class="nonterminal"/>
<text class="nonterminal" x="165" y="65">PropertyName</text></a><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
<rect x="71" y="123" width="110" height="32"/>
<rect x="69" y="121" width="110" height="32" class="nonterminal"/>
<text class="nonterminal" x="79" y="141">PropertyName</text></a><rect x="221" y="123" width="30" height="32" rx="10"/>
<rect x="219" y="121" width="30" height="32" class="terminal" rx="10"/>
<text class="terminal" x="229" y="141">=</text>
<rect x="221" y="167" width="34" height="32" rx="10"/>
<rect x="219" y="165" width="34" height="32" class="terminal" rx="10"/>
<text class="terminal" x="229" y="185">!=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
<rect x="295" y="123" width="56" height="32"/>
<rect x="293" y="121" width="56" height="32" class="nonterminal"/>
<text class="nonterminal" x="303" y="141">Value</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
<rect x="49" y="1" width="24" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="21">,</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m60 0 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m110 0 h10 m0 0 h84 m-320 0 h20 m300 0 h20 m-340 0 q10 0 10 10 m320 0 q0 -10 10 -10 m-330 10 v56 m320 0 v-56 m-320 56 q0 10 10 10 m300 0 q10 0 10 -10 m-310 10 h10 m110 0 h10 m20 0 h10 m30 0 h10 m0 0 h4 m-74 0 h20 m54 0 h20 m-94 0 q10 0 10 10 m74 0 q0 -10 10 -10 m-84 10 v24 m74 0 v-24 m-74 24 q0 10 10 10 m54 0 q10 0 10 -10 m-64 10 h10 m34 0 h10 m20 -44 h10 m56 0 h10 m-340 -76 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m340 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-340 0 h10 m24 0 h10 m0 0 h296 m23 44 h-3"/>
<polygon points="409 61 417 57 417 65"/>
<polygon points="409 61 401 57 401 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#Query" title="Query">Query</a>    ::= ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) ( ',' ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) )*</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Value">Value:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="81">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 17 1 13 1 21"/>
<polygon points="17 17 9 13 9 21"/><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#NumberLiteral" xlink:title="NumberLiteral">
<rect x="51" y="3" width="108" height="32"/>
<rect x="49" y="1" width="108" height="32" class="nonterminal"/>
<text class="nonterminal" x="59" y="21">NumberLiteral</text></a><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#StringLiteral" xlink:title="StringLiteral">
<rect x="51" y="47" width="96" height="32"/>
<rect x="49" y="45" width="96" height="32" class="nonterminal"/>
<text class="nonterminal" x="59" y="65">StringLiteral</text></a><svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 17 h2 m20 0 h10 m108 0 h10 m-148 0 h20 m128 0 h20 m-168 0 q10 0 10 10 m148 0 q0 -10 10 -10 m-158 10 v24 m148 0 v-24 m-148 24 q0 10 10 10 m128 0 q10 0 10 -10 m-138 10 h10 m96 0 h10 m0 0 h12 m23 -44 h-3"/>
<polygon points="197 17 205 13 205 21"/>
<polygon points="197 17 189 13 189 21"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#Value" title="Value">Value</a>    ::= <a href="#NumberLiteral" title="NumberLiteral">NumberLiteral</a></div>
<div>           | <a href="#StringLiteral" title="StringLiteral">StringLiteral</a></div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
<xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="StringLiteral">StringLiteral:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="219" height="81">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 17 1 13 1 21"/>
<polygon points="17 17 9 13 9 21"/><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#QuotedString" xlink:title="QuotedString">
<rect x="51" y="3" width="104" height="32"/>
<rect x="49" y="1" width="104" height="32" class="nonterminal"/>
<text class="nonterminal" x="59" y="21">QuotedString</text></a><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#UnquotedString" xlink:title="UnquotedString">
<rect x="51" y="47" width="120" height="32"/>
<rect x="49" y="45" width="120" height="32" class="nonterminal"/>
<text class="nonterminal" x="59" y="65">UnquotedString</text></a><svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 17 h2 m20 0 h10 m104 0 h10 m0 0 h16 m-160 0 h20 m140 0 h20 m-180 0 q10 0 10 10 m160 0 q0 -10 10 -10 m-170 10 v24 m160 0 v-24 m-160 24 q0 10 10 10 m140 0 q10 0 10 -10 m-150 10 h10 m120 0 h10 m23 -44 h-3"/>
<polygon points="209 17 217 13 217 21"/>
<polygon points="209 17 201 13 201 21"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#StringLiteral" title="StringLiteral">StringLiteral</a></div>
<div>         ::= <a href="#QuotedString" title="QuotedString">QuotedString</a></div>
<div>           | <a href="#UnquotedString" title="UnquotedString">UnquotedString</a></div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#Value" title="Value">Value</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="QuotedString">QuotedString:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="327" height="151">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 33 1 29 1 37"/>
<polygon points="17 33 9 29 9 37"/>
<rect x="51" y="19" width="26" height="32" rx="10"/>
<rect x="49" y="17" width="26" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="37">"</text>
<polygon points="137 35 144 19 186 19 193 35 186 51 144 51"/>
<polygon points="135 33 142 17 184 17 191 33 184 49 142 49" class="regexp"/>
<text class="regexp" x="150" y="37">[^"]</text>
<rect x="253" y="19" width="26" height="32" rx="10"/>
<rect x="251" y="17" width="26" height="32" class="terminal" rx="10"/>
<text class="terminal" x="261" y="37">"</text>
<rect x="51" y="101" width="24" height="32" rx="10"/>
<rect x="49" y="99" width="24" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="119">'</text>
<polygon points="135 117 142 101 182 101 189 117 182 133 142 133"/>
<polygon points="133 115 140 99 180 99 187 115 180 131 140 131" class="regexp"/>
<text class="regexp" x="148" y="119">[^']</text>
<rect x="249" y="101" width="24" height="32" rx="10"/>
<rect x="247" y="99" width="24" height="32" class="terminal" rx="10"/>
<text class="terminal" x="257" y="119">'</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 33 h2 m20 0 h10 m26 0 h10 m40 0 h10 m56 0 h10 m-96 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -12 q0 -10 10 -10 m76 32 l20 0 m-20 0 q10 0 10 -10 l0 -12 q0 -10 -10 -10 m-76 0 h10 m0 0 h66 m-116 32 h20 m116 0 h20 m-156 0 q10 0 10 10 m136 0 q0 -10 10 -10 m-146 10 v14 m136 0 v-14 m-136 14 q0 10 10 10 m116 0 q10 0 10 -10 m-126 10 h10 m0 0 h106 m20 -34 h10 m26 0 h10 m-268 0 h20 m248 0 h20 m-288 0 q10 0 10 10 m268 0 q0 -10 10 -10 m-278 10 v62 m268 0 v-62 m-268 62 q0 10 10 10 m248 0 q10 0 10 -10 m-258 10 h10 m24 0 h10 m40 0 h10 m54 0 h10 m-94 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -12 q0 -10 10 -10 m74 32 l20 0 m-20 0 q10 0 10 -10 l0 -12 q0 -10 -10 -10 m-74 0 h10 m0 0 h64 m-114 32 h20 m114 0 h20 m-154 0 q10 0 10 10 m134 0 q0 -10 10 -10 m-144 10 v14 m134 0 v-14 m-134 14 q0 10 10 10 m114 0 q10 0 10 -10 m-124 10 h10 m0 0 h104 m20 -34 h10 m24 0 h10 m0 0 h6 m23 -82 h-3"/>
<polygon points="317 33 325 29 325 37"/>
<polygon points="317 33 309 29 309 37"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#QuotedString" title="QuotedString">QuotedString</a></div>
<div>         ::= '"' [^"]* '"'</div>
<div>           | "'" [^']* "'"</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#StringLiteral" title="StringLiteral">StringLiteral</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="UnquotedString">UnquotedString:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="53">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 33 1 29 1 37"/>
<polygon points="17 33 9 29 9 37"/>
<polygon points="51 35 58 19 152 19 159 35 152 51 58 51"/>
<polygon points="49 33 56 17 150 17 157 33 150 49 56 49" class="regexp"/>
<text class="regexp" x="64" y="37">[^{space},]</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 33 h2 m20 0 h10 m108 0 h10 m-148 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -12 q0 -10 10 -10 m128 32 l20 0 m-20 0 q10 0 10 -10 l0 -12 q0 -10 -10 -10 m-128 0 h10 m0 0 h118 m23 32 h-3"/>
<polygon points="197 33 205 29 205 37"/>
<polygon points="197 33 189 29 189 37"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#UnquotedString" title="UnquotedString">UnquotedString</a></div>
<div>         ::= [^{space},]+</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#StringLiteral" title="StringLiteral">StringLiteral</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="NumberLiteral">NumberLiteral:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="377" height="305">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 51 1 47 1 55"/>
<polygon points="17 51 9 47 9 55"/>
<rect x="51" y="37" width="28" height="32" rx="10"/>
<rect x="49" y="35" width="28" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="55">0</text>
<polygon points="139 19 146 3 194 3 201 19 194 35 146 35"/>
<polygon points="137 17 144 1 192 1 199 17 192 33 144 33" class="regexp"/>
<text class="regexp" x="152" y="21">[0-7]</text>
<rect x="119" y="85" width="28" height="32" rx="10"/>
<rect x="117" y="83" width="28" height="32" class="terminal" rx="10"/>
<text class="terminal" x="127" y="103">x</text>
<polygon points="207 101 214 85 262 85 269 101 262 117 214 117"/>
<polygon points="205 99 212 83 260 83 267 99 260 115 212 115" class="regexp"/>
<text class="regexp" x="220" y="103">[0-9]</text>
<polygon points="207 145 214 129 260 129 267 145 260 161 214 161"/>
<polygon points="205 143 212 127 258 127 265 143 258 159 212 159" class="regexp"/>
<text class="regexp" x="220" y="147">[A-F]</text>
<polygon points="207 189 214 173 258 173 265 189 258 205 214 205"/>
<polygon points="205 187 212 171 256 171 263 187 256 203 212 203" class="regexp"/>
<text class="regexp" x="220" y="191">[a-f]</text>
<rect x="71" y="271" width="26" height="32" rx="10"/>
<rect x="69" y="269" width="26" height="32" class="terminal" rx="10"/>
<text class="terminal" x="79" y="289">-</text>
<polygon points="137 255 144 239 192 239 199 255 192 271 144 271"/>
<polygon points="135 253 142 237 190 237 197 253 190 269 142 269" class="regexp"/>
<text class="regexp" x="150" y="257">[1-9]</text>
<polygon points="239 255 246 239 294 239 301 255 294 271 246 271"/>
<polygon points="237 253 244 237 292 237 299 253 292 269 244 269" class="regexp"/>
<text class="regexp" x="252" y="257">[0-9]</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 51 h2 m20 0 h10 m28 0 h10 m40 0 h10 m0 0 h72 m-102 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -14 q0 -10 10 -10 m82 34 l20 0 m-20 0 q10 0 10 -10 l0 -14 q0 -10 -10 -10 m-82 0 h10 m62 0 h10 m20 34 h88 m-230 0 h20 m210 0 h20 m-250 0 q10 0 10 10 m230 0 q0 -10 10 -10 m-240 10 v28 m230 0 v-28 m-230 28 q0 10 10 10 m210 0 q10 0 10 -10 m-220 10 h10 m28 0 h10 m40 0 h10 m62 0 h10 m-102 0 h20 m82 0 h20 m-122 0 q10 0 10 10 m102 0 q0 -10 10 -10 m-112 10 v24 m102 0 v-24 m-102 24 q0 10 10 10 m82 0 q10 0 10 -10 m-92 10 h10 m60 0 h10 m0 0 h2 m-92 -10 v20 m102 0 v-20 m-102 20 v24 m102 0 v-24 m-102 24 q0 10 10 10 m82 0 q10 0 10 -10 m-92 10 h10 m58 0 h10 m0 0 h4 m-122 -88 l20 0 m-1 0 q-9 0 -9 -10 l0 -12 q0 -10 10 -10 m122 32 l20 0 m-20 0 q10 0 10 -10 l0 -12 q0 -10 -10 -10 m-122 0 h10 m0 0 h112 m-278 -16 h20 m298 0 h20 m-338 0 q10 0 10 10 m318 0 q0 -10 10 -10 m-328 10 v182 m318 0 v-182 m-318 182 q0 10 10 10 m298 0 q10 0 10 -10 m-288 10 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m62 0 h10 m20 0 h10 m62 0 h10 m-102 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -12 q0 -10 10 -10 m82 32 l20 0 m-20 0 q10 0 10 -10 l0 -12 q0 -10 -10 -10 m-82 0 h10 m0 0 h72 m20 32 h8 m23 -202 h-3"/>
<polygon points="367 51 375 47 375 55"/>
<polygon points="367 51 359 47 359 55"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#NumberLiteral" title="NumberLiteral">NumberLiteral</a></div>
<div>         ::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ )</div>
<div>           | '-'? [1-9] [0-9]+</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#Value" title="Value">Value</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="PropertyName">PropertyName:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="283" height="203">
<defs>
<style type="text/css">
@namespace "http://www.w3.org/2000/svg";
.line {fill: none; stroke: #332900;}
.bold-line {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
.thin-line {stroke: #1F1800; shape-rendering: crispEdges}
.filled {fill: #332900; stroke: none;}
text.terminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #141000;
font-weight: bold;
}
text.nonterminal {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1A1400;
font-weight: normal;
}
text.regexp {font-family: Verdana, Sans-serif;
font-size: 12px;
fill: #1F1800;
font-weight: normal;
}
rect, circle, polygon {fill: #332900; stroke: #332900;}
rect.terminal {fill: #FFDB4D; stroke: #332900;}
rect.nonterminal {fill: #FFEC9E; stroke: #332900;}
rect.text {fill: none; stroke: none;}
polygon.regexp {fill: #FFF4C7; stroke: #332900;}
</style>
</defs>
<polygon points="9 183 1 179 1 187"/>
<polygon points="17 183 9 179 9 187"/>
<polygon points="51 185 58 169 106 169 113 185 106 201 58 201"/>
<polygon points="49 183 56 167 104 167 111 183 104 199 56 199" class="regexp"/>
<text class="regexp" x="64" y="187">[A-Z]</text>
<polygon points="153 151 160 135 208 135 215 151 208 167 160 167"/>
<polygon points="151 149 158 133 206 133 213 149 206 165 158 165" class="regexp"/>
<text class="regexp" x="166" y="153">[A-Z]</text>
<polygon points="153 107 160 91 208 91 215 107 208 123 160 123"/>
<polygon points="151 105 158 89 206 89 213 105 206 121 158 121" class="regexp"/>
<text class="regexp" x="166" y="109">[0-9]</text>
<rect x="153" y="47" width="28" height="32" rx="10"/>
<rect x="151" y="45" width="28" height="32" class="terminal" rx="10"/>
<text class="terminal" x="161" y="65">_</text>
<rect x="51" y="3" width="24" height="32" rx="10"/>
<rect x="49" y="1" width="24" height="32" class="terminal" rx="10"/>
<text class="terminal" x="59" y="21">.</text>
<svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 183 h2 m20 0 h10 m62 0 h10 m20 0 h10 m0 0 h72 m-102 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -14 q0 -10 10 -10 m82 34 l20 0 m-20 0 q10 0 10 -10 l0 -14 q0 -10 -10 -10 m-82 0 h10 m62 0 h10 m-92 10 l0 -44 q0 -10 10 -10 m92 54 l0 -44 q0 -10 -10 -10 m-82 0 h10 m62 0 h10 m-92 10 l0 -44 q0 -10 10 -10 m92 54 l0 -44 q0 -10 -10 -10 m-82 0 h10 m28 0 h10 m0 0 h34 m-204 122 l20 0 m-1 0 q-9 0 -9 -10 l0 -146 q0 -10 10 -10 m204 166 l20 0 m-20 0 q10 0 10 -10 l0 -146 q0 -10 -10 -10 m-204 0 h10 m24 0 h10 m0 0 h160 m23 166 h-3"/>
<polygon points="273 183 281 179 281 187"/>
<polygon points="273 183 265 179 265 187"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:div class="ebnf"><xhtml:code>
<div><a href="#PropertyName" title="PropertyName">PropertyName</a></div>
<div>         ::= [A-Z] [A-Z0-9_]* ( '.' [A-Z] [A-Z0-9_]* )*</div></xhtml:code></xhtml:div>
</xhtml:p>
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
<xhtml:ul>
<xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
<xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
</xhtml:ul>
</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:hr xmlns:xhtml="http://www.w3.org/1999/xhtml" />
<xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:table class="signature" border="0">
<xhtml:tr>
<xhtml:td style="width: 100%"> </xhtml:td>
<xhtml:td valign="top">
<xhtml:nobr class="signature">... generated by <xhtml:a name="Railroad-Diagram-Generator" class="signature" title="https://www.bottlecaps.de/rr/ui" href="https://www.bottlecaps.de/rr/ui" target="_blank">Railroad Diagram Generator</xhtml:a></xhtml:nobr>
</xhtml:td>
<xhtml:td><xhtml:a name="Railroad-Diagram-Generator" title="https://www.bottlecaps.de/rr/ui" href="https://www.bottlecaps.de/rr/ui" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
<g transform="scale(0.178)">
<circle cx="45" cy="45" r="45" style="stroke:none; fill:#FFCC00"/>
<circle cx="45" cy="45" r="42" style="stroke:#332900; stroke-width:2px; fill:#FFCC00"/>
<line x1="15" y1="15" x2="75" y2="75" stroke="#332900" style="stroke-width:9px;"/>
<line x1="15" y1="75" x2="75" y2="15" stroke="#332900" style="stroke-width:9px;"/>
<text x="7" y="54" style="font-size:26px; font-family:Arial, Sans-serif; font-weight:bold; fill: #332900">R</text>
<text x="64" y="54" style="font-size:26px; font-family:Arial, Sans-serif; font-weight:bold; fill: #332900">R</text>
</g></svg></xhtml:a></xhtml:td>
</xhtml:tr>
</xhtml:table>
</xhtml:p>
</body>
</html>
+507
View File
@@ -0,0 +1,507 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <openssl/crypto.h>
#include "internal/property.h"
#include "internal/ctype.h"
#include <openssl/lhash.h>
#include <openssl/rand.h>
#include "internal/thread_once.h"
#include "internal/lhash.h"
#include "internal/sparse_array.h"
#include "property_lcl.h"
/* The number of elements in the query cache before we initiate a flush */
#define IMPL_CACHE_FLUSH_THRESHOLD 500
typedef struct {
OSSL_PROPERTY_LIST *properties;
void *method;
void (*method_destruct)(void *);
} IMPLEMENTATION;
DEFINE_STACK_OF(IMPLEMENTATION)
typedef struct {
const char *query;
void *method;
char body[1];
} QUERY;
DEFINE_LHASH_OF(QUERY);
typedef struct {
int nid;
STACK_OF(IMPLEMENTATION) *impls;
LHASH_OF(QUERY) *cache;
} ALGORITHM;
struct ossl_method_store_st {
size_t nelem;
SPARSE_ARRAY_OF(ALGORITHM) *algs;
OSSL_PROPERTY_LIST *global_properties;
int need_flush;
unsigned int nbits;
unsigned char rand_bits[(IMPL_CACHE_FLUSH_THRESHOLD + 7) / 8];
CRYPTO_RWLOCK *lock;
};
typedef struct {
OSSL_METHOD_STORE *store;
LHASH_OF(QUERY) *cache;
size_t nelem;
} IMPL_CACHE_FLUSH;
DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid);
static void ossl_method_cache_flush_all(OSSL_METHOD_STORE *c);
int ossl_property_read_lock(OSSL_METHOD_STORE *p)
{
return p != NULL ? CRYPTO_THREAD_read_lock(p->lock) : 0;
}
int ossl_property_write_lock(OSSL_METHOD_STORE *p)
{
return p != NULL ? CRYPTO_THREAD_write_lock(p->lock) : 0;
}
int ossl_property_unlock(OSSL_METHOD_STORE *p)
{
return p != 0 ? CRYPTO_THREAD_unlock(p->lock) : 0;
}
int ossl_method_store_init(void)
{
if (ossl_property_string_init()
&& ossl_prop_defn_init()
&& ossl_property_parse_init())
return 1;
ossl_method_store_cleanup();
return 0;
}
void ossl_method_store_cleanup(void)
{
ossl_property_string_cleanup();
ossl_prop_defn_cleanup();
}
static CRYPTO_ONCE method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_method_store_init)
{
return OPENSSL_init_crypto(0, NULL)
&& ossl_method_store_init()
&& OPENSSL_atexit(&ossl_method_store_cleanup);
}
static unsigned long query_hash(const QUERY *a)
{
return OPENSSL_LH_strhash(a->query);
}
static int query_cmp(const QUERY *a, const QUERY *b)
{
return strcmp(a->query, b->query);
}
static void impl_free(IMPLEMENTATION *impl)
{
if (impl != NULL) {
if (impl->method_destruct)
impl->method_destruct(impl->method);
OPENSSL_free(impl);
}
}
static void impl_cache_free(QUERY *elem)
{
OPENSSL_free(elem);
}
static void alg_cleanup(size_t idx, ALGORITHM *a)
{
if (a != NULL) {
sk_IMPLEMENTATION_pop_free(a->impls, &impl_free);
lh_QUERY_doall(a->cache, &impl_cache_free);
lh_QUERY_free(a->cache);
OPENSSL_free(a);
}
}
OSSL_METHOD_STORE *ossl_method_store_new(void)
{
OSSL_METHOD_STORE *res = OPENSSL_zalloc(sizeof(*res));
if (!RUN_ONCE(&method_store_init_flag, do_method_store_init))
return 0;
if (res != NULL) {
if ((res->algs = ossl_sa_ALGORITHM_new()) == NULL) {
OPENSSL_free(res);
return NULL;
}
if ((res->lock = CRYPTO_THREAD_lock_new()) == NULL) {
OPENSSL_free(res->algs);
OPENSSL_free(res);
return NULL;
}
}
return res;
}
void ossl_method_store_free(OSSL_METHOD_STORE *store)
{
if (store != NULL) {
ossl_sa_ALGORITHM_doall(store->algs, &alg_cleanup);
ossl_sa_ALGORITHM_free(store->algs);
ossl_property_free(store->global_properties);
CRYPTO_THREAD_lock_free(store->lock);
OPENSSL_free(store);
}
}
static ALGORITHM *ossl_method_store_retrieve(OSSL_METHOD_STORE *store, int nid)
{
return ossl_sa_ALGORITHM_get(store->algs, nid);
}
static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg)
{
return ossl_sa_ALGORITHM_set(store->algs, alg->nid, alg);
}
int ossl_method_store_add(OSSL_METHOD_STORE *store,
int nid, const char *properties,
void *method, void (*method_destruct)(void *))
{
ALGORITHM *alg = NULL;
IMPLEMENTATION *impl;
int ret = 0;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
if (properties == NULL)
properties = "";
/* Create new entry */
impl = OPENSSL_malloc(sizeof(*impl));
if (impl == NULL)
return 0;
impl->method = method;
impl->method_destruct = method_destruct;
/*
* Insert into the hash table if required.
*
* A write lock is used unconditionally because we wend our way down to the
* property string code which isn't locking friendly.
*/
ossl_property_write_lock(store);
ossl_method_cache_flush(store, nid);
if ((impl->properties = ossl_prop_defn_get(properties)) == NULL) {
if ((impl->properties = ossl_parse_property(properties)) == NULL)
goto err;
ossl_prop_defn_set(properties, impl->properties);
}
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
if ((alg = OPENSSL_zalloc(sizeof(*alg))) == NULL
|| (alg->impls = sk_IMPLEMENTATION_new_null()) == NULL
|| (alg->cache = lh_QUERY_new(&query_hash, &query_cmp)) == NULL)
goto err;
alg->nid = nid;
if (!ossl_method_store_insert(store, alg))
goto err;
}
/* Push onto stack */
if (sk_IMPLEMENTATION_push(alg->impls, impl))
ret = 1;
ossl_property_unlock(store);
if (ret == 0)
impl_free(impl);
return ret;
err:
ossl_property_unlock(store);
alg_cleanup(0, alg);
impl_free(impl);
return 0;
}
int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
const void *method)
{
ALGORITHM *alg = NULL;
int i;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
ossl_property_write_lock(store);
ossl_method_cache_flush(store, nid);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
/*
* A sorting find then a delete could be faster but these stacks should be
* relatively small, so we avoid the overhead. Sorting could also surprise
* users when result orderings change (even though they are not guaranteed).
*/
for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
if (impl->method == method) {
sk_IMPLEMENTATION_delete(alg->impls, i);
ossl_property_unlock(store);
impl_free(impl);
return 1;
}
}
ossl_property_unlock(store);
return 0;
}
int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
const char *prop_query, void **method)
{
ALGORITHM *alg;
IMPLEMENTATION *impl;
OSSL_PROPERTY_LIST *pq = NULL, *p2;
int ret = 0;
int j;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
/*
* This only needs to be a read lock, because queries never create property
* names or value and thus don't modify any of the property string layer.
*/
ossl_property_read_lock(store);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
if (prop_query == NULL) {
if ((impl = sk_IMPLEMENTATION_value(alg->impls, 0)) != NULL) {
*method = impl->method;
ret = 1;
}
goto fin;
}
pq = ossl_parse_query(prop_query);
if (pq == NULL)
goto fin;
if (store->global_properties != NULL) {
p2 = ossl_property_merge(pq, store->global_properties);
if (p2 == NULL)
goto fin;
ossl_property_free(pq);
pq = p2;
}
for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
impl = sk_IMPLEMENTATION_value(alg->impls, j);
if (ossl_property_match(pq, impl->properties)) {
*method = impl->method;
ret = 1;
goto fin;
}
}
fin:
ossl_property_unlock(store);
ossl_property_free(pq);
return ret;
}
int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
const char *prop_query) {
int ret = 0;
if (store == NULL)
return 1;
ossl_property_write_lock(store);
ossl_method_cache_flush_all(store);
if (prop_query == NULL) {
ossl_property_free(store->global_properties);
store->global_properties = NULL;
ossl_property_unlock(store);
return 1;
}
store->global_properties = ossl_parse_query(prop_query);
ret = store->global_properties != NULL;
ossl_property_unlock(store);
return ret;
}
static void impl_cache_flush_alg(size_t idx, ALGORITHM *alg)
{
lh_QUERY_doall(alg->cache, &impl_cache_free);
lh_QUERY_flush(alg->cache);
}
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
{
ALGORITHM *alg = ossl_method_store_retrieve(store, nid);
if (alg != NULL) {
store->nelem -= lh_QUERY_num_items(alg->cache);
impl_cache_flush_alg(0, alg);
}
}
static void ossl_method_cache_flush_all(OSSL_METHOD_STORE *store)
{
ossl_sa_ALGORITHM_doall(store->algs, &impl_cache_flush_alg);
store->nelem = 0;
}
IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
/*
* Flush an element from the query cache (perhaps).
*
* In order to avoid taking a write lock to keep accurate LRU information or
* using atomic operations to approximate similar, the procedure used here
* is to stochastically flush approximately half the cache. Since generating
* random numbers is relatively expensive, we produce them in blocks and
* consume them as we go, saving generated bits between generations of flushes.
*
* This procedure isn't ideal, LRU would be better. However, in normal
* operation, reaching a full cache would be quite unexpected. It means
* that no steady state of algorithm queries has been reached. I.e. it is most
* likely an attack of some form. A suboptimal clearance strategy that doesn't
* degrade performance of the normal case is preferable to a more refined
* approach that imposes a performance impact.
*/
static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
{
OSSL_METHOD_STORE *store = state->store;
unsigned int n;
if (store->nbits == 0) {
if (!RAND_bytes(store->rand_bits, sizeof(store->rand_bits)))
return;
store->nbits = sizeof(store->rand_bits) * 8;
}
n = --store->nbits;
if ((store->rand_bits[n >> 3] & (1 << (n & 7))) != 0)
OPENSSL_free(lh_QUERY_delete(state->cache, c));
else
state->nelem++;
}
static void impl_cache_flush_one_alg(size_t idx, ALGORITHM *alg, void *v)
{
IMPL_CACHE_FLUSH *state = (IMPL_CACHE_FLUSH *)v;
state->cache = alg->cache;
lh_QUERY_doall_IMPL_CACHE_FLUSH(state->cache, &impl_cache_flush_cache,
state);
}
static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
{
IMPL_CACHE_FLUSH state;
state.nelem = 0;
state.store = store;
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
store->need_flush = 0;
store->nelem = state.nelem;
}
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
const char *prop_query, void **method)
{
ALGORITHM *alg;
QUERY elem, *r;
if (nid <= 0 || store == NULL)
return 0;
ossl_property_read_lock(store);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
elem.query = prop_query;
r = lh_QUERY_retrieve(alg->cache, &elem);
if (r == NULL) {
ossl_property_unlock(store);
return 0;
}
*method = r->method;
ossl_property_unlock(store);
return 1;
}
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
const char *prop_query, void *method)
{
QUERY elem, *old, *p = NULL;
ALGORITHM *alg;
size_t len;
if (nid <= 0 || store == NULL)
return 0;
if (prop_query == NULL)
return 1;
ossl_property_write_lock(store);
if (store->need_flush)
ossl_method_cache_flush_some(store);
alg = ossl_method_store_retrieve(store, nid);
if (alg == NULL) {
ossl_property_unlock(store);
return 0;
}
if (method == NULL) {
elem.query = prop_query;
lh_QUERY_delete(alg->cache, &elem);
ossl_property_unlock(store);
return 1;
}
p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query)));
if (p != NULL) {
p->query = p->body;
p->method = method;
memcpy((char *)p->query, prop_query, len + 1);
if ((old = lh_QUERY_insert(alg->cache, p)) != NULL)
OPENSSL_free(old);
if (old != NULL || !lh_QUERY_error(alg->cache)) {
store->nelem++;
if (store->nelem >= IMPL_CACHE_FLUSH_THRESHOLD)
store->need_flush = 1;
ossl_property_unlock(store);
return 1;
}
}
ossl_property_unlock(store);
OPENSSL_free(p);
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/*
* 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/propertyerr.h"
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA PROP_str_functs[] = {
{ERR_PACK(ERR_LIB_PROP, PROP_F_OSSL_PARSE_PROPERTY, 0),
"ossl_parse_property"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_OSSL_PARSE_QUERY, 0), "ossl_parse_query"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_HEX, 0), "parse_hex"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_NAME, 0), "parse_name"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_NUMBER, 0), "parse_number"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_OCT, 0), "parse_oct"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_STRING, 0), "parse_string"},
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_UNQUOTED, 0), "parse_unquoted"},
{0, NULL}
};
static const ERR_STRING_DATA PROP_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NAME_TOO_LONG), "name too long"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_ASCII_CHARACTER),
"not an ascii character"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_HEXADECIMAL_DIGIT),
"not an hexadecimal digit"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_IDENTIFIER), "not an identifier"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_OCTAL_DIGIT),
"not an octal digit"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_A_DECIMAL_DIGIT),
"not a decimal digit"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NO_MATCHING_STRING_DELIMETER),
"no matching string delimeter"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NO_VALUE), "no value"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_PARSE_FAILED), "parse failed"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_STRING_TOO_LONG), "string too long"},
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_TRAILING_CHARACTERS),
"trailing characters"},
{0, NULL}
};
#endif
int ERR_load_PROP_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(PROP_str_functs[0].error) == NULL) {
ERR_load_strings_const(PROP_str_functs);
ERR_load_strings_const(PROP_str_reasons);
}
#endif
return 1;
}
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/crypto.h>
#include "internal/property.h"
typedef struct ossl_property_list_st OSSL_PROPERTY_LIST;
typedef int OSSL_PROPERTY_IDX;
/* Initialisation and finalisation for subsystem */
int ossl_method_store_init(void);
void ossl_method_store_cleanup(void);
/* Property string functions */
OSSL_PROPERTY_IDX ossl_property_name(const char *s, int create);
OSSL_PROPERTY_IDX ossl_property_value(const char *s, int create);
int ossl_property_string_init(void);
void ossl_property_string_cleanup(void);
/* Property list functions */
int ossl_property_parse_init(void);
void ossl_property_free(OSSL_PROPERTY_LIST *p);
int ossl_property_match(const OSSL_PROPERTY_LIST *query,
const OSSL_PROPERTY_LIST *defn);
OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
const OSSL_PROPERTY_LIST *b);
/* Property definition functions */
OSSL_PROPERTY_LIST *ossl_parse_property(const char *s);
/* Property query functions */
OSSL_PROPERTY_LIST *ossl_parse_query(const char *s);
/* Property definition cache functions */
int ossl_prop_defn_init(void);
void ossl_prop_defn_cleanup(void);
OSSL_PROPERTY_LIST *ossl_prop_defn_get(const char *prop);
int ossl_prop_defn_set(const char *prop, OSSL_PROPERTY_LIST *pl);
/* Property cache lock / unlock */
int ossl_property_write_lock(OSSL_METHOD_STORE *);
int ossl_property_read_lock(OSSL_METHOD_STORE *);
int ossl_property_unlock(OSSL_METHOD_STORE *);
+545
View File
@@ -0,0 +1,545 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <openssl/err.h>
#include "internal/propertyerr.h"
#include "internal/property.h"
#include "internal/ctype.h"
#include "internal/nelem.h"
#include "property_lcl.h"
#include "e_os.h"
typedef enum {
PROPERTY_TYPE_STRING, PROPERTY_TYPE_NUMBER,
PROPERTY_TYPE_VALUE_UNDEFINED
} PROPERTY_TYPE;
typedef enum {
PROPERTY_OPER_EQ, PROPERTY_OPER_NE, PROPERTY_OVERRIDE
} PROPERTY_OPER;
typedef struct {
OSSL_PROPERTY_IDX name_idx;
PROPERTY_TYPE type;
PROPERTY_OPER oper;
union {
int64_t int_val; /* Signed integer */
OSSL_PROPERTY_IDX str_val; /* String */
} v;
} PROPERTY_DEFINITION;
struct ossl_property_list_st {
int n;
PROPERTY_DEFINITION properties[1];
};
static OSSL_PROPERTY_IDX ossl_property_true, ossl_property_false;
DEFINE_STACK_OF(PROPERTY_DEFINITION)
static const char *skip_space(const char *s)
{
while (ossl_isspace(*s))
s++;
return s;
}
static int match_ch(const char *t[], char m)
{
const char *s = *t;
if (*s == m) {
*t = skip_space(s + 1);
return 1;
}
return 0;
}
#define MATCH(s, m) match(s, m, sizeof(m) - 1)
static int match(const char *t[], const char m[], size_t m_len)
{
const char *s = *t;
if (strncasecmp(s, m, m_len) == 0) {
*t = skip_space(s + m_len);
return 1;
}
return 0;
}
static int parse_name(const char *t[], int create, OSSL_PROPERTY_IDX *idx)
{
char name[100];
int err = 0;
size_t i = 0;
const char *s = *t;
int user_name = 0;
for (;;) {
if (!ossl_isalpha(*s)) {
PROPerr(PROP_F_PARSE_NAME, PROP_R_NOT_AN_IDENTIFIER);
return 0;
}
do {
if (i < sizeof(name) - 1)
name[i++] = ossl_tolower(*s);
else
err = 1;
} while (*++s == '_' || ossl_isalnum(*s));
if (*s != '.')
break;
user_name = 1;
if (i < sizeof(name) - 1)
name[i++] = *s;
else
err = 1;
s++;
}
name[i] = '\0';
*t = skip_space(s);
if (!err) {
*idx = ossl_property_name(name, user_name && create);
return 1;
}
PROPerr(PROP_F_PARSE_NAME, PROP_R_NAME_TOO_LONG);
return 0;
}
static int parse_number(const char *t[], PROPERTY_DEFINITION *res)
{
const char *s = *t;
int64_t v = 0;
if (!ossl_isdigit(*s))
return 0;
do {
v = v * 10 + (*s++ - '0');
} while (ossl_isdigit(*s));
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
PROPerr(PROP_F_PARSE_NUMBER, PROP_R_NOT_A_DECIMAL_DIGIT);
return 0;
}
*t = skip_space(s);
res->type = PROPERTY_TYPE_NUMBER;
res->v.int_val = v;
return 1;
}
static int parse_hex(const char *t[], PROPERTY_DEFINITION *res)
{
const char *s = *t;
int64_t v = 0;
if (!ossl_isxdigit(*s))
return 0;
do {
v <<= 4;
if (ossl_isdigit(*s))
v += *s - '0';
else
v += ossl_tolower(*s) - 'a';
} while (ossl_isxdigit(*++s));
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
PROPerr(PROP_F_PARSE_HEX, PROP_R_NOT_AN_HEXADECIMAL_DIGIT);
return 0;
}
*t = skip_space(s);
res->type = PROPERTY_TYPE_NUMBER;
res->v.int_val = v;
return 1;
}
static int parse_oct(const char *t[], PROPERTY_DEFINITION *res)
{
const char *s = *t;
int64_t v = 0;
if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
return 0;
do {
v = (v << 3) + (*s - '0');
} while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
PROPerr(PROP_F_PARSE_OCT, PROP_R_NOT_AN_OCTAL_DIGIT);
return 0;
}
*t = skip_space(s);
res->type = PROPERTY_TYPE_NUMBER;
res->v.int_val = v;
return 1;
}
static int parse_string(const char *t[], char delim, PROPERTY_DEFINITION *res,
const int create)
{
char v[1000];
const char *s = *t;
size_t i = 0;
int err = 0;
while (*s != '\0' && *s != delim) {
if (i < sizeof(v) - 1)
v[i++] = *s;
else
err = 1;
s++;
}
if (*s == '\0') {
PROPerr(PROP_F_PARSE_STRING,
PROP_R_NO_MATCHING_STRING_DELIMETER);
return 0;
}
v[i] = '\0';
*t = skip_space(s + 1);
if (err)
PROPerr(PROP_F_PARSE_STRING, PROP_R_STRING_TOO_LONG);
else
res->v.str_val = ossl_property_value(v, create);
res->type = PROPERTY_TYPE_STRING;
return !err;
}
static int parse_unquoted(const char *t[], PROPERTY_DEFINITION *res,
const int create)
{
char v[1000];
const char *s = *t;
size_t i = 0;
int err = 0;
if (*s == '\0' || *s == ',')
return 0;
while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
if (i < sizeof(v) - 1)
v[i++] = ossl_tolower(*s);
else
err = 1;
s++;
}
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_NOT_AN_ASCII_CHARACTER);
return 0;
}
v[i] = 0;
*t = skip_space(s);
if (err)
PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_STRING_TOO_LONG);
else
res->v.str_val = ossl_property_value(v, create);
res->type = PROPERTY_TYPE_STRING;
return !err;
}
static int parse_value(const char *t[], PROPERTY_DEFINITION *res, int create)
{
const char *s = *t;
int r = 0;
if (*s == '"' || *s == '\'') {
s++;
r = parse_string(&s, s[-1], res, create);
} else if (*s == '+') {
s++;
r = parse_number(&s, res);
} else if (*s == '-') {
s++;
r = parse_number(&s, res);
res->v.int_val = -res->v.int_val;
} else if (*s == '0' && s[1] == 'x') {
s += 2;
r = parse_hex(&s, res);
} else if (*s == '0' && ossl_isdigit(s[1])) {
s++;
r = parse_oct(&s, res);
} else if (ossl_isdigit(*s)) {
return parse_number(t, res);
} else if (ossl_isalpha(*s))
return parse_unquoted(t, res, create);
if (r)
*t = s;
return r;
}
static int pd_compare(const PROPERTY_DEFINITION *const *p1,
const PROPERTY_DEFINITION *const *p2)
{
const PROPERTY_DEFINITION *pd1 = *p1;
const PROPERTY_DEFINITION *pd2 = *p2;
if (pd1->name_idx < pd2->name_idx)
return -1;
if (pd1->name_idx > pd2->name_idx)
return 1;
return 0;
}
static void pd_free(PROPERTY_DEFINITION *pd)
{
OPENSSL_free(pd);
}
/*
* Convert a stack of property definitions and queries into a fixed array.
* The items are sorted for efficient query. The stack is not freed.
*/
static OSSL_PROPERTY_LIST *stack_to_property_list(STACK_OF(PROPERTY_DEFINITION)
*sk)
{
const int n = sk_PROPERTY_DEFINITION_num(sk);
OSSL_PROPERTY_LIST *r;
int i;
r = OPENSSL_malloc(sizeof(*r)
+ (n == 0 ? 0 : n - 1) * sizeof(r->properties[0]));
if (r != NULL) {
sk_PROPERTY_DEFINITION_sort(sk);
for (i = 0; i < n; i++)
r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
r->n = n;
}
return r;
}
OSSL_PROPERTY_LIST *ossl_parse_property(const char *defn)
{
PROPERTY_DEFINITION *prop = NULL;
OSSL_PROPERTY_LIST *res = NULL;
STACK_OF(PROPERTY_DEFINITION) *sk;
const char *s = defn;
int done;
if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
return NULL;
s = skip_space(s);
done = *s == '\0';
while (!done) {
prop = OPENSSL_malloc(sizeof(*prop));
if (prop == NULL)
goto err;
memset(&prop->v, 0, sizeof(prop->v));
if (!parse_name(&s, 1, &prop->name_idx))
goto err;
prop->oper = PROPERTY_OPER_EQ;
if (prop->name_idx == 0) {
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_PARSE_FAILED);
goto err;
}
if (match_ch(&s, '=')) {
if (!parse_value(&s, prop, 1)) {
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_NO_VALUE);
goto err;
}
} else {
/* A name alone means a true Boolean */
prop->type = PROPERTY_TYPE_STRING;
prop->v.str_val = ossl_property_true;
}
if (!sk_PROPERTY_DEFINITION_push(sk, prop))
goto err;
prop = NULL;
done = !match_ch(&s, ',');
}
if (*s != '\0') {
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_TRAILING_CHARACTERS);
goto err;
}
res = stack_to_property_list(sk);
err:
OPENSSL_free(prop);
sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
return res;
}
OSSL_PROPERTY_LIST *ossl_parse_query(const char *s)
{
STACK_OF(PROPERTY_DEFINITION) *sk;
OSSL_PROPERTY_LIST *res = NULL;
PROPERTY_DEFINITION *prop = NULL;
int done;
if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
return NULL;
s = skip_space(s);
done = *s == '\0';
while (!done) {
prop = OPENSSL_malloc(sizeof(*prop));
if (prop == NULL)
goto err;
memset(&prop->v, 0, sizeof(prop->v));
if (match_ch(&s, '-')) {
prop->oper = PROPERTY_OVERRIDE;
if (!parse_name(&s, 0, &prop->name_idx))
goto err;
goto skip_value;
}
if (!parse_name(&s, 0, &prop->name_idx))
goto err;
if (match_ch(&s, '=')) {
prop->oper = PROPERTY_OPER_EQ;
} else if (MATCH(&s, "!=")) {
prop->oper = PROPERTY_OPER_NE;
} else {
/* A name alone is a Boolean comparison for true */
prop->oper = PROPERTY_OPER_EQ;
prop->type = PROPERTY_TYPE_STRING;
prop->v.str_val = ossl_property_true;
goto skip_value;
}
if (!parse_value(&s, prop, 0))
prop->type = PROPERTY_TYPE_VALUE_UNDEFINED;
skip_value:
if (!sk_PROPERTY_DEFINITION_push(sk, prop))
goto err;
prop = NULL;
done = !match_ch(&s, ',');
}
if (*s != '\0') {
PROPerr(PROP_F_OSSL_PARSE_QUERY, PROP_R_TRAILING_CHARACTERS);
goto err;
}
res = stack_to_property_list(sk);
err:
OPENSSL_free(prop);
sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
return res;
}
int ossl_property_match(const OSSL_PROPERTY_LIST *query,
const OSSL_PROPERTY_LIST *defn)
{
const PROPERTY_DEFINITION *const q = query->properties;
const PROPERTY_DEFINITION *const d = defn->properties;
int i = 0, j = 0;
PROPERTY_OPER oper;
while (i < query->n) {
if ((oper = q[i].oper) == PROPERTY_OVERRIDE) {
i++;
continue;
}
if (j < defn->n) {
if (q[i].name_idx > d[j].name_idx) { /* skip defn, not in query */
j++;
continue;
}
if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
const int eq = q[i].type == d[j].type
&& memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
if ((eq && oper != PROPERTY_OPER_EQ)
|| (!eq && oper != PROPERTY_OPER_NE))
return 0;
i++;
j++;
continue;
}
}
/*
* Handle the cases of a missing value and a query with no corresponding
* definition. The former fails for any comparision except inequality,
* the latter is treated as a comparison against the Boolean false.
*/
if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
if (oper != PROPERTY_OPER_NE)
return 0;
} else if (q[i].type != PROPERTY_TYPE_STRING
|| (oper == PROPERTY_OPER_EQ
&& q[i].v.str_val != ossl_property_false)
|| (oper == PROPERTY_OPER_NE
&& q[i].v.str_val == ossl_property_false)) {
return 0;
}
i++;
}
return 1;
}
void ossl_property_free(OSSL_PROPERTY_LIST *p)
{
OPENSSL_free(p);
}
/*
* Merge two property lists.
* If there is a common name, the one from the first list is used.
*/
OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
const OSSL_PROPERTY_LIST *b)
{
const PROPERTY_DEFINITION *const ap = a->properties;
const PROPERTY_DEFINITION *const bp = b->properties;
const PROPERTY_DEFINITION *copy;
OSSL_PROPERTY_LIST *r;
int i, j, n;
const int t = a->n + b->n;
r = OPENSSL_malloc(sizeof(*r)
+ (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
if (r == NULL)
return NULL;
for (i = j = n = 0; i < a->n || j < b->n; n++) {
if (i >= a->n) {
copy = &bp[j++];
} else if (j >= b->n) {
copy = &ap[i++];
} else if (ap[i].name_idx <= bp[j].name_idx) {
if (ap[i].name_idx == bp[j].name_idx)
j++;
copy = &ap[i++];
} else {
copy = &bp[j++];
}
memcpy(r->properties + n, copy, sizeof(r->properties[0]));
}
r->n = n;
if (n != t)
r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
return r;
}
int ossl_property_parse_init(void)
{
static const char *const predefined_names[] = {
"default", /* Being provided by the default built-in provider */
"provider", /* Name of provider (default, fips) */
"version", /* Version number of this provider */
"fips", /* FIPS supporting provider */
"engine", /* An old style engine masquerading as a provider */
};
size_t i;
for (i = 0; i < OSSL_NELEM(predefined_names); i++)
if (ossl_property_name(predefined_names[i], 1) == 0)
goto err;
/* Pre-populate the two Boolean values */
if ((ossl_property_true = ossl_property_value("yes", 1)) == 0
|| (ossl_property_false = ossl_property_value("no", 1)) == 0)
goto err;
return 1;
err:
return 0;
}
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/lhash.h>
#include "internal/lhash.h"
#include "property_lcl.h"
/*
* Property strings are a consolidation of all strings seen by the property
* subsystem. There are two name spaces to keep property names separate from
* property values (numeric values are not expected to be cached however).
* They allow a rapid conversion from a string to a unique index and any
* subsequent string comparison can be done via an integer compare.
*
* This implementation uses OpenSSL's standard hash table. There are more
* space and time efficient algorithms if this becomes a bottleneck.
*/
typedef struct {
const char *s;
OSSL_PROPERTY_IDX idx;
char body[1];
} PROPERTY_STRING;
DEFINE_LHASH_OF(PROPERTY_STRING);
typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
static PROP_TABLE *prop_names;
static PROP_TABLE *prop_values;
static OSSL_PROPERTY_IDX prop_name_idx = 0;
static OSSL_PROPERTY_IDX prop_value_idx = 0;
static unsigned long property_hash(const PROPERTY_STRING *a)
{
return OPENSSL_LH_strhash(a->s);
}
static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b)
{
return strcmp(a->s, b->s);
}
static void property_free(PROPERTY_STRING *ps)
{
OPENSSL_free(ps);
}
static void property_table_free(PROP_TABLE **pt)
{
PROP_TABLE *t = *pt;
if (t != NULL) {
lh_PROPERTY_STRING_doall(t, &property_free);
lh_PROPERTY_STRING_free(t);
*pt = NULL;
}
}
static PROPERTY_STRING *new_property_string(const char *s,
OSSL_PROPERTY_IDX *pidx)
{
const size_t l = strlen(s);
PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l);
if (ps != NULL) {
memcpy(ps->body, s, l + 1);
ps->s = ps->body;
ps->idx = ++*pidx;
if (ps->idx == 0) {
OPENSSL_free(ps);
return NULL;
}
}
return ps;
}
static OSSL_PROPERTY_IDX ossl_property_string(PROP_TABLE *t,
OSSL_PROPERTY_IDX *pidx,
const char *s)
{
PROPERTY_STRING p, *ps, *ps_new;
p.s = s;
ps = lh_PROPERTY_STRING_retrieve(t, &p);
if (ps == NULL && pidx != NULL)
if ((ps_new = new_property_string(s, pidx)) != NULL) {
lh_PROPERTY_STRING_insert(t, ps_new);
if (lh_PROPERTY_STRING_error(t)) {
property_free(ps_new);
return 0;
}
ps = ps_new;
}
return ps != NULL ? ps->idx : 0;
}
OSSL_PROPERTY_IDX ossl_property_name(const char *s, int create)
{
return ossl_property_string(prop_names, create ? &prop_name_idx : NULL, s);
}
OSSL_PROPERTY_IDX ossl_property_value(const char *s, int create)
{
return ossl_property_string(prop_values, create ? &prop_value_idx : NULL, s);
}
int ossl_property_string_init(void)
{
prop_names = lh_PROPERTY_STRING_new(&property_hash, &property_cmp);
if (prop_names == NULL)
return 0;
prop_values = lh_PROPERTY_STRING_new(&property_hash, &property_cmp);
if (prop_values == NULL)
goto err;
return 1;
err:
ossl_property_string_cleanup();
return 0;
}
void ossl_property_string_cleanup(void)
{
property_table_free(&prop_names);
property_table_free(&prop_values);
prop_name_idx = prop_value_idx = 0;
}
+31 -3
View File
@@ -113,8 +113,6 @@ my @T = map([ 8*$_, 8*($_+1), 8*($_+2), 8*($_+3), 8*($_+4) ], (30,35,40,45,50));
$code.=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -122,6 +120,8 @@ $code.=<<___;
.code 32
#endif
.text
.type iotas32, %object
.align 5
iotas32:
@@ -691,7 +691,14 @@ ___
$code.=<<___;
blo .Lround2x
#if __ARM_ARCH__>=5
ldr pc,[sp,#440]
#else
ldr lr,[sp,#440]
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size KeccakF1600_int,.-KeccakF1600_int
.type KeccakF1600, %function
@@ -730,7 +737,14 @@ KeccakF1600:
stmia @E[1], {@C[0]-@C[9]}
add sp,sp,#440+20
#if __ARM_ARCH__>=5
ldmia sp!,{r4-r11,pc}
#else
ldmia sp!,{r4-r11,lr}
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size KeccakF1600,.-KeccakF1600
___
{ my ($A_flat,$inp,$len,$bsz) = map("r$_",(10..12,14));
@@ -905,7 +919,14 @@ SHA3_absorb:
.Labsorb_abort:
add sp,sp,#456+32
mov r0,$len @ return value
#if __ARM_ARCH__>=5
ldmia sp!,{r4-r12,pc}
#else
ldmia sp!,{r4-r12,lr}
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size SHA3_absorb,.-SHA3_absorb
___
}
@@ -1055,7 +1076,14 @@ SHA3_squeeze:
.align 4
.Lsqueeze_done:
add sp,sp,#24
#if __ARM_ARCH__>=5
ldmia sp!,{r4-r10,pc}
#else
ldmia sp!,{r4-r10,lr}
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size SHA3_squeeze,.-SHA3_squeeze
___
}
@@ -1265,7 +1293,7 @@ KeccakF1600_neon:
subs r3, r3, #1
bne .Loop_neon
bx lr
ret
.size KeccakF1600_neon,.-KeccakF1600_neon
.global SHA3_absorb_neon
+14
View File
@@ -121,6 +121,7 @@ $code.=<<___;
.align 5
KeccakF1600_int:
adr $C[2],iotas
.inst 0xd503233f // paciasp
stp $C[2],x30,[sp,#16] // 32 bytes on top are mine
b .Loop
.align 4
@@ -292,12 +293,14 @@ $code.=<<___;
bne .Loop
ldr x30,[sp,#24]
.inst 0xd50323bf // autiasp
ret
.size KeccakF1600_int,.-KeccakF1600_int
.type KeccakF1600,%function
.align 5
KeccakF1600:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -347,6 +350,7 @@ KeccakF1600:
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#128
.inst 0xd50323bf // autiasp
ret
.size KeccakF1600,.-KeccakF1600
@@ -354,6 +358,7 @@ KeccakF1600:
.type SHA3_absorb,%function
.align 5
SHA3_absorb:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-128]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -451,6 +456,7 @@ $code.=<<___;
ldp x25,x26,[x29,#64]
ldp x27,x28,[x29,#80]
ldp x29,x30,[sp],#128
.inst 0xd50323bf // autiasp
ret
.size SHA3_absorb,.-SHA3_absorb
___
@@ -461,6 +467,7 @@ $code.=<<___;
.type SHA3_squeeze,%function
.align 5
SHA3_squeeze:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-48]!
add x29,sp,#0
stp x19,x20,[sp,#16]
@@ -523,6 +530,7 @@ SHA3_squeeze:
ldp x19,x20,[sp,#16]
ldp x21,x22,[sp,#32]
ldp x29,x30,[sp],#48
.inst 0xd50323bf // autiasp
ret
.size SHA3_squeeze,.-SHA3_squeeze
___
@@ -641,6 +649,7 @@ KeccakF1600_ce:
.type KeccakF1600_cext,%function
.align 5
KeccakF1600_cext:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
stp d8,d9,[sp,#16] // per ABI requirement
@@ -673,6 +682,7 @@ $code.=<<___;
ldp d12,d13,[sp,#48]
ldp d14,d15,[sp,#64]
ldr x29,[sp],#80
.inst 0xd50323bf // autiasp
ret
.size KeccakF1600_cext,.-KeccakF1600_cext
___
@@ -685,6 +695,7 @@ $code.=<<___;
.type SHA3_absorb_cext,%function
.align 5
SHA3_absorb_cext:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-80]!
add x29,sp,#0
stp d8,d9,[sp,#16] // per ABI requirement
@@ -756,6 +767,7 @@ $code.=<<___;
ldp d12,d13,[sp,#48]
ldp d14,d15,[sp,#64]
ldp x29,x30,[sp],#80
.inst 0xd50323bf // autiasp
ret
.size SHA3_absorb_cext,.-SHA3_absorb_cext
___
@@ -767,6 +779,7 @@ $code.=<<___;
.type SHA3_squeeze_cext,%function
.align 5
SHA3_squeeze_cext:
.inst 0xd503233f // paciasp
stp x29,x30,[sp,#-16]!
add x29,sp,#0
mov x9,$ctx
@@ -822,6 +835,7 @@ SHA3_squeeze_cext:
.Lsqueeze_done_ce:
ldr x29,[sp],#16
.inst 0xd50323bf // autiasp
ret
.size SHA3_squeeze_cext,.-SHA3_squeeze_cext
___
+14 -6
View File
@@ -187,7 +187,6 @@ ___
$code=<<___;
#include "arm_arch.h"
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -195,6 +194,8 @@ $code=<<___;
.code 32
#endif
.text
.global sha1_block_data_order
.type sha1_block_data_order,%function
@@ -202,12 +203,14 @@ $code=<<___;
sha1_block_data_order:
#if __ARM_MAX_ARCH__>=7
.Lsha1_block:
adr r3,.Lsha1_block
ldr r12,.LOPENSSL_armcap
# if !defined(_WIN32)
adr r3,.Lsha1_block
ldr r12,[r3,r12] @ OPENSSL_armcap_P
#ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
#endif
# endif
tst r12,#ARMV8_SHA1
bne .LARMv8
tst r12,#ARMV7_NEON
@@ -311,7 +314,11 @@ $code.=<<___;
.LK_60_79: .word 0xca62c1d6
#if __ARM_MAX_ARCH__>=7
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.Lsha1_block
# endif
#endif
.asciz "SHA1 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 5
@@ -613,14 +620,15 @@ my ($ABCD,$E,$E0,$E1)=map("q$_",(0..3));
my @MSG=map("q$_",(4..7));
my @Kxx=map("q$_",(8..11));
my ($W0,$W1,$ABCD_SAVE)=map("q$_",(12..14));
my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code.=<<___;
#if __ARM_MAX_ARCH__>=7
# if defined(__thumb2__)
# define INST(a,b,c,d) .byte c,d|0xf,a,b
# define INST(a,b,c,d) $_byte c,d|0xf,a,b
# else
# define INST(a,b,c,d) .byte a,b,c,d|0x10
# define INST(a,b,c,d) $_byte a,b,c,d|0x10
# endif
.type sha1_block_data_order_armv8,%function
+11 -19
View File
@@ -58,10 +58,10 @@ $code.=<<___ if ($i<15 && !($i&1));
lsr @Xx[$i+1],@Xx[$i],#32
___
$code.=<<___ if ($i<14 && !($i&1));
ldr @Xx[$i+2],[$inp,#`($i+2)*4-64`]
ldur @Xx[$i+2],[$inp,#`($i+2)*4-64`]
___
$code.=<<___ if ($i<14 && ($i&1));
#ifdef __ARMEB__
#ifdef __AARCH64EB__
ror @Xx[$i+1],@Xx[$i+1],#32
#else
rev32 @Xx[$i+1],@Xx[$i+1]
@@ -171,23 +171,19 @@ ___
}
$code.=<<___;
#include "arm_arch.h"
#ifndef __KERNEL__
# include "arm_arch.h"
.extern OPENSSL_armcap_P
#endif
.text
.extern OPENSSL_armcap_P
.globl sha1_block_data_order
.type sha1_block_data_order,%function
.align 6
sha1_block_data_order:
#ifdef __ILP32__
ldrsw x16,.LOPENSSL_armcap_P
#else
ldr x16,.LOPENSSL_armcap_P
#endif
adr x17,.LOPENSSL_armcap_P
add x16,x16,x17
ldr w16,[x16]
adrp x16,OPENSSL_armcap_P
ldr w16,[x16,#:lo12:OPENSSL_armcap_P]
tst w16,#ARMV8_SHA1
b.ne .Lv8_entry
@@ -208,7 +204,7 @@ sha1_block_data_order:
movz $K,#0x7999
sub $num,$num,#1
movk $K,#0x5a82,lsl#16
#ifdef __ARMEB__
#ifdef __AARCH64EB__
ror $Xx[0],@Xx[0],#32
#else
rev32 @Xx[0],@Xx[0]
@@ -321,15 +317,11 @@ $code.=<<___;
.long 0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1 //K_20_39
.long 0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc //K_40_59
.long 0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6 //K_60_79
.LOPENSSL_armcap_P:
#ifdef __ILP32__
.long OPENSSL_armcap_P-.
#else
.quad OPENSSL_armcap_P-.
#endif
.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
#if !defined(__KERNELL__) && !defined(_WIN64)
.comm OPENSSL_armcap_P,4,4
#endif
___
}}}
+13 -5
View File
@@ -181,7 +181,6 @@ $code=<<___;
# define __ARM_MAX_ARCH__ 7
#endif
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -189,6 +188,8 @@ $code=<<___;
.code 32
#endif
.text
.type K256,%object
.align 5
K256:
@@ -212,7 +213,11 @@ K256:
.word 0 @ terminator
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.Lsha256_block_data_order
# endif
#endif
.align 5
@@ -227,10 +232,12 @@ sha256_block_data_order:
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
# if !defined(_WIN32)
ldr r12,[r3,r12] @ OPENSSL_armcap_P
#ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
#endif
# endif
tst r12,#ARMV8_SHA256
bne .LARMv8
tst r12,#ARMV7_NEON
@@ -598,14 +605,15 @@ my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2));
my @MSG=map("q$_",(8..11));
my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15));
my $Ktbl="r3";
my $_byte = ($flavour =~ /win/ ? "DCB" : ".byte");
$code.=<<___;
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
# if defined(__thumb2__)
# define INST(a,b,c,d) .byte c,d|0xc,a,b
# define INST(a,b,c,d) $_byte c,d|0xc,a,b
# else
# define INST(a,b,c,d) .byte a,b,c,d
# define INST(a,b,c,d) $_byte a,b,c,d
# endif
.type sha256_block_data_order_armv8,%function
+15 -5
View File
@@ -196,6 +196,9 @@ $code.=<<___;
add $Ktbl,$Ktbl,#8
___
}
my $_word = ($flavour =~ /win/ ? "DCDU" : ".word");
$code=<<___;
#ifndef __KERNEL__
# include "arm_arch.h"
@@ -211,14 +214,13 @@ $code=<<___;
#ifdef __ARMEL__
# define LO 0
# define HI 4
# define WORD64(hi0,lo0,hi1,lo1) .word lo0,hi0, lo1,hi1
# define WORD64(hi0,lo0,hi1,lo1) $_word lo0,hi0, lo1,hi1
#else
# define HI 0
# define LO 4
# define WORD64(hi0,lo0,hi1,lo1) .word hi0,lo0, hi1,lo1
# define WORD64(hi0,lo0,hi1,lo1) $_word hi0,lo0, hi1,lo1
#endif
.text
#if defined(__thumb2__)
.syntax unified
.thumb
@@ -227,6 +229,8 @@ $code=<<___;
.code 32
#endif
.text
.type K512,%object
.align 5
K512:
@@ -273,7 +277,11 @@ WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
.size K512,.-K512
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
# ifdef _WIN32
.word OPENSSL_armcap_P
# else
.word OPENSSL_armcap_P-.Lsha512_block_data_order
# endif
.skip 32-4
#else
.skip 32
@@ -290,10 +298,12 @@ sha512_block_data_order:
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
# if !defined(_WIN32)
ldr r12,[r3,r12] @ OPENSSL_armcap_P
#ifdef __APPLE__
# endif
# if defined(__APPLE__) || defined(_WIN32)
ldr r12,[r12]
#endif
# endif
tst r12,#ARMV7_NEON
bne .LNEON
#endif

Some files were not shown because too many files have changed in this diff Show More