Update pre9
This commit is contained in:
@@ -1,21 +1,35 @@
|
||||
Andy Polyakov
|
||||
Ben Laurie
|
||||
Bodo Möller
|
||||
Emilia Käsper
|
||||
Eric Young
|
||||
Geoff Thorpe
|
||||
Holger Reif
|
||||
Kurt Roeckx
|
||||
Lutz Jänicke
|
||||
Mark J. Cox
|
||||
Matt Caswell
|
||||
Nils Larsch
|
||||
Paul C. Sutton
|
||||
Ralf S. Engelschall
|
||||
Rich Salz
|
||||
Richard Levitte
|
||||
Stephen Henson
|
||||
Steve Marquess
|
||||
Tim Hudson
|
||||
Ulf Möller
|
||||
Viktor Dukhovni
|
||||
# This is the list of OpenSSL authors for copyright purposes.
|
||||
#
|
||||
# This does not necessarily list everyone who has contributed code, since in
|
||||
# some cases, their employer may be the copyright holder. To see the full list
|
||||
# of contributors, see the revision history in source control.
|
||||
OpenSSL Software Services, Inc.
|
||||
OpenSSL Software Foundation, Inc.
|
||||
|
||||
# Individuals
|
||||
Andy Polyakov
|
||||
Ben Laurie
|
||||
Ben Kaduk
|
||||
Bernd Edlinger
|
||||
Bodo Möller
|
||||
David Benjamin
|
||||
Emilia Käsper
|
||||
Eric Young
|
||||
Geoff Thorpe
|
||||
Holger Reif
|
||||
Kurt Roeckx
|
||||
Lutz Jänicke
|
||||
Mark J. Cox
|
||||
Matt Caswell
|
||||
Matthias St. Pierre
|
||||
Nils Larsch
|
||||
Paul Dale
|
||||
Paul C. Sutton
|
||||
Ralf S. Engelschall
|
||||
Rich Salz
|
||||
Richard Levitte
|
||||
Stephen Henson
|
||||
Steve Marquess
|
||||
Tim Hudson
|
||||
Ulf Möller
|
||||
Viktor Dukhovni
|
||||
@@ -9,6 +9,23 @@
|
||||
|
||||
Changes between 1.1.0h and 1.1.1 [xx XXX xxxx]
|
||||
|
||||
*) Revert blinding in ECDSA sign and instead make problematic addition
|
||||
length-invariant. Switch even to fixed-length Montgomery multiplication.
|
||||
[Andy Polyakov]
|
||||
|
||||
*) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
|
||||
step for binary curves. The new implementation is based on formulas from
|
||||
differential addition-and-doubling in mixed Lopez-Dahab projective
|
||||
coordinates, modified to independently blind the operands.
|
||||
[Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
|
||||
|
||||
*) Add a scaffold to optionally enhance the Montgomery ladder implementation
|
||||
for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing
|
||||
EC_METHODs to implement their own specialized "ladder step", to take
|
||||
advantage of more favorable coordinate systems or more efficient
|
||||
differential addition-and-doubling algorithms.
|
||||
[Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
|
||||
|
||||
*) Modified the random device based seed sources to keep the relevant
|
||||
file descriptors open rather than reopening them on each access.
|
||||
This allows such sources to operate in a chroot() jail without
|
||||
@@ -196,12 +213,12 @@
|
||||
|
||||
Some of its new features are:
|
||||
o Support for multiple DRBG instances with seed chaining.
|
||||
o Add a public DRBG instance for the default RAND method.
|
||||
o Add a dedicated DRBG instance for generating long term private keys.
|
||||
o Make the DRBG instances fork-safe.
|
||||
o The default RAND method makes use of a DRBG.
|
||||
o There is a public and private DRBG instance.
|
||||
o The DRBG instances are fork-safe.
|
||||
o Keep all global DRBG instances on the secure heap if it is enabled.
|
||||
o Add a DRBG instance to every SSL instance for lock free operation
|
||||
and to increase unpredictability.
|
||||
o The public and private DRBG instance are per thread for lock free
|
||||
operation
|
||||
[Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre]
|
||||
|
||||
*) Changed Configure so it only says what it does and doesn't dump
|
||||
|
||||
@@ -180,7 +180,7 @@ CFLAGS={- join('', @{$config{CFLAGS}}) -}
|
||||
LDFLAGS={- join('', @{$config{LFLAGS}}) -}
|
||||
EX_LIBS={- join('', map { ",$_" } @{$config{LDLIBS}}) -}
|
||||
|
||||
PERL={- $config{perl} -}
|
||||
PERL={- $config{PERL} -}
|
||||
|
||||
AS={- $config{AS} -}
|
||||
ASFLAGS={- join(' ', @{$config{ASFLAGS}}) -}
|
||||
|
||||
@@ -212,7 +212,7 @@ EX_LIBS= {- join(' ', @{$config{LDLIBS}}) -}
|
||||
|
||||
MAKEDEPEND={- $config{makedepprog} -}
|
||||
|
||||
PERL={- $config{perl} -}
|
||||
PERL={- $config{PERL} -}
|
||||
|
||||
AR=$(CROSS_COMPILE){- $config{AR} -}
|
||||
ARFLAGS= {- join(' ', @{$config{ARFLAGS}}) -}
|
||||
|
||||
@@ -92,20 +92,20 @@ GENERATED={- # common0.tmpl provides @generated
|
||||
join(" ", map { (my $x = $_) =~ s|\.[sS]$|.asm|; $x }
|
||||
@generated) -}
|
||||
|
||||
INSTALL_LIBS={- join(" ", map { lib($_) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBS={- join(" ", map { shlib($_) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; shlib($_) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_ENGINES={- join(" ", map { dso($_) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_ENGINEPDBS={- join(" ", map { local $dsoext = ".pdb"; dso($_) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_PROGRAMS={- join(" ", map { $_.$exeext } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -}
|
||||
INSTALL_PROGRAMPDBS={- join(" ", map { $_.".pdb" } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -}
|
||||
INSTALL_LIBS={- join(" ", map { quotify1(lib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBS={- join(" ", map { quotify1(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_SHLIBPDBS={- join(" ", map { local $shlibext = ".pdb"; quotify1(shlib($_)) } @{$unified_info{install}->{libraries}}) -}
|
||||
INSTALL_ENGINES={- join(" ", map { quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_ENGINEPDBS={- join(" ", map { local $dsoext = ".pdb"; quotify1(dso($_)) } @{$unified_info{install}->{engines}}) -}
|
||||
INSTALL_PROGRAMS={- join(" ", map { quotify1($_.$exeext) } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -}
|
||||
INSTALL_PROGRAMPDBS={- join(" ", map { quotify1($_.".pdb") } grep { !m|^test\\| } @{$unified_info{install}->{programs}}) -}
|
||||
{- output_off() if $disabled{apps}; "" -}
|
||||
BIN_SCRIPTS=$(BLDDIR)\tools\c_rehash.pl
|
||||
MISC_SCRIPTS=$(BLDDIR)\apps\CA.pl $(BLDDIR)\apps\tsget.pl
|
||||
BIN_SCRIPTS="$(BLDDIR)\tools\c_rehash.pl"
|
||||
MISC_SCRIPTS="$(BLDDIR)\apps\CA.pl" "$(BLDDIR)\apps\tsget.pl"
|
||||
{- output_on() if $disabled{apps}; "" -}
|
||||
|
||||
APPS_OPENSSL={- use File::Spec::Functions;
|
||||
catfile("apps","openssl") -}
|
||||
"\"".catfile("apps","openssl")."\"" -}
|
||||
|
||||
# Do not edit these manually. Use Configure with --prefix or --openssldir
|
||||
# to change this! Short explanation in the top comment in Configure
|
||||
@@ -173,7 +173,7 @@ LD={- $config{LD} -}
|
||||
LDFLAGS={- join(' ', @{$config{LDFLAGS}}) -}
|
||||
EX_LIBS={- join(' ', @{$config{LDLIBS}}) -}
|
||||
|
||||
PERL={- $config{perl} -}
|
||||
PERL={- $config{PERL} -}
|
||||
|
||||
AR={- $config{AR} -}
|
||||
ARFLAGS= {- join(' ', @{$config{ARFLAGS}}) -}
|
||||
@@ -186,6 +186,8 @@ ASFLAGS={- join(' ', @{$config{ASFLAGS}}) -}
|
||||
|
||||
RC={- $config{RC} -}
|
||||
|
||||
ECHO="$(PERL)" "$(SRCDIR)\util\echo.pl"
|
||||
|
||||
##### Special command flags ##########################################
|
||||
|
||||
COUTFLAG={- $target{coutflag} -}$(OSSL_EMPTY)
|
||||
@@ -319,15 +321,15 @@ build_apps build_tests: build_programs
|
||||
# Convenience target to prebuild all generated files, not just the mandatory
|
||||
# ones
|
||||
build_all_generated: $(GENERATED_MANDATORY) $(GENERATED)
|
||||
@rem {- output_off() if $disabled{makedepend}; "" -}
|
||||
@echo "Warning: consider configuring with no-makedepend, because if"
|
||||
@echo " target system doesn't have $(PERL),"
|
||||
@echo " then make will fail..."
|
||||
@rem {- output_on() if $disabled{makedepend}; "" -}
|
||||
@{- output_off() if $disabled{makedepend}; "" -}
|
||||
@$(ECHO) "Warning: consider configuring with no-makedepend, because if"
|
||||
@$(ECHO) " target system doesn't have $(PERL),"
|
||||
@$(ECHO) " then make will fail..."
|
||||
@{- output_on() if $disabled{makedepend}; "" -}
|
||||
|
||||
test: tests
|
||||
{- dependmagic('tests'); -}: build_programs_nodep build_engines_nodep
|
||||
@rem {- output_off() if $disabled{tests}; "" -}
|
||||
@{- output_off() if $disabled{tests}; "" -}
|
||||
-mkdir $(BLDDIR)\test\test-runs
|
||||
set SRCTOP=$(SRCDIR)
|
||||
set BLDTOP=$(BLDDIR)
|
||||
@@ -336,17 +338,17 @@ test: tests
|
||||
set OPENSSL_ENGINES=$(MAKEDIR)\engines
|
||||
set OPENSSL_DEBUG_MEMORY=on
|
||||
"$(PERL)" "$(SRCDIR)\test\run_tests.pl" $(TESTS)
|
||||
@rem {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
|
||||
@echo "Tests are not supported with your chosen Configure options"
|
||||
@rem {- output_on() if !$disabled{tests}; "" -}
|
||||
@{- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
|
||||
@$(ECHO) "Tests are not supported with your chosen Configure options"
|
||||
@{- output_on() if !$disabled{tests}; "" -}
|
||||
|
||||
list-tests:
|
||||
@rem {- output_off() if $disabled{tests}; "" -}
|
||||
@{- output_off() if $disabled{tests}; "" -}
|
||||
@set SRCTOP=$(SRCDIR)
|
||||
@"$(PERL)" "$(SRCDIR)\test\run_tests.pl" list
|
||||
@rem {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
|
||||
@echo "Tests are not supported with your chosen Configure options"
|
||||
@rem {- output_on() if !$disabled{tests}; "" -}
|
||||
@{- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
|
||||
@$(ECHO) "Tests are not supported with your chosen Configure options"
|
||||
@{- output_on() if !$disabled{tests}; "" -}
|
||||
|
||||
install: install_sw install_ssldirs install_docs
|
||||
|
||||
@@ -373,9 +375,9 @@ distclean: clean
|
||||
-del /Q /F makefile
|
||||
|
||||
depend:
|
||||
@ rem {- output_off() if $disabled{makedepend}; "" -}
|
||||
@ {- output_off() if $disabled{makedepend}; "" -}
|
||||
@ "$(PERL)" "$(SRCDIR)\util\add-depends.pl" "VC"
|
||||
@ rem {- output_on() if $disabled{makedepend}; "" -}
|
||||
@ {- output_on() if $disabled{makedepend}; "" -}
|
||||
|
||||
# Install helper targets #############################################
|
||||
|
||||
@@ -405,17 +407,17 @@ install_ssldirs:
|
||||
"$(OPENSSLDIR)\ct_log_list.cnf"
|
||||
|
||||
install_dev:
|
||||
@if "$(INSTALLTOP)"=="" ( echo INSTALLTOP should not be empty & exit 1 )
|
||||
@echo *** Installing development files
|
||||
@if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 )
|
||||
@$(ECHO) "*** Installing development files"
|
||||
@"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\include\openssl"
|
||||
@rem {- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -}
|
||||
@{- output_off() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -}
|
||||
@"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(SRCDIR)\ms\applink.c" \
|
||||
"$(INSTALLTOP)\include\openssl"
|
||||
@rem {- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -}
|
||||
@{- output_on() unless grep { $_ eq "OPENSSL_USE_APPLINK" } @{$config{defines}}; "" -}
|
||||
@"$(PERL)" "$(SRCDIR)\util\copy.pl" "-exclude_re=/__DECC_" \
|
||||
"$(SRCDIR)\include\openssl\*.h" \
|
||||
"$(INSTALLTOP)\include\openssl"
|
||||
@"$(PERL)" "$(SRCDIR)\util\copy.pl" $(BLDDIR)\include\openssl\*.h \
|
||||
@"$(PERL)" "$(SRCDIR)\util\copy.pl" "$(BLDDIR)\include\openssl\*.h" \
|
||||
"$(INSTALLTOP)\include\openssl"
|
||||
@"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(libdir)"
|
||||
@"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_LIBS) "$(libdir)"
|
||||
@@ -425,8 +427,8 @@ install_dev:
|
||||
uninstall_dev:
|
||||
|
||||
install_engines:
|
||||
@if "$(INSTALLTOP)"=="" ( echo INSTALLTOP should not be empty & exit 1 )
|
||||
@echo *** Installing engines
|
||||
@if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 )
|
||||
@$(ECHO) "*** Installing engines"
|
||||
@"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(ENGINESDIR)"
|
||||
@if not "$(ENGINES)"=="" \
|
||||
"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_ENGINES) "$(ENGINESDIR)"
|
||||
@@ -436,8 +438,8 @@ install_engines:
|
||||
uninstall_engines:
|
||||
|
||||
install_runtime:
|
||||
@if "$(INSTALLTOP)"=="" ( echo INSTALLTOP should not be empty & exit 1 )
|
||||
@echo *** Installing runtime files
|
||||
@if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 )
|
||||
@$(ECHO) "*** Installing runtime files"
|
||||
@"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(INSTALLTOP)\bin"
|
||||
@if not "$(SHLIBS)"=="" \
|
||||
"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_SHLIBS) "$(INSTALLTOP)\bin"
|
||||
@@ -462,13 +464,13 @@ uninstall_html_docs:
|
||||
# Building targets ###################################################
|
||||
|
||||
configdata.pm: "$(SRCDIR)\Configure" {- join(" ", map { '"'.$_.'"' } @{$config{build_file_templates}}, @{$config{build_infos}}, @{$config{conf_files}}) -}
|
||||
@echo "Detected changed: $?"
|
||||
@$(ECHO) "Detected changed: $?"
|
||||
"$(PERL)" configdata.pm -r
|
||||
@echo "**************************************************"
|
||||
@echo "*** ***"
|
||||
@echo "*** Please run the same make command again ***"
|
||||
@echo "*** ***"
|
||||
@echo "**************************************************"
|
||||
@$(ECHO) "**************************************************"
|
||||
@$(ECHO) "*** ***"
|
||||
@$(ECHO) "*** Please run the same make command again ***"
|
||||
@$(ECHO) "*** ***"
|
||||
@$(ECHO) "**************************************************"
|
||||
@exit 1
|
||||
|
||||
reconfigure reconf:
|
||||
@@ -740,8 +742,6 @@ EOF
|
||||
foreach my $prod (@{$unified_info{dirinfo}->{$dir}->{products}->{$type}}) {
|
||||
if (dirname($prod) eq $dir) {
|
||||
push @deps, $prod.$extinfo{$type};
|
||||
} else {
|
||||
push @actions, "\t@rem No support to produce $type ".join(", ", @{$unified_info{dirinfo}->{$dir}->{products}->{$type}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,6 +553,7 @@ my %user = (
|
||||
LDLIBS => [], # -l
|
||||
MT => undef,
|
||||
MTFLAGS => [],
|
||||
PERL => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
|
||||
RANLIB => env('RANLIB'),
|
||||
RC => env('RC') || env('WINDRES'),
|
||||
RCFLAGS => [],
|
||||
@@ -1117,10 +1118,8 @@ $target{dso_extension}//=$target{shared_extension_simple};
|
||||
($target{shared_import_extension}=$target{shared_extension_simple}.".a")
|
||||
if ($config{target} =~ /^(?:Cygwin|mingw)/);
|
||||
|
||||
# Allow overriding the names of some tools. USE WITH CARE
|
||||
# Note: only Unix cares about HASHBANGPERL... that explains
|
||||
# the default string.
|
||||
$config{perl} = ($^O ne "VMS" ? $^X : "perl");
|
||||
# Fill %config with values from %user, and in case those are undefined or
|
||||
# empty, use values from %target (acting as a default).
|
||||
foreach (keys %user) {
|
||||
my $ref_type = ref $user{$_};
|
||||
|
||||
@@ -2459,7 +2458,7 @@ _____
|
||||
if ($dump || $cmdline) {
|
||||
print "\nCommand line (with current working directory = $here):\n\n";
|
||||
print ' ',join(' ',
|
||||
$config{perl},
|
||||
$config{PERL},
|
||||
catfile($config{sourcedir}, 'Configure'),
|
||||
@{$config{perlargv}}), "\n";
|
||||
print "\nPerl information:\n\n";
|
||||
@@ -3065,7 +3064,7 @@ sub run_dofile
|
||||
foreach (@templates) {
|
||||
die "Can't open $_, $!" unless -f $_;
|
||||
}
|
||||
my $perlcmd = (quotify("maybeshell", $config{perl}))[0];
|
||||
my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
|
||||
my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
|
||||
#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
|
||||
system($cmd);
|
||||
|
||||
+12
-14
@@ -24,7 +24,6 @@
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/lhash.h>
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
# include <openssl/rsa.h>
|
||||
@@ -177,21 +176,22 @@ static void exts_cleanup(OPENSSL_STRING *x)
|
||||
static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
|
||||
{
|
||||
char *p;
|
||||
size_t off;
|
||||
|
||||
/* Check syntax. */
|
||||
if (strchr(kv, '=') == NULL)
|
||||
return 1;
|
||||
|
||||
/* Skip leading whitespace, make a copy. */
|
||||
while (*kv && isspace(*kv))
|
||||
if (*++kv == '\0')
|
||||
return 1;
|
||||
if ((p = strchr(kv, '=')) == NULL)
|
||||
return 1;
|
||||
off = p - kv;
|
||||
if ((kv = OPENSSL_strdup(kv)) == NULL)
|
||||
return -1;
|
||||
|
||||
/* Skip trailing space before the equal sign. */
|
||||
for (p = strchr(kv, '='); p > kv; --p)
|
||||
if (p[-1] != ' ' && p[-1] != '\t')
|
||||
for (p = kv + off; p > kv; --p)
|
||||
if (!isspace(p[-1]))
|
||||
break;
|
||||
if (p == kv) {
|
||||
OPENSSL_free(kv);
|
||||
@@ -199,16 +199,13 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
/* Finally have a clean "key"; see if it's there. */
|
||||
if (lh_OPENSSL_STRING_retrieve(addexts, (OPENSSL_STRING*)kv) != NULL) {
|
||||
BIO_printf(bio_err, "Extension \"%s\" repeated\n", kv);
|
||||
OPENSSL_free(kv);
|
||||
return 1;
|
||||
/* Finally have a clean "key"; see if it's there [by attempt to add it]. */
|
||||
if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
|
||||
!= NULL || lh_OPENSSL_STRING_error(addexts)) {
|
||||
OPENSSL_free(p != NULL ? p : kv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Not found; add it. */
|
||||
if (lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv) == NULL)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -950,6 +947,7 @@ int req_main(int argc, char **argv)
|
||||
ERR_print_errors(bio_err);
|
||||
}
|
||||
NCONF_free(req_conf);
|
||||
NCONF_free(addext_conf);
|
||||
BIO_free(addext_bio);
|
||||
BIO_free(in);
|
||||
BIO_free_all(out);
|
||||
|
||||
+15
-7
@@ -903,14 +903,18 @@ static int EVP_Update_loop(void *args)
|
||||
if (decrypt) {
|
||||
for (count = 0; COND(nb_iter); count++) {
|
||||
rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
|
||||
if (rc != 1)
|
||||
if (rc != 1) {
|
||||
/* reset iv in case of counter overflow */
|
||||
EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (count = 0; COND(nb_iter); count++) {
|
||||
rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
|
||||
if (rc != 1)
|
||||
if (rc != 1) {
|
||||
/* reset iv in case of counter overflow */
|
||||
EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (decrypt)
|
||||
@@ -937,20 +941,24 @@ static int EVP_Update_loop_ccm(void *args)
|
||||
#endif
|
||||
if (decrypt) {
|
||||
for (count = 0; COND(nb_iter); count++) {
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
|
||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag);
|
||||
EVP_DecryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
|
||||
/* reset iv */
|
||||
EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
|
||||
/* counter is reset on every update */
|
||||
EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
|
||||
EVP_DecryptFinal_ex(ctx, buf, &outl);
|
||||
}
|
||||
} else {
|
||||
for (count = 0; COND(nb_iter); count++) {
|
||||
EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
|
||||
/* restore iv length field */
|
||||
EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
|
||||
/* counter is reset on every update */
|
||||
EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
|
||||
EVP_EncryptFinal_ex(ctx, buf, &outl);
|
||||
}
|
||||
}
|
||||
if (decrypt)
|
||||
EVP_DecryptFinal_ex(ctx, buf, &outl);
|
||||
else
|
||||
EVP_EncryptFinal_ex(ctx, buf, &outl);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
wnum.neg = 0;
|
||||
wnum.d = &(snum->d[loop]);
|
||||
wnum.top = div_n;
|
||||
wnum.flags = BN_FLG_STATIC_DATA;
|
||||
/*
|
||||
* only needed when BN_ucmp messes up the values between top and max
|
||||
*/
|
||||
|
||||
+26
-21
@@ -361,17 +361,17 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_to_montgomery(val[0], aa, mont, ctx))
|
||||
if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
|
||||
goto err; /* 1 */
|
||||
|
||||
window = BN_window_bits_for_exponent_size(bits);
|
||||
if (window > 1) {
|
||||
if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
|
||||
goto err; /* 2 */
|
||||
j = 1 << (window - 1);
|
||||
for (i = 1; i < j; i++) {
|
||||
if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx))
|
||||
!bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@@ -393,19 +393,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
for (i = 1; i < j; i++)
|
||||
r->d[i] = (~m->d[i]) & BN_MASK2;
|
||||
r->top = j;
|
||||
/*
|
||||
* Upper words will be zero if the corresponding words of 'm' were
|
||||
* 0xfff[...], so decrement r->top accordingly.
|
||||
*/
|
||||
bn_correct_top(r);
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
} else
|
||||
#endif
|
||||
if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
|
||||
if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
|
||||
goto err;
|
||||
for (;;) {
|
||||
if (BN_is_bit_set(p, wstart) == 0) {
|
||||
if (!start) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
if (wstart == 0)
|
||||
@@ -436,12 +432,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
/* add the 'bytes above' */
|
||||
if (!start)
|
||||
for (i = 0; i < j; i++) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* wvalue will be an odd number < 2^window */
|
||||
if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))
|
||||
goto err;
|
||||
|
||||
/* move the 'window' down further */
|
||||
@@ -451,6 +447,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
if (wstart < 0)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
|
||||
* removes padding [if any] and makes return value suitable for public
|
||||
* API consumer.
|
||||
*/
|
||||
#if defined(SPARC_T4_MONT)
|
||||
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
|
||||
j = mont->N.top; /* borrow j */
|
||||
@@ -575,7 +576,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
|
||||
}
|
||||
|
||||
b->top = top;
|
||||
bn_correct_top(b);
|
||||
b->flags |= BN_FLG_FIXED_TOP;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -747,16 +748,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
tmp.top = top;
|
||||
} else
|
||||
#endif
|
||||
if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
|
||||
if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
|
||||
goto err;
|
||||
|
||||
/* prepare a^1 in Montgomery domain */
|
||||
if (a->neg || BN_ucmp(a, m) >= 0) {
|
||||
if (!BN_nnmod(&am, a, m, ctx))
|
||||
goto err;
|
||||
if (!BN_to_montgomery(&am, &am, mont, ctx))
|
||||
if (!bn_to_mont_fixed_top(&am, &am, mont, ctx))
|
||||
goto err;
|
||||
} else if (!BN_to_montgomery(&am, a, mont, ctx))
|
||||
} else if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
|
||||
goto err;
|
||||
|
||||
#if defined(SPARC_T4_MONT)
|
||||
@@ -1034,14 +1035,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
* performance advantage of sqr over mul).
|
||||
*/
|
||||
if (window > 1) {
|
||||
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))
|
||||
goto err;
|
||||
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
|
||||
window))
|
||||
goto err;
|
||||
for (i = 3; i < numPowers; i++) {
|
||||
/* Calculate a^i = a^(i-1) * a */
|
||||
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))
|
||||
goto err;
|
||||
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
|
||||
window))
|
||||
@@ -1072,7 +1073,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
|
||||
/* Square the result window-size times */
|
||||
for (i = 0; i < window; i++)
|
||||
if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
@@ -1095,12 +1096,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
goto err;
|
||||
|
||||
/* Multiply the result into the intermediate result */
|
||||
if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))
|
||||
if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert the final result from montgomery to standard format */
|
||||
/*
|
||||
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
|
||||
* removes padding [if any] and makes return value suitable for public
|
||||
* API consumer.
|
||||
*/
|
||||
#if defined(SPARC_T4_MONT)
|
||||
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
|
||||
am.d[0] = 1; /* borrow am */
|
||||
|
||||
+17
-4
@@ -141,7 +141,16 @@
|
||||
*/
|
||||
|
||||
# ifdef BN_DEBUG
|
||||
# include <assert.h>
|
||||
/*
|
||||
* The new BN_FLG_FIXED_TOP flag marks vectors that were not treated with
|
||||
* bn_correct_top, in other words such vectors are permitted to have zeros
|
||||
* in most significant limbs. Such vectors are used internally to achieve
|
||||
* execution time invariance for critical operations with private keys.
|
||||
* It's BN_DEBUG-only flag, because user application is not supposed to
|
||||
* observe it anyway. Moreover, optimizing compiler would actually remove
|
||||
* all operations manipulating the bit in question in non-BN_DEBUG build.
|
||||
*/
|
||||
# define BN_FLG_FIXED_TOP 0x10000
|
||||
# ifdef BN_DEBUG_RAND
|
||||
# define bn_pollute(a) \
|
||||
do { \
|
||||
@@ -165,8 +174,10 @@
|
||||
do { \
|
||||
const BIGNUM *_bnum2 = (a); \
|
||||
if (_bnum2 != NULL) { \
|
||||
assert(((_bnum2->top == 0) && !_bnum2->neg) || \
|
||||
(_bnum2->top && (_bnum2->d[_bnum2->top - 1] != 0))); \
|
||||
int _top = _bnum2->top; \
|
||||
(void)ossl_assert((_top == 0 && !_bnum2->neg) || \
|
||||
(_top && ((_bnum2->flags & BN_FLG_FIXED_TOP) \
|
||||
|| _bnum2->d[_top - 1] != 0))); \
|
||||
bn_pollute(_bnum2); \
|
||||
} \
|
||||
} while(0)
|
||||
@@ -185,6 +196,7 @@
|
||||
|
||||
# else /* !BN_DEBUG */
|
||||
|
||||
# define BN_FLG_FIXED_TOP 0
|
||||
# define bn_pollute(a)
|
||||
# define bn_check_top(a)
|
||||
# define bn_fix_top(a) bn_correct_top(a)
|
||||
@@ -216,7 +228,8 @@ struct bignum_st {
|
||||
/* Used for montgomery multiplication */
|
||||
struct bn_mont_ctx_st {
|
||||
int ri; /* number of bits in R */
|
||||
BIGNUM RR; /* used to convert to montgomery form */
|
||||
BIGNUM RR; /* used to convert to montgomery form,
|
||||
possibly zero-padded */
|
||||
BIGNUM N; /* The modulus */
|
||||
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only
|
||||
* stored for bignum algorithm) */
|
||||
|
||||
+28
-20
@@ -12,6 +12,7 @@
|
||||
#include "internal/cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
#include <openssl/opensslconf.h>
|
||||
#include "internal/constant_time_locl.h"
|
||||
|
||||
/* This stuff appears to be completely unused, so is deprecated */
|
||||
#if OPENSSL_API_COMPAT < 0x00908000L
|
||||
@@ -209,8 +210,6 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
||||
{
|
||||
BN_ULONG *a = NULL;
|
||||
|
||||
bn_check_top(b);
|
||||
|
||||
if (words > (INT_MAX / (4 * BN_BITS2))) {
|
||||
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
|
||||
return NULL;
|
||||
@@ -245,8 +244,6 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
||||
|
||||
BIGNUM *bn_expand2(BIGNUM *b, int words)
|
||||
{
|
||||
bn_check_top(b);
|
||||
|
||||
if (words > b->dmax) {
|
||||
BN_ULONG *a = bn_expand_internal(b, words);
|
||||
if (!a)
|
||||
@@ -259,7 +256,6 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
|
||||
b->dmax = words;
|
||||
}
|
||||
|
||||
bn_check_top(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -294,15 +290,17 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
||||
if (b->top > 0)
|
||||
memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
|
||||
|
||||
a->top = b->top;
|
||||
a->neg = b->neg;
|
||||
a->top = b->top;
|
||||
a->flags |= b->flags & BN_FLG_FIXED_TOP;
|
||||
bn_check_top(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
|
||||
| BN_FLG_CONSTTIME \
|
||||
| BN_FLG_SECURE))
|
||||
| BN_FLG_SECURE \
|
||||
| BN_FLG_FIXED_TOP))
|
||||
#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
|
||||
|
||||
void BN_swap(BIGNUM *a, BIGNUM *b)
|
||||
@@ -343,8 +341,9 @@ void BN_clear(BIGNUM *a)
|
||||
bn_check_top(a);
|
||||
if (a->d != NULL)
|
||||
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
|
||||
a->top = 0;
|
||||
a->neg = 0;
|
||||
a->top = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
BN_ULONG BN_get_word(const BIGNUM *a)
|
||||
@@ -365,6 +364,7 @@ int BN_set_word(BIGNUM *a, BN_ULONG w)
|
||||
a->neg = 0;
|
||||
a->d[0] = w;
|
||||
a->top = (w ? 1 : 0);
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
bn_check_top(a);
|
||||
return 1;
|
||||
}
|
||||
@@ -417,24 +417,29 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
||||
/* ignore negative */
|
||||
static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
size_t i, inc, lasti, j;
|
||||
BN_ULONG l;
|
||||
|
||||
bn_check_top(a);
|
||||
i = BN_num_bytes(a);
|
||||
n = BN_num_bytes(a);
|
||||
if (tolen == -1)
|
||||
tolen = i;
|
||||
else if (tolen < i)
|
||||
tolen = n;
|
||||
else if (tolen < n)
|
||||
return -1;
|
||||
/* Add leading zeroes if necessary */
|
||||
if (tolen > i) {
|
||||
memset(to, 0, tolen - i);
|
||||
to += tolen - i;
|
||||
|
||||
if (n == 0) {
|
||||
OPENSSL_cleanse(to, tolen);
|
||||
return tolen;
|
||||
}
|
||||
while (i--) {
|
||||
|
||||
lasti = n - 1;
|
||||
for (i = 0, inc = 1, j = tolen; j > 0;) {
|
||||
l = a->d[i / BN_BYTES];
|
||||
*(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
|
||||
to[--j] = (unsigned char)(l >> (8 * (i % BN_BYTES)) & (0 - inc));
|
||||
inc = (i - lasti) >> (8 * sizeof(i) - 1);
|
||||
i += inc; /* stay on top limb */
|
||||
}
|
||||
|
||||
return tolen;
|
||||
}
|
||||
|
||||
@@ -601,6 +606,7 @@ int BN_set_bit(BIGNUM *a, int n)
|
||||
for (k = a->top; k < i + 1; k++)
|
||||
a->d[k] = 0;
|
||||
a->top = i + 1;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
a->d[i] |= (((BN_ULONG)1) << j);
|
||||
@@ -833,8 +839,9 @@ int BN_security_bits(int L, int N)
|
||||
|
||||
void BN_zero_ex(BIGNUM *a)
|
||||
{
|
||||
a->top = 0;
|
||||
a->neg = 0;
|
||||
a->top = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
}
|
||||
|
||||
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
|
||||
@@ -958,5 +965,6 @@ void bn_correct_top(BIGNUM *a)
|
||||
}
|
||||
if (a->top == 0)
|
||||
a->neg = 0;
|
||||
a->flags &= ~BN_FLG_FIXED_TOP;
|
||||
bn_pollute(a);
|
||||
}
|
||||
+60
-6
@@ -35,16 +35,70 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||
|
||||
/*
|
||||
* BN_mod_add variant that may be used if both a and b are non-negative and
|
||||
* less than m
|
||||
* less than m. The original algorithm was
|
||||
*
|
||||
* if (!BN_uadd(r, a, b))
|
||||
* return 0;
|
||||
* if (BN_ucmp(r, m) >= 0)
|
||||
* return BN_usub(r, r, m);
|
||||
*
|
||||
* which is replaced with addition, subtracting modulus, and conditional
|
||||
* move depending on whether or not subtraction borrowed.
|
||||
*/
|
||||
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m)
|
||||
{
|
||||
size_t i, ai, bi, mtop = m->top;
|
||||
BN_ULONG storage[1024 / BN_BITS2];
|
||||
BN_ULONG carry, temp, mask, *rp, *tp = storage;
|
||||
const BN_ULONG *ap, *bp;
|
||||
|
||||
if (bn_wexpand(r, mtop) == NULL)
|
||||
return 0;
|
||||
|
||||
if (mtop > sizeof(storage) / sizeof(storage[0])
|
||||
&& (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)
|
||||
return 0;
|
||||
|
||||
ap = a->d != NULL ? a->d : tp;
|
||||
bp = b->d != NULL ? b->d : tp;
|
||||
|
||||
for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) {
|
||||
mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));
|
||||
temp = ((ap[ai] & mask) + carry) & BN_MASK2;
|
||||
carry = (temp < carry);
|
||||
|
||||
mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));
|
||||
tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2;
|
||||
carry += (tp[i] < temp);
|
||||
|
||||
i++;
|
||||
ai += (i - a->dmax) >> (8 * sizeof(i) - 1);
|
||||
bi += (i - b->dmax) >> (8 * sizeof(i) - 1);
|
||||
}
|
||||
rp = r->d;
|
||||
carry -= bn_sub_words(rp, tp, m->d, mtop);
|
||||
for (i = 0; i < mtop; i++) {
|
||||
rp[i] = (carry & tp[i]) | (~carry & rp[i]);
|
||||
((volatile BN_ULONG *)tp)[i] = 0;
|
||||
}
|
||||
r->top = mtop;
|
||||
|
||||
if (tp != storage)
|
||||
OPENSSL_free(tp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m)
|
||||
{
|
||||
if (!BN_uadd(r, a, b))
|
||||
return 0;
|
||||
if (BN_ucmp(r, m) >= 0)
|
||||
return BN_usub(r, r, m);
|
||||
return 1;
|
||||
int ret = bn_mod_add_fixed_top(r, a, b, m);
|
||||
|
||||
if (ret)
|
||||
bn_correct_top(r);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||
|
||||
+43
-20
@@ -20,29 +20,43 @@
|
||||
#define MONT_WORD /* use the faster word-based algorithm */
|
||||
|
||||
#ifdef MONT_WORD
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
|
||||
static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
|
||||
#endif
|
||||
|
||||
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
BN_MONT_CTX *mont, BN_CTX *ctx)
|
||||
{
|
||||
int ret = bn_mul_mont_fixed_top(r, a, b, mont, ctx);
|
||||
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
BN_MONT_CTX *mont, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *tmp;
|
||||
int ret = 0;
|
||||
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
|
||||
int num = mont->N.top;
|
||||
|
||||
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
|
||||
if (num > 1 && a->top == num && b->top == num) {
|
||||
if (bn_wexpand(r, num) == NULL)
|
||||
return 0;
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((a->top + b->top) > 2 * num)
|
||||
return 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
if (tmp == NULL)
|
||||
@@ -58,13 +72,12 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
}
|
||||
/* reduce from aRR to aR */
|
||||
#ifdef MONT_WORD
|
||||
if (!BN_from_montgomery_word(r, tmp, mont))
|
||||
if (!bn_from_montgomery_word(r, tmp, mont))
|
||||
goto err;
|
||||
#else
|
||||
if (!BN_from_montgomery(r, tmp, mont, ctx))
|
||||
goto err;
|
||||
#endif
|
||||
bn_check_top(r);
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
@@ -72,7 +85,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
}
|
||||
|
||||
#ifdef MONT_WORD
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
{
|
||||
BIGNUM *n;
|
||||
BN_ULONG *ap, *np, *rp, n0, v, carry;
|
||||
@@ -95,12 +108,11 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
|
||||
/* clear the top words of T */
|
||||
i = max - r->top;
|
||||
if (i < 0)
|
||||
return 0;
|
||||
if (i)
|
||||
memset(&rp[r->top], 0, sizeof(*rp) * i);
|
||||
|
||||
r->top = max;
|
||||
r->flags |= BN_FLG_FIXED_TOP;
|
||||
n0 = mont->n0[0];
|
||||
|
||||
/*
|
||||
@@ -119,6 +131,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
if (bn_wexpand(ret, nl) == NULL)
|
||||
return 0;
|
||||
ret->top = nl;
|
||||
ret->flags |= BN_FLG_FIXED_TOP;
|
||||
ret->neg = r->neg;
|
||||
|
||||
rp = ret->d;
|
||||
@@ -129,20 +142,16 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
*/
|
||||
ap = &(r->d[nl]);
|
||||
|
||||
carry -= bn_sub_words(rp, ap, np, nl);
|
||||
/*
|
||||
* |v| is one if |ap| - |np| underflowed or zero if it did not. Note |v|
|
||||
* cannot be -1. That would imply the subtraction did not fit in |nl| words,
|
||||
* and we know at most one subtraction is needed.
|
||||
* |carry| is -1 if |ap| - |np| underflowed or zero if it did not. Note
|
||||
* |carry| cannot be 1. That would imply the subtraction did not fit in
|
||||
* |nl| words, and we know at most one subtraction is needed.
|
||||
*/
|
||||
v = bn_sub_words(rp, ap, np, nl) - carry;
|
||||
v = 0 - v;
|
||||
for (i = 0; i < nl; i++) {
|
||||
rp[i] = (v & ap[i]) | (~v & rp[i]);
|
||||
rp[i] = (carry & ap[i]) | (~carry & rp[i]);
|
||||
ap[i] = 0;
|
||||
}
|
||||
bn_correct_top(r);
|
||||
bn_correct_top(ret);
|
||||
bn_check_top(ret);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -156,8 +165,11 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
BIGNUM *t;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((t = BN_CTX_get(ctx)) && BN_copy(t, a))
|
||||
retn = BN_from_montgomery_word(ret, t, mont);
|
||||
if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
|
||||
retn = bn_from_montgomery_word(ret, t, mont);
|
||||
bn_correct_top(ret);
|
||||
bn_check_top(ret);
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
#else /* !MONT_WORD */
|
||||
BIGNUM *t1, *t2;
|
||||
@@ -195,6 +207,12 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
return retn;
|
||||
}
|
||||
|
||||
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);
|
||||
}
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_new(void)
|
||||
{
|
||||
BN_MONT_CTX *ret;
|
||||
@@ -232,7 +250,7 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont)
|
||||
|
||||
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
int i, ret = 0;
|
||||
BIGNUM *Ri, *R;
|
||||
|
||||
if (BN_is_zero(mod))
|
||||
@@ -367,6 +385,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
|
||||
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
|
||||
goto err;
|
||||
|
||||
for (i = mont->RR.top, ret = mont->N.top; i < ret; i++)
|
||||
mont->RR.d[i] = 0;
|
||||
mont->RR.top = ret;
|
||||
mont->RR.flags |= BN_FLG_FIXED_TOP;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
|
||||
+1
-1
@@ -254,7 +254,7 @@ static void nist_cp_bn_0(BN_ULONG *dst, const BN_ULONG *src, int top, int max)
|
||||
int i;
|
||||
|
||||
#ifdef BN_DEBUG
|
||||
assert(top <= max);
|
||||
(void)ossl_assert(top <= max);
|
||||
#endif
|
||||
for (i = 0; i < top; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
+2
-8
@@ -82,14 +82,8 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
|
||||
}
|
||||
|
||||
rr->neg = 0;
|
||||
/*
|
||||
* If the most-significant half of the top word of 'a' is zero, then the
|
||||
* square of 'a' will max-1 words.
|
||||
*/
|
||||
if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l))
|
||||
rr->top = max - 1;
|
||||
else
|
||||
rr->top = max;
|
||||
rr->top = max;
|
||||
bn_correct_top(rr);
|
||||
if (r != rr && BN_copy(r, rr) == NULL)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ static const ERR_STRING_DATA CONF_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SECTION), "no section"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SUCH_FILE), "no such file"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NUMBER_TOO_LARGE), "number too large"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE),
|
||||
"recursive directory include"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY),
|
||||
|
||||
+33
-13
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "internal/conf.h"
|
||||
#include "internal/ctype.h"
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/conf.h>
|
||||
@@ -123,6 +124,7 @@ long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
|
||||
int status;
|
||||
long result = 0;
|
||||
|
||||
ERR_set_mark();
|
||||
if (conf == NULL) {
|
||||
status = NCONF_get_number_e(NULL, group, name, &result);
|
||||
} else {
|
||||
@@ -130,12 +132,8 @@ long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
|
||||
CONF_set_nconf(&ctmp, conf);
|
||||
status = NCONF_get_number_e(&ctmp, group, name, &result);
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
/* This function does not believe in errors... */
|
||||
ERR_clear_error();
|
||||
}
|
||||
return result;
|
||||
ERR_pop_to_mark();
|
||||
return status == 0 ? 0L : result;
|
||||
}
|
||||
|
||||
void CONF_free(LHASH_OF(CONF_VALUE) *conf)
|
||||
@@ -277,10 +275,23 @@ char *NCONF_get_string(const CONF *conf, const char *group, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int default_is_number(const CONF *conf, char c)
|
||||
{
|
||||
return ossl_isdigit(c);
|
||||
}
|
||||
|
||||
static int default_to_int(const CONF *conf, char c)
|
||||
{
|
||||
return (int)(c - '0');
|
||||
}
|
||||
|
||||
int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
|
||||
long *result)
|
||||
{
|
||||
char *str;
|
||||
long res;
|
||||
int (*is_number)(const CONF *, char) = &default_is_number;
|
||||
int (*to_int)(const CONF *, char) = &default_to_int;
|
||||
|
||||
if (result == NULL) {
|
||||
CONFerr(CONF_F_NCONF_GET_NUMBER_E, ERR_R_PASSED_NULL_PARAMETER);
|
||||
@@ -292,14 +303,23 @@ int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
if (conf == NULL)
|
||||
*result = strtol(str, &str, 10);
|
||||
else
|
||||
for (*result = 0; conf->meth->is_number(conf, *str);) {
|
||||
*result = (*result) * 10 + conf->meth->to_int(conf, *str);
|
||||
str++;
|
||||
}
|
||||
if (conf != NULL) {
|
||||
if (conf->meth->is_number != NULL)
|
||||
is_number = conf->meth->is_number;
|
||||
if (conf->meth->to_int != NULL)
|
||||
to_int = conf->meth->to_int;
|
||||
}
|
||||
for (res = 0; is_number(conf, *str); str++) {
|
||||
const int d = to_int(conf, *str);
|
||||
|
||||
if (res > (LONG_MAX - d) / 10L) {
|
||||
CONFerr(CONF_F_NCONF_GET_NUMBER_E, CONF_R_NUMBER_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
res = res * 10 + d;
|
||||
}
|
||||
|
||||
*result = res;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# details see http://www.openssl.org/~appro/cryptogams/.
|
||||
# ====================================================================
|
||||
#
|
||||
# X25519 lower-level primitives for x86_86.
|
||||
# X25519 lower-level primitives for x86_64.
|
||||
#
|
||||
# February 2018.
|
||||
#
|
||||
@@ -102,13 +102,22 @@ $code.=<<___;
|
||||
.type x25519_fe51_mul,\@function,3
|
||||
.align 32
|
||||
x25519_fe51_mul:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_mul_body:
|
||||
|
||||
mov 8*0(%rsi),%rax # f[0]
|
||||
mov 8*0(%rdx),%r11 # load g[0-4]
|
||||
@@ -236,19 +245,30 @@ x25519_fe51_mul:
|
||||
|
||||
mov 8*4(%rsp),%rdi # restore 1st argument
|
||||
jmp .Lreduce51
|
||||
.Lfe51_mul_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_mul,.-x25519_fe51_mul
|
||||
|
||||
.globl x25519_fe51_sqr
|
||||
.type x25519_fe51_sqr,\@function,2
|
||||
.align 32
|
||||
x25519_fe51_sqr:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_sqr_body:
|
||||
|
||||
mov 8*0(%rsi),%rax # g[0]
|
||||
mov 8*2(%rsi),%r15 # g[2]
|
||||
@@ -391,27 +411,45 @@ x25519_fe51_sqr:
|
||||
mov %r10,8*4(%rdi)
|
||||
|
||||
mov 8*5(%rsp),%r15
|
||||
.cfi_restore %r15
|
||||
mov 8*6(%rsp),%r14
|
||||
.cfi_restore %r14
|
||||
mov 8*7(%rsp),%r13
|
||||
.cfi_restore %r13
|
||||
mov 8*8(%rsp),%r12
|
||||
.cfi_restore %r12
|
||||
mov 8*9(%rsp),%rbx
|
||||
.cfi_restore %rbx
|
||||
mov 8*10(%rsp),%rbp
|
||||
.cfi_restore %rbp
|
||||
lea 8*11(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 88
|
||||
.Lfe51_sqr_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_sqr,.-x25519_fe51_sqr
|
||||
|
||||
.globl x25519_fe51_mul121666
|
||||
.type x25519_fe51_mul121666,\@function,2
|
||||
.align 32
|
||||
x25519_fe51_mul121666:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
mov \$121666,%eax
|
||||
.cfi_push %r15
|
||||
lea -8*5(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 40
|
||||
.Lfe51_mul121666_body:
|
||||
mov \$121666,%eax
|
||||
|
||||
mulq 8*0(%rsi)
|
||||
mov %rax,%rbx # %rbx:%rcx = h0
|
||||
@@ -434,6 +472,8 @@ x25519_fe51_mul121666:
|
||||
mov %rdx,%r15
|
||||
|
||||
jmp .Lreduce51
|
||||
.Lfe51_mul121666_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe51_mul121666,.-x25519_fe51_mul121666
|
||||
___
|
||||
########################################################################
|
||||
@@ -460,14 +500,24 @@ x25519_fe64_eligible:
|
||||
.type x25519_fe64_mul,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_mul:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
push %rdi # offload dst
|
||||
.cfi_push %rdi
|
||||
lea -8*2(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 16
|
||||
.Lfe64_mul_body:
|
||||
|
||||
mov %rdx,%rax
|
||||
mov 8*0(%rdx),%rbp # b[0]
|
||||
@@ -534,20 +584,32 @@ x25519_fe64_mul:
|
||||
adox %rdi,$acc7 # of=0
|
||||
|
||||
jmp .Lreduce64
|
||||
.Lfe64_mul_epilogue:
|
||||
.cfi_endproc
|
||||
.size x25519_fe64_mul,.-x25519_fe64_mul
|
||||
|
||||
.globl x25519_fe64_sqr
|
||||
.type x25519_fe64_sqr,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_sqr:
|
||||
.cfi_startproc
|
||||
push %rbp
|
||||
.cfi_push %rbp
|
||||
push %rbx
|
||||
.cfi_push %rbx
|
||||
push %r12
|
||||
.cfi_push %r12
|
||||
push %r13
|
||||
.cfi_push %r13
|
||||
push %r14
|
||||
.cfi_push %r14
|
||||
push %r15
|
||||
.cfi_push %r15
|
||||
push %rdi # offload dst
|
||||
.cfi_push %rdi
|
||||
lea -8*2(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 16
|
||||
.Lfe64_sqr_body:
|
||||
|
||||
mov 8*0(%rsi),%rdx # a[0]
|
||||
mov 8*1(%rsi),%rcx # a[1]
|
||||
@@ -637,19 +699,29 @@ x25519_fe64_sqr:
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
mov 8*3(%rsp),%r15
|
||||
.cfi_restore %r15
|
||||
mov 8*4(%rsp),%r14
|
||||
.cfi_restore %r14
|
||||
mov 8*5(%rsp),%r13
|
||||
.cfi_restore %r13
|
||||
mov 8*6(%rsp),%r12
|
||||
.cfi_restore %r12
|
||||
mov 8*7(%rsp),%rbx
|
||||
.cfi_restore %rbx
|
||||
mov 8*8(%rsp),%rbp
|
||||
.cfi_restore %rbp
|
||||
lea 8*9(%rsp),%rsp
|
||||
.cfi_adjust_cfa_offset 88
|
||||
.Lfe64_sqr_epilogue:
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size x25519_fe64_sqr,.-x25519_fe64_sqr
|
||||
|
||||
.globl x25519_fe64_mul121666
|
||||
.type x25519_fe64_mul121666,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_mul121666:
|
||||
.Lfe64_mul121666_body:
|
||||
mov \$121666,%edx
|
||||
mulx 8*0(%rsi),$acc0,%rcx
|
||||
mulx 8*1(%rsi),$acc1,%rax
|
||||
@@ -676,6 +748,7 @@ x25519_fe64_mul121666:
|
||||
mov $acc3,8*3(%rdi)
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_mul121666_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_mul121666,.-x25519_fe64_mul121666
|
||||
|
||||
@@ -683,6 +756,7 @@ x25519_fe64_mul121666:
|
||||
.type x25519_fe64_add,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_add:
|
||||
.Lfe64_add_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -698,13 +772,18 @@ x25519_fe64_add:
|
||||
|
||||
add %rax,$acc0
|
||||
adc \$0,$acc1
|
||||
mov $acc0,8*0(%rdi)
|
||||
adc \$0,$acc2
|
||||
mov $acc1,8*1(%rdi)
|
||||
adc \$0,$acc3
|
||||
mov $acc2,8*2(%rdi)
|
||||
sbb %rax,%rax # cf -> mask
|
||||
mov $acc3,8*3(%rdi)
|
||||
and \$38,%rax
|
||||
|
||||
add %rax,$acc0
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_add_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_add,.-x25519_fe64_add
|
||||
|
||||
@@ -712,6 +791,7 @@ x25519_fe64_add:
|
||||
.type x25519_fe64_sub,\@function,3
|
||||
.align 32
|
||||
x25519_fe64_sub:
|
||||
.Lfe64_sub_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -727,13 +807,18 @@ x25519_fe64_sub:
|
||||
|
||||
sub %rax,$acc0
|
||||
sbb \$0,$acc1
|
||||
mov $acc0,8*0(%rdi)
|
||||
sbb \$0,$acc2
|
||||
mov $acc1,8*1(%rdi)
|
||||
sbb \$0,$acc3
|
||||
mov $acc2,8*2(%rdi)
|
||||
sbb %rax,%rax # cf -> mask
|
||||
mov $acc3,8*3(%rdi)
|
||||
and \$38,%rax
|
||||
|
||||
sub %rax,$acc0
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_sub_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_sub,.-x25519_fe64_sub
|
||||
|
||||
@@ -741,6 +826,7 @@ x25519_fe64_sub:
|
||||
.type x25519_fe64_tobytes,\@function,2
|
||||
.align 32
|
||||
x25519_fe64_tobytes:
|
||||
.Lfe64_to_body:
|
||||
mov 8*0(%rsi),$acc0
|
||||
mov 8*1(%rsi),$acc1
|
||||
mov 8*2(%rsi),$acc2
|
||||
@@ -751,6 +837,7 @@ x25519_fe64_tobytes:
|
||||
sar \$63,$acc3 # most significant bit -> mask
|
||||
shr \$1,%rax # most significant bit cleared
|
||||
and \$19,$acc3
|
||||
add \$19,$acc3 # compare to modulus in the same go
|
||||
|
||||
add $acc3,$acc0
|
||||
adc \$0,$acc1
|
||||
@@ -760,15 +847,20 @@ x25519_fe64_tobytes:
|
||||
lea (%rax,%rax),$acc3
|
||||
sar \$63,%rax # most significant bit -> mask
|
||||
shr \$1,$acc3 # most significant bit cleared
|
||||
not %rax
|
||||
and \$19,%rax
|
||||
|
||||
add %rax,$acc0
|
||||
sub %rax,$acc0
|
||||
sbb \$0,$acc1
|
||||
sbb \$0,$acc2
|
||||
sbb \$0,$acc3
|
||||
|
||||
mov $acc0,8*0(%rdi)
|
||||
mov $acc1,8*1(%rdi)
|
||||
mov $acc2,8*2(%rdi)
|
||||
mov $acc3,8*3(%rdi)
|
||||
mov $acc0,8*0(%rdi)
|
||||
|
||||
.Lfe64_to_epilogue:
|
||||
ret
|
||||
.size x25519_fe64_tobytes,.-x25519_fe64_tobytes
|
||||
___
|
||||
@@ -804,6 +896,222 @@ $code.=<<___;
|
||||
.asciz "X25519 primitives for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
___
|
||||
|
||||
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
|
||||
# CONTEXT *context,DISPATCHER_CONTEXT *disp)
|
||||
if ($win64) {
|
||||
$rec="%rcx";
|
||||
$frame="%rdx";
|
||||
$context="%r8";
|
||||
$disp="%r9";
|
||||
|
||||
$code.=<<___;
|
||||
.extern __imp_RtlVirtualUnwind
|
||||
|
||||
.type short_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
short_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
pushfq
|
||||
sub \$64,%rsp
|
||||
|
||||
mov 120($context),%rax # pull context->Rax
|
||||
mov 248($context),%rbx # pull context->Rip
|
||||
|
||||
mov 8($disp),%rsi # disp->ImageBase
|
||||
mov 56($disp),%r11 # disp->HandlerData
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # end of prologue label
|
||||
cmp %r10,%rbx # context->Rip<end of prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
jmp .Lcommon_seh_tail
|
||||
.size short_handler,.-short_handler
|
||||
|
||||
.type full_handler,\@abi-omnipotent
|
||||
.align 16
|
||||
full_handler:
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
pushfq
|
||||
sub \$64,%rsp
|
||||
|
||||
mov 120($context),%rax # pull context->Rax
|
||||
mov 248($context),%rbx # pull context->Rip
|
||||
|
||||
mov 8($disp),%rsi # disp->ImageBase
|
||||
mov 56($disp),%r11 # disp->HandlerData
|
||||
|
||||
mov 0(%r11),%r10d # HandlerData[0]
|
||||
lea (%rsi,%r10),%r10 # end of prologue label
|
||||
cmp %r10,%rbx # context->Rip<end of prologue label
|
||||
jb .Lcommon_seh_tail
|
||||
|
||||
mov 152($context),%rax # pull context->Rsp
|
||||
|
||||
mov 4(%r11),%r10d # HandlerData[1]
|
||||
lea (%rsi,%r10),%r10 # epilogue label
|
||||
cmp %r10,%rbx # context->Rip>=epilogue label
|
||||
jae .Lcommon_seh_tail
|
||||
|
||||
mov 8(%r11),%r10d # HandlerData[2]
|
||||
lea (%rax,%r10),%rax
|
||||
|
||||
mov -8(%rax),%rbp
|
||||
mov -16(%rax),%rbx
|
||||
mov -24(%rax),%r12
|
||||
mov -32(%rax),%r13
|
||||
mov -40(%rax),%r14
|
||||
mov -48(%rax),%r15
|
||||
mov %rbx,144($context) # restore context->Rbx
|
||||
mov %rbp,160($context) # restore context->Rbp
|
||||
mov %r12,216($context) # restore context->R12
|
||||
mov %r13,224($context) # restore context->R13
|
||||
mov %r14,232($context) # restore context->R14
|
||||
mov %r15,240($context) # restore context->R15
|
||||
|
||||
.Lcommon_seh_tail:
|
||||
mov 8(%rax),%rdi
|
||||
mov 16(%rax),%rsi
|
||||
mov %rax,152($context) # restore context->Rsp
|
||||
mov %rsi,168($context) # restore context->Rsi
|
||||
mov %rdi,176($context) # restore context->Rdi
|
||||
|
||||
mov 40($disp),%rdi # disp->ContextRecord
|
||||
mov $context,%rsi # context
|
||||
mov \$154,%ecx # sizeof(CONTEXT)
|
||||
.long 0xa548f3fc # cld; rep movsq
|
||||
|
||||
mov $disp,%rsi
|
||||
xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
|
||||
mov 8(%rsi),%rdx # arg2, disp->ImageBase
|
||||
mov 0(%rsi),%r8 # arg3, disp->ControlPc
|
||||
mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
|
||||
mov 40(%rsi),%r10 # disp->ContextRecord
|
||||
lea 56(%rsi),%r11 # &disp->HandlerData
|
||||
lea 24(%rsi),%r12 # &disp->EstablisherFrame
|
||||
mov %r10,32(%rsp) # arg5
|
||||
mov %r11,40(%rsp) # arg6
|
||||
mov %r12,48(%rsp) # arg7
|
||||
mov %rcx,56(%rsp) # arg8, (NULL)
|
||||
call *__imp_RtlVirtualUnwind(%rip)
|
||||
|
||||
mov \$1,%eax # ExceptionContinueSearch
|
||||
add \$64,%rsp
|
||||
popfq
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %rbp
|
||||
pop %rbx
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
ret
|
||||
.size full_handler,.-full_handler
|
||||
|
||||
.section .pdata
|
||||
.align 4
|
||||
.rva .LSEH_begin_x25519_fe51_mul
|
||||
.rva .LSEH_end_x25519_fe51_mul
|
||||
.rva .LSEH_info_x25519_fe51_mul
|
||||
|
||||
.rva .LSEH_begin_x25519_fe51_sqr
|
||||
.rva .LSEH_end_x25519_fe51_sqr
|
||||
.rva .LSEH_info_x25519_fe51_sqr
|
||||
|
||||
.rva .LSEH_begin_x25519_fe51_mul121666
|
||||
.rva .LSEH_end_x25519_fe51_mul121666
|
||||
.rva .LSEH_info_x25519_fe51_mul121666
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.rva .LSEH_begin_x25519_fe64_mul
|
||||
.rva .LSEH_end_x25519_fe64_mul
|
||||
.rva .LSEH_info_x25519_fe64_mul
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_sqr
|
||||
.rva .LSEH_end_x25519_fe64_sqr
|
||||
.rva .LSEH_info_x25519_fe64_sqr
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_mul121666
|
||||
.rva .LSEH_end_x25519_fe64_mul121666
|
||||
.rva .LSEH_info_x25519_fe64_mul121666
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_add
|
||||
.rva .LSEH_end_x25519_fe64_add
|
||||
.rva .LSEH_info_x25519_fe64_add
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_sub
|
||||
.rva .LSEH_end_x25519_fe64_sub
|
||||
.rva .LSEH_info_x25519_fe64_sub
|
||||
|
||||
.rva .LSEH_begin_x25519_fe64_tobytes
|
||||
.rva .LSEH_end_x25519_fe64_tobytes
|
||||
.rva .LSEH_info_x25519_fe64_tobytes
|
||||
___
|
||||
$code.=<<___;
|
||||
.section .xdata
|
||||
.align 8
|
||||
.LSEH_info_x25519_fe51_mul:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_mul_body,.Lfe51_mul_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
.LSEH_info_x25519_fe51_sqr:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_sqr_body,.Lfe51_sqr_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
.LSEH_info_x25519_fe51_mul121666:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe51_mul121666_body,.Lfe51_mul121666_epilogue # HandlerData[]
|
||||
.long 88,0
|
||||
___
|
||||
$code.=<<___ if ($addx);
|
||||
.LSEH_info_x25519_fe64_mul:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe64_mul_body,.Lfe64_mul_epilogue # HandlerData[]
|
||||
.long 72,0
|
||||
.LSEH_info_x25519_fe64_sqr:
|
||||
.byte 9,0,0,0
|
||||
.rva full_handler
|
||||
.rva .Lfe64_sqr_body,.Lfe64_sqr_epilogue # HandlerData[]
|
||||
.long 72,0
|
||||
.LSEH_info_x25519_fe64_mul121666:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_mul121666_body,.Lfe64_mul121666_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_add:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_add_body,.Lfe64_add_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_sub:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_sub_body,.Lfe64_sub_epilogue # HandlerData[]
|
||||
.LSEH_info_x25519_fe64_tobytes:
|
||||
.byte 9,0,0,0
|
||||
.rva short_handler
|
||||
.rva .Lfe64_to_body,.Lfe64_to_epilogue # HandlerData[]
|
||||
___
|
||||
}
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
print $code;
|
||||
close STDOUT;
|
||||
+150
-143
@@ -11,149 +11,23 @@
|
||||
#include "ec_lcl.h"
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#if defined(X25519_ASM) \
|
||||
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
|
||||
&& !defined(__sparc__) \
|
||||
&& !(defined(__ANDROID__) && !defined(__clang__)) )
|
||||
/*
|
||||
* Base 2^51 implementation.
|
||||
*/
|
||||
# define BASE_2_51_IMPLEMENTED
|
||||
#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64))
|
||||
|
||||
typedef uint64_t fe51[5];
|
||||
# if !defined(X25519_ASM)
|
||||
typedef __uint128_t u128;
|
||||
# endif
|
||||
|
||||
static const uint64_t MASK51 = 0x7ffffffffffff;
|
||||
|
||||
static uint64_t load_7(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
result |= ((uint64_t)in[6]) << 48;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t load_6(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void fe51_frombytes(fe51 h, const uint8_t *s)
|
||||
{
|
||||
uint64_t h0 = load_7(s); /* 56 bits */
|
||||
uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */
|
||||
uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */
|
||||
uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */
|
||||
uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */
|
||||
|
||||
h1 |= h0 >> 51; h0 &= MASK51;
|
||||
h2 |= h1 >> 51; h1 &= MASK51;
|
||||
h3 |= h2 >> 51; h2 &= MASK51;
|
||||
h4 |= h3 >> 51; h3 &= MASK51;
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
}
|
||||
|
||||
static void fe51_tobytes(uint8_t *s, const fe51 h)
|
||||
{
|
||||
uint64_t h0 = h[0];
|
||||
uint64_t h1 = h[1];
|
||||
uint64_t h2 = h[2];
|
||||
uint64_t h3 = h[3];
|
||||
uint64_t h4 = h[4];
|
||||
uint64_t q;
|
||||
|
||||
/* compare to modulus */
|
||||
q = (h0 + 19) >> 51;
|
||||
q = (h1 + q) >> 51;
|
||||
q = (h2 + q) >> 51;
|
||||
q = (h3 + q) >> 51;
|
||||
q = (h4 + q) >> 51;
|
||||
|
||||
/* full reduce */
|
||||
h0 += 19 * q;
|
||||
h1 += h0 >> 51; h0 &= MASK51;
|
||||
h2 += h1 >> 51; h1 &= MASK51;
|
||||
h3 += h2 >> 51; h2 &= MASK51;
|
||||
h4 += h3 >> 51; h3 &= MASK51;
|
||||
h4 &= MASK51;
|
||||
|
||||
/* smash */
|
||||
s[0] = (uint8_t)(h0 >> 0);
|
||||
s[1] = (uint8_t)(h0 >> 8);
|
||||
s[2] = (uint8_t)(h0 >> 16);
|
||||
s[3] = (uint8_t)(h0 >> 24);
|
||||
s[4] = (uint8_t)(h0 >> 32);
|
||||
s[5] = (uint8_t)(h0 >> 40);
|
||||
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
|
||||
s[7] = (uint8_t)(h1 >> 5);
|
||||
s[8] = (uint8_t)(h1 >> 13);
|
||||
s[9] = (uint8_t)(h1 >> 21);
|
||||
s[10] = (uint8_t)(h1 >> 29);
|
||||
s[11] = (uint8_t)(h1 >> 37);
|
||||
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
|
||||
s[13] = (uint8_t)(h2 >> 2);
|
||||
s[14] = (uint8_t)(h2 >> 10);
|
||||
s[15] = (uint8_t)(h2 >> 18);
|
||||
s[16] = (uint8_t)(h2 >> 26);
|
||||
s[17] = (uint8_t)(h2 >> 34);
|
||||
s[18] = (uint8_t)(h2 >> 42);
|
||||
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
|
||||
s[20] = (uint8_t)(h3 >> 7);
|
||||
s[21] = (uint8_t)(h3 >> 15);
|
||||
s[22] = (uint8_t)(h3 >> 23);
|
||||
s[23] = (uint8_t)(h3 >> 31);
|
||||
s[24] = (uint8_t)(h3 >> 39);
|
||||
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
|
||||
s[26] = (uint8_t)(h4 >> 4);
|
||||
s[27] = (uint8_t)(h4 >> 12);
|
||||
s[28] = (uint8_t)(h4 >> 20);
|
||||
s[29] = (uint8_t)(h4 >> 28);
|
||||
s[30] = (uint8_t)(h4 >> 36);
|
||||
s[31] = (uint8_t)(h4 >> 44);
|
||||
}
|
||||
|
||||
# ifdef X25519_ASM
|
||||
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
|
||||
void x25519_fe51_sqr(fe51 h, const fe51 f);
|
||||
void x25519_fe51_mul121666(fe51 h, fe51 f);
|
||||
# define fe51_mul x25519_fe51_mul
|
||||
# define fe51_sq x25519_fe51_sqr
|
||||
# define fe51_mul121666 x25519_fe51_mul121666
|
||||
|
||||
# if defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_AMD64) || defined(_M_X64)
|
||||
|
||||
# define BASE_2_64_IMPLEMENTED
|
||||
# define BASE_2_64_IMPLEMENTED
|
||||
|
||||
typedef uint64_t fe64[4];
|
||||
|
||||
int x25519_fe64_eligible(void);
|
||||
|
||||
/*
|
||||
* There are no reference C implementations for this radix.
|
||||
* Following subroutines perform corresponding operations modulo
|
||||
* 2^256-38, i.e. double the curve modulus. However, inputs and
|
||||
* outputs are permitted to be partially reduced, i.e. to remain
|
||||
* in [0..2^256) range. It's all tied up in final fe64_tobytes
|
||||
* that performs full reduction modulo 2^255-19.
|
||||
*
|
||||
* There are no reference C implementations for these.
|
||||
*/
|
||||
void x25519_fe64_mul(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_sqr(fe64 h, const fe64 f);
|
||||
@@ -161,12 +35,12 @@ void x25519_fe64_mul121666(fe64 h, fe64 f);
|
||||
void x25519_fe64_add(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_sub(fe64 h, const fe64 f, const fe64 g);
|
||||
void x25519_fe64_tobytes(uint8_t *s, const fe64 f);
|
||||
# define fe64_mul x25519_fe64_mul
|
||||
# define fe64_sqr x25519_fe64_sqr
|
||||
# define fe64_mul121666 x25519_fe64_mul121666
|
||||
# define fe64_add x25519_fe64_add
|
||||
# define fe64_sub x25519_fe64_sub
|
||||
# define fe64_tobytes x25519_fe64_tobytes
|
||||
# define fe64_mul x25519_fe64_mul
|
||||
# define fe64_sqr x25519_fe64_sqr
|
||||
# define fe64_mul121666 x25519_fe64_mul121666
|
||||
# define fe64_add x25519_fe64_add
|
||||
# define fe64_sub x25519_fe64_sub
|
||||
# define fe64_tobytes x25519_fe64_tobytes
|
||||
|
||||
static uint64_t load_8(const uint8_t *in)
|
||||
{
|
||||
@@ -375,10 +249,143 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
|
||||
|
||||
OPENSSL_cleanse(e, sizeof(e));
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(X25519_ASM) \
|
||||
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
|
||||
&& !defined(__sparc__) \
|
||||
&& !(defined(__ANDROID__) && !defined(__clang__)) )
|
||||
/*
|
||||
* Base 2^51 implementation. It's virtually no different from reference
|
||||
* base 2^25.5 implementation in respect to lax boundary conditions for
|
||||
* intermediate values and even individual limbs. So that whatever you
|
||||
* know about the reference, applies even here...
|
||||
*/
|
||||
# define BASE_2_51_IMPLEMENTED
|
||||
|
||||
typedef uint64_t fe51[5];
|
||||
|
||||
static const uint64_t MASK51 = 0x7ffffffffffff;
|
||||
|
||||
static uint64_t load_7(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
result |= ((uint64_t)in[6]) << 48;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t load_6(const uint8_t *in)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
result = in[0];
|
||||
result |= ((uint64_t)in[1]) << 8;
|
||||
result |= ((uint64_t)in[2]) << 16;
|
||||
result |= ((uint64_t)in[3]) << 24;
|
||||
result |= ((uint64_t)in[4]) << 32;
|
||||
result |= ((uint64_t)in[5]) << 40;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void fe51_frombytes(fe51 h, const uint8_t *s)
|
||||
{
|
||||
uint64_t h0 = load_7(s); /* 56 bits */
|
||||
uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */
|
||||
uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */
|
||||
uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */
|
||||
uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */
|
||||
|
||||
h1 |= h0 >> 51; h0 &= MASK51;
|
||||
h2 |= h1 >> 51; h1 &= MASK51;
|
||||
h3 |= h2 >> 51; h2 &= MASK51;
|
||||
h4 |= h3 >> 51; h3 &= MASK51;
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
}
|
||||
|
||||
static void fe51_tobytes(uint8_t *s, const fe51 h)
|
||||
{
|
||||
uint64_t h0 = h[0];
|
||||
uint64_t h1 = h[1];
|
||||
uint64_t h2 = h[2];
|
||||
uint64_t h3 = h[3];
|
||||
uint64_t h4 = h[4];
|
||||
uint64_t q;
|
||||
|
||||
/* compare to modulus */
|
||||
q = (h0 + 19) >> 51;
|
||||
q = (h1 + q) >> 51;
|
||||
q = (h2 + q) >> 51;
|
||||
q = (h3 + q) >> 51;
|
||||
q = (h4 + q) >> 51;
|
||||
|
||||
/* full reduce */
|
||||
h0 += 19 * q;
|
||||
h1 += h0 >> 51; h0 &= MASK51;
|
||||
h2 += h1 >> 51; h1 &= MASK51;
|
||||
h3 += h2 >> 51; h2 &= MASK51;
|
||||
h4 += h3 >> 51; h3 &= MASK51;
|
||||
h4 &= MASK51;
|
||||
|
||||
/* smash */
|
||||
s[0] = (uint8_t)(h0 >> 0);
|
||||
s[1] = (uint8_t)(h0 >> 8);
|
||||
s[2] = (uint8_t)(h0 >> 16);
|
||||
s[3] = (uint8_t)(h0 >> 24);
|
||||
s[4] = (uint8_t)(h0 >> 32);
|
||||
s[5] = (uint8_t)(h0 >> 40);
|
||||
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
|
||||
s[7] = (uint8_t)(h1 >> 5);
|
||||
s[8] = (uint8_t)(h1 >> 13);
|
||||
s[9] = (uint8_t)(h1 >> 21);
|
||||
s[10] = (uint8_t)(h1 >> 29);
|
||||
s[11] = (uint8_t)(h1 >> 37);
|
||||
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
|
||||
s[13] = (uint8_t)(h2 >> 2);
|
||||
s[14] = (uint8_t)(h2 >> 10);
|
||||
s[15] = (uint8_t)(h2 >> 18);
|
||||
s[16] = (uint8_t)(h2 >> 26);
|
||||
s[17] = (uint8_t)(h2 >> 34);
|
||||
s[18] = (uint8_t)(h2 >> 42);
|
||||
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
|
||||
s[20] = (uint8_t)(h3 >> 7);
|
||||
s[21] = (uint8_t)(h3 >> 15);
|
||||
s[22] = (uint8_t)(h3 >> 23);
|
||||
s[23] = (uint8_t)(h3 >> 31);
|
||||
s[24] = (uint8_t)(h3 >> 39);
|
||||
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
|
||||
s[26] = (uint8_t)(h4 >> 4);
|
||||
s[27] = (uint8_t)(h4 >> 12);
|
||||
s[28] = (uint8_t)(h4 >> 20);
|
||||
s[29] = (uint8_t)(h4 >> 28);
|
||||
s[30] = (uint8_t)(h4 >> 36);
|
||||
s[31] = (uint8_t)(h4 >> 44);
|
||||
}
|
||||
|
||||
# if defined(X25519_ASM)
|
||||
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
|
||||
void x25519_fe51_sqr(fe51 h, const fe51 f);
|
||||
void x25519_fe51_mul121666(fe51 h, fe51 f);
|
||||
# define fe51_mul x25519_fe51_mul
|
||||
# define fe51_sq x25519_fe51_sqr
|
||||
# define fe51_mul121666 x25519_fe51_mul121666
|
||||
# else
|
||||
|
||||
typedef __uint128_t u128;
|
||||
|
||||
static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
|
||||
{
|
||||
u128 h0, h1, h2, h3, h4;
|
||||
|
||||
+271
-57
@@ -15,63 +15,6 @@
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
|
||||
const EC_METHOD *EC_GF2m_simple_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_characteristic_two_field,
|
||||
ec_GF2m_simple_group_init,
|
||||
ec_GF2m_simple_group_finish,
|
||||
ec_GF2m_simple_group_clear_finish,
|
||||
ec_GF2m_simple_group_copy,
|
||||
ec_GF2m_simple_group_set_curve,
|
||||
ec_GF2m_simple_group_get_curve,
|
||||
ec_GF2m_simple_group_get_degree,
|
||||
ec_group_simple_order_bits,
|
||||
ec_GF2m_simple_group_check_discriminant,
|
||||
ec_GF2m_simple_point_init,
|
||||
ec_GF2m_simple_point_finish,
|
||||
ec_GF2m_simple_point_clear_finish,
|
||||
ec_GF2m_simple_point_copy,
|
||||
ec_GF2m_simple_point_set_to_infinity,
|
||||
0 /* set_Jprojective_coordinates_GFp */ ,
|
||||
0 /* get_Jprojective_coordinates_GFp */ ,
|
||||
ec_GF2m_simple_point_set_affine_coordinates,
|
||||
ec_GF2m_simple_point_get_affine_coordinates,
|
||||
0, 0, 0,
|
||||
ec_GF2m_simple_add,
|
||||
ec_GF2m_simple_dbl,
|
||||
ec_GF2m_simple_invert,
|
||||
ec_GF2m_simple_is_at_infinity,
|
||||
ec_GF2m_simple_is_on_curve,
|
||||
ec_GF2m_simple_cmp,
|
||||
ec_GF2m_simple_make_affine,
|
||||
ec_GF2m_simple_points_make_affine,
|
||||
0 /* mul */,
|
||||
0 /* precompute_mul */,
|
||||
0 /* have_precompute_mul */,
|
||||
ec_GF2m_simple_field_mul,
|
||||
ec_GF2m_simple_field_sqr,
|
||||
ec_GF2m_simple_field_div,
|
||||
0 /* field_encode */ ,
|
||||
0 /* field_decode */ ,
|
||||
0, /* field_set_to_one */
|
||||
ec_key_simple_priv2oct,
|
||||
ec_key_simple_oct2priv,
|
||||
0, /* set private */
|
||||
ec_key_simple_generate_key,
|
||||
ec_key_simple_check_key,
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
|
||||
* are handled by EC_GROUP_new.
|
||||
@@ -737,4 +680,275 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
|
||||
return BN_GF2m_mod_div(r, a, b, group->field, ctx);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Lopez-Dahab ladder, pre step.
|
||||
* See e.g. "Guide to ECC" Alg 3.40.
|
||||
* Modified to blind s and r independently.
|
||||
* s:= p, r := 2p
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
/* if p is not affine, something is wrong */
|
||||
if (p->Z_is_one == 0)
|
||||
return 0;
|
||||
|
||||
/* s blinding: make sure lambda (s->Z here) is not zero */
|
||||
do {
|
||||
if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(s->Z));
|
||||
|
||||
/* if field_encode defined convert between representations */
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, s->Z, s->Z, ctx))
|
||||
|| !group->meth->field_mul(group, s->X, p->X, s->Z, ctx))
|
||||
return 0;
|
||||
|
||||
/* r blinding: make sure lambda (r->Y here for storage) is not zero */
|
||||
do {
|
||||
if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(r->Y));
|
||||
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, r->Y, r->Y, ctx))
|
||||
|| !group->meth->field_sqr(group, r->Z, p->X, ctx)
|
||||
|| !group->meth->field_sqr(group, r->X, r->Z, ctx)
|
||||
|| !BN_GF2m_add(r->X, r->X, group->b)
|
||||
|| !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
|
||||
|| !group->meth->field_mul(group, r->X, r->X, r->Y, ctx))
|
||||
return 0;
|
||||
|
||||
s->Z_is_one = 0;
|
||||
r->Z_is_one = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords.
|
||||
* http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3
|
||||
* s := r + s, r := 2r
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_step(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx)
|
||||
|| !group->meth->field_mul(group, s->X, r->X, s->Z, ctx)
|
||||
|| !group->meth->field_sqr(group, s->Y, r->Z, ctx)
|
||||
|| !group->meth->field_sqr(group, r->Z, r->X, ctx)
|
||||
|| !BN_GF2m_add(s->Z, r->Y, s->X)
|
||||
|| !group->meth->field_sqr(group, s->Z, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, s->X, r->Y, s->X, ctx)
|
||||
|| !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx)
|
||||
|| !BN_GF2m_add(s->X, s->X, r->Y)
|
||||
|| !group->meth->field_sqr(group, r->Y, r->Z, ctx)
|
||||
|| !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx)
|
||||
|| !group->meth->field_sqr(group, s->Y, s->Y, ctx)
|
||||
|| !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx)
|
||||
|| !BN_GF2m_add(r->X, r->Y, s->Y))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Recover affine (x,y) result from Lopez-Dahab r and s, affine p.
|
||||
* See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m)
|
||||
* without Precomputation" (Lopez and Dahab, CHES 1999),
|
||||
* Appendix Alg Mxy.
|
||||
*/
|
||||
static
|
||||
int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *t0, *t1, *t2 = NULL;
|
||||
|
||||
if (BN_is_zero(r->Z))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
if (BN_is_zero(s->Z)) {
|
||||
if (!EC_POINT_copy(r, p)
|
||||
|| !EC_POINT_invert(group, r, ctx)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
t0 = BN_CTX_get(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t2 == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, t1, p->X, r->Z, ctx)
|
||||
|| !BN_GF2m_add(t1, r->X, t1)
|
||||
|| !group->meth->field_mul(group, t2, p->X, s->Z, ctx)
|
||||
|| !group->meth->field_mul(group, r->Z, r->X, t2, ctx)
|
||||
|| !BN_GF2m_add(t2, t2, s->X)
|
||||
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|
||||
|| !group->meth->field_sqr(group, t2, p->X, ctx)
|
||||
|| !BN_GF2m_add(t2, p->Y, t2)
|
||||
|| !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_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)
|
||||
|| !group->meth->field_mul(group, t2, t2, t1, ctx)
|
||||
|| !BN_GF2m_add(r->Y, p->Y, t2)
|
||||
|| !BN_one(r->Z))
|
||||
goto err;
|
||||
|
||||
r->Z_is_one = 1;
|
||||
|
||||
/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
|
||||
BN_set_negative(r->X, 0);
|
||||
BN_set_negative(r->Y, 0);
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, size_t num,
|
||||
const EC_POINT *points[],
|
||||
const BIGNUM *scalars[],
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
EC_POINT *t = NULL;
|
||||
|
||||
/*-
|
||||
* We limit use of the ladder only to the following cases:
|
||||
* - r := scalar * G
|
||||
* Fixed point mul: scalar != NULL && num == 0;
|
||||
* - r := scalars[0] * points[0]
|
||||
* Variable point mul: scalar == NULL && num == 1;
|
||||
* - r := scalar * G + scalars[0] * points[0]
|
||||
* used, e.g., in ECDSA verification: scalar != NULL && num == 1
|
||||
*
|
||||
* In any other case (num > 1) we use the default wNAF implementation.
|
||||
*
|
||||
* We also let the default implementation handle degenerate cases like group
|
||||
* order or cofactor set to 0.
|
||||
*/
|
||||
if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
|
||||
return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
|
||||
if (scalar != NULL && num == 0)
|
||||
/* Fixed point multiplication */
|
||||
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
|
||||
|
||||
if (scalar == NULL && num == 1)
|
||||
/* Variable point multiplication */
|
||||
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
|
||||
|
||||
/*-
|
||||
* Double point multiplication:
|
||||
* r := scalar * G + scalars[0] * points[0]
|
||||
*/
|
||||
|
||||
if ((t = EC_POINT_new(group)) == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
|
||||
|| !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
|
||||
|| !EC_POINT_add(group, r, t, r, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EC_POINT_free(t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const EC_METHOD *EC_GF2m_simple_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_characteristic_two_field,
|
||||
ec_GF2m_simple_group_init,
|
||||
ec_GF2m_simple_group_finish,
|
||||
ec_GF2m_simple_group_clear_finish,
|
||||
ec_GF2m_simple_group_copy,
|
||||
ec_GF2m_simple_group_set_curve,
|
||||
ec_GF2m_simple_group_get_curve,
|
||||
ec_GF2m_simple_group_get_degree,
|
||||
ec_group_simple_order_bits,
|
||||
ec_GF2m_simple_group_check_discriminant,
|
||||
ec_GF2m_simple_point_init,
|
||||
ec_GF2m_simple_point_finish,
|
||||
ec_GF2m_simple_point_clear_finish,
|
||||
ec_GF2m_simple_point_copy,
|
||||
ec_GF2m_simple_point_set_to_infinity,
|
||||
0, /* set_Jprojective_coordinates_GFp */
|
||||
0, /* get_Jprojective_coordinates_GFp */
|
||||
ec_GF2m_simple_point_set_affine_coordinates,
|
||||
ec_GF2m_simple_point_get_affine_coordinates,
|
||||
0, /* point_set_compressed_coordinates */
|
||||
0, /* point2oct */
|
||||
0, /* oct2point */
|
||||
ec_GF2m_simple_add,
|
||||
ec_GF2m_simple_dbl,
|
||||
ec_GF2m_simple_invert,
|
||||
ec_GF2m_simple_is_at_infinity,
|
||||
ec_GF2m_simple_is_on_curve,
|
||||
ec_GF2m_simple_cmp,
|
||||
ec_GF2m_simple_make_affine,
|
||||
ec_GF2m_simple_points_make_affine,
|
||||
ec_GF2m_simple_points_mul,
|
||||
0, /* precompute_mult */
|
||||
0, /* have_precompute_mult */
|
||||
ec_GF2m_simple_field_mul,
|
||||
ec_GF2m_simple_field_sqr,
|
||||
ec_GF2m_simple_field_div,
|
||||
0, /* field_encode */
|
||||
0, /* field_decode */
|
||||
0, /* field_set_to_one */
|
||||
ec_key_simple_priv2oct,
|
||||
ec_key_simple_oct2priv,
|
||||
0, /* set private */
|
||||
ec_key_simple_generate_key,
|
||||
ec_key_simple_check_key,
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0, /* blind_coordinates */
|
||||
ec_GF2m_simple_ladder_pre,
|
||||
ec_GF2m_simple_ladder_step,
|
||||
ec_GF2m_simple_ladder_post
|
||||
};
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
+15
-6
@@ -70,10 +70,16 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
"ec_GF2m_simple_group_check_discriminant"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, 0),
|
||||
"ec_GF2m_simple_group_set_curve"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_POST, 0),
|
||||
"ec_GF2m_simple_ladder_post"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_LADDER_PRE, 0),
|
||||
"ec_GF2m_simple_ladder_pre"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_OCT2POINT, 0),
|
||||
"ec_GF2m_simple_oct2point"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT2OCT, 0),
|
||||
"ec_GF2m_simple_point2oct"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINTS_MUL, 0),
|
||||
"ec_GF2m_simple_points_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 0),
|
||||
"ec_GF2m_simple_point_get_affine_coordinates"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 0),
|
||||
@@ -191,6 +197,7 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0),
|
||||
"EC_POINTs_make_affine"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MUL, 0), "EC_POINTs_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_BN2POINT, 0), "EC_POINT_bn2point"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_CMP, 0), "EC_POINT_cmp"},
|
||||
@@ -226,6 +233,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_SET_TO_INFINITY, 0),
|
||||
"EC_POINT_set_to_infinity"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_PRE_COMP_NEW, 0), "ec_pre_comp_new"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_SCALAR_MUL_LADDER, 0),
|
||||
"ec_scalar_mul_ladder"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_MUL, 0), "ec_wNAF_mul"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_EC_WNAF_PRECOMPUTE_MULT, 0),
|
||||
"ec_wNAF_precompute_mult"},
|
||||
@@ -261,12 +270,6 @@ static const ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_KEYGEN, 0), "pkey_ec_keygen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_PARAMGEN, 0), "pkey_ec_paramgen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_SIGN, 0), "pkey_ec_sign"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_KEYGEN, 0), "pkey_sm2_keygen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_PARAMGEN, 0), "pkey_sm2_paramgen"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"},
|
||||
{ERR_PACK(ERR_LIB_EC, EC_F_VALIDATE_ECX_DERIVE, 0), "validate_ecx_derive"},
|
||||
{0, NULL}
|
||||
};
|
||||
@@ -320,6 +323,9 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
"invalid trinomial basis"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_KEYS_NOT_SET), "keys not set"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_POST_FAILURE), "ladder post failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_PRE_FAILURE), "ladder pre failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_LADDER_STEP_FAILURE), "ladder step failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PARAMETERS), "missing parameters"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_MISSING_PRIVATE_KEY), "missing private key"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_NEED_NEW_SETUP_VALUES),
|
||||
@@ -339,6 +345,8 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_ARITHMETIC_FAILURE),
|
||||
"point arithmetic failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_AT_INFINITY), "point at infinity"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_COORDINATES_BLIND_FAILURE),
|
||||
"point coordinates blind failure"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_POINT_IS_NOT_ON_CURVE),
|
||||
"point is not on curve"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_RANDOM_NUMBER_GENERATION_FAILED),
|
||||
@@ -347,6 +355,7 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_SLOT_FULL), "slot full"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_GENERATOR), "undefined generator"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNDEFINED_ORDER), "undefined order"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_GROUP), "unknown group"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNKNOWN_ORDER), "unknown order"},
|
||||
{ERR_PACK(ERR_LIB_EC, 0, EC_R_UNSUPPORTED_FIELD), "unsupported field"},
|
||||
|
||||
@@ -178,6 +178,15 @@ struct ec_method_st {
|
||||
int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r,
|
||||
const BIGNUM *x, BN_CTX *);
|
||||
int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_pre)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_step)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
int (*ladder_post)(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -637,4 +646,76 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
|
||||
void X25519_public_from_private(uint8_t out_public_value[32],
|
||||
const uint8_t private_key[32]);
|
||||
|
||||
/*-
|
||||
* This functions computes a single point multiplication over the EC group,
|
||||
* using, at a high level, a Montgomery ladder with conditional swaps, with
|
||||
* various timing attack defenses.
|
||||
*
|
||||
* It performs either a fixed point multiplication
|
||||
* (scalar * generator)
|
||||
* when point is NULL, or a variable point multiplication
|
||||
* (scalar * point)
|
||||
* when point is not NULL.
|
||||
*
|
||||
* `scalar` cannot be NULL and should be in the range [0,n) otherwise all
|
||||
* constant time bets are off (where n is the cardinality of the EC group).
|
||||
*
|
||||
* This function expects `group->order` and `group->cardinality` to be well
|
||||
* defined and non-zero: it fails with an error code otherwise.
|
||||
*
|
||||
* NB: This says nothing about the constant-timeness of the ladder step
|
||||
* implementation (i.e., the default implementation is based on EC_POINT_add and
|
||||
* EC_POINT_dbl, which of course are not constant time themselves) or the
|
||||
* underlying multiprecision arithmetic.
|
||||
*
|
||||
* The product is stored in `r`.
|
||||
*
|
||||
* This is an internal function: callers are in charge of ensuring that the
|
||||
* input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
|
||||
*
|
||||
* Returns 1 on success, 0 otherwise.
|
||||
*/
|
||||
int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx);
|
||||
|
||||
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
|
||||
|
||||
static inline int ec_point_ladder_pre(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_pre != NULL)
|
||||
return group->meth->ladder_pre(group, r, s, p, ctx);
|
||||
|
||||
if (!EC_POINT_copy(s, p)
|
||||
|| !EC_POINT_dbl(group, r, s, ctx))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int ec_point_ladder_step(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_step != NULL)
|
||||
return group->meth->ladder_step(group, r, s, p, ctx);
|
||||
|
||||
if (!EC_POINT_add(group, s, r, s, ctx)
|
||||
|| !EC_POINT_dbl(group, r, r, ctx))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static inline int ec_point_ladder_post(const EC_GROUP *group,
|
||||
EC_POINT *r, EC_POINT *s,
|
||||
EC_POINT *p, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->ladder_post != NULL)
|
||||
return group->meth->ladder_post(group, r, s, p, ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
+31
-4
@@ -919,11 +919,38 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
size_t num, const EC_POINT *points[],
|
||||
const BIGNUM *scalars[], BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->mul == 0)
|
||||
/* use default */
|
||||
return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
int ret = 0;
|
||||
size_t i = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
|
||||
return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
||||
if ((scalar == NULL) && (num == 0)) {
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!ec_point_is_compat(points[i], group)) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {
|
||||
ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (group->meth->mul != NULL)
|
||||
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
||||
else
|
||||
/* use default */
|
||||
ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
|
||||
|
||||
+114
-81
@@ -108,10 +108,9 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
|
||||
} while(0)
|
||||
|
||||
/*-
|
||||
* This functions computes (in constant time) a point multiplication over the
|
||||
* EC group.
|
||||
*
|
||||
* At a high level, it is Montgomery ladder with conditional swaps.
|
||||
* This functions computes a single point multiplication over the EC group,
|
||||
* using, at a high level, a Montgomery ladder with conditional swaps, with
|
||||
* various timing attack defenses.
|
||||
*
|
||||
* It performs either a fixed point multiplication
|
||||
* (scalar * generator)
|
||||
@@ -119,51 +118,85 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
|
||||
* (scalar * point)
|
||||
* when point is not NULL.
|
||||
*
|
||||
* scalar should be in the range [0,n) otherwise all constant time bets are off.
|
||||
* `scalar` cannot be NULL and should be in the range [0,n) otherwise all
|
||||
* constant time bets are off (where n is the cardinality of the EC group).
|
||||
*
|
||||
* NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
|
||||
* which of course are not constant time themselves.
|
||||
* This function expects `group->order` and `group->cardinality` to be well
|
||||
* defined and non-zero: it fails with an error code otherwise.
|
||||
*
|
||||
* The product is stored in r.
|
||||
* NB: This says nothing about the constant-timeness of the ladder step
|
||||
* implementation (i.e., the default implementation is based on EC_POINT_add and
|
||||
* EC_POINT_dbl, which of course are not constant time themselves) or the
|
||||
* underlying multiprecision arithmetic.
|
||||
*
|
||||
* The product is stored in `r`.
|
||||
*
|
||||
* This is an internal function: callers are in charge of ensuring that the
|
||||
* input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
|
||||
*
|
||||
* Returns 1 on success, 0 otherwise.
|
||||
*/
|
||||
static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
|
||||
EC_POINT *p = NULL;
|
||||
EC_POINT *s = NULL;
|
||||
BIGNUM *k = NULL;
|
||||
BIGNUM *lambda = NULL;
|
||||
BIGNUM *cardinality = NULL;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
|
||||
/* early exit if the input point is the point at infinity */
|
||||
if (point != NULL && EC_POINT_is_at_infinity(group, point))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
if (BN_is_zero(group->order)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER);
|
||||
return 0;
|
||||
}
|
||||
if (BN_is_zero(group->cofactor)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
s = EC_POINT_new(group);
|
||||
if (s == NULL)
|
||||
if (((p = EC_POINT_new(group)) == NULL)
|
||||
|| ((s = EC_POINT_new(group)) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
|
||||
if (point == NULL) {
|
||||
if (!EC_POINT_copy(s, group->generator))
|
||||
goto err;
|
||||
} else {
|
||||
if (!EC_POINT_copy(s, point))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (point == NULL) {
|
||||
if (!EC_POINT_copy(p, group->generator)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!EC_POINT_copy(p, point)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME);
|
||||
EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
|
||||
EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
|
||||
|
||||
cardinality = BN_CTX_get(ctx);
|
||||
lambda = BN_CTX_get(ctx);
|
||||
k = BN_CTX_get(ctx);
|
||||
if (k == NULL || !BN_mul(cardinality, group->order, group->cofactor, ctx))
|
||||
if (k == NULL) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Group cardinalities are often on a word boundary.
|
||||
@@ -174,11 +207,15 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
cardinality_bits = BN_num_bits(cardinality);
|
||||
group_top = bn_get_top(cardinality);
|
||||
if ((bn_wexpand(k, group_top + 1) == NULL)
|
||||
|| (bn_wexpand(lambda, group_top + 1) == NULL))
|
||||
|| (bn_wexpand(lambda, group_top + 1) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_copy(k, scalar))
|
||||
if (!BN_copy(k, scalar)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_set_flags(k, BN_FLG_CONSTTIME);
|
||||
|
||||
@@ -187,15 +224,21 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
* this is an unusual input, and we don't guarantee
|
||||
* constant-timeness
|
||||
*/
|
||||
if (!BN_nnmod(k, k, cardinality, ctx))
|
||||
if (!BN_nnmod(k, k, cardinality, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BN_add(lambda, k, cardinality))
|
||||
if (!BN_add(lambda, k, cardinality)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
BN_set_flags(lambda, BN_FLG_CONSTTIME);
|
||||
if (!BN_add(k, lambda, cardinality))
|
||||
if (!BN_add(k, lambda, cardinality)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* lambda := scalar + cardinality
|
||||
* k := scalar + 2*cardinality
|
||||
@@ -209,8 +252,13 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
|| (bn_wexpand(s->Z, group_top) == NULL)
|
||||
|| (bn_wexpand(r->X, group_top) == NULL)
|
||||
|| (bn_wexpand(r->Y, group_top) == NULL)
|
||||
|| (bn_wexpand(r->Z, group_top) == NULL))
|
||||
|| (bn_wexpand(r->Z, group_top) == NULL)
|
||||
|| (bn_wexpand(p->X, group_top) == NULL)
|
||||
|| (bn_wexpand(p->Y, group_top) == NULL)
|
||||
|| (bn_wexpand(p->Z, group_top) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Apply coordinate blinding for EC_POINT.
|
||||
@@ -220,19 +268,19 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
* success or if coordinate blinding is not implemented for this
|
||||
* group.
|
||||
*/
|
||||
if (!ec_point_blind_coordinates(group, s, ctx))
|
||||
if (!ec_point_blind_coordinates(group, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Initialize the Montgomery ladder */
|
||||
if (!ec_point_ladder_pre(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* top bit is a 1, in a fixed pos */
|
||||
if (!EC_POINT_copy(r, s))
|
||||
goto err;
|
||||
|
||||
EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!EC_POINT_dbl(group, s, s, ctx))
|
||||
goto err;
|
||||
|
||||
pbit = 0;
|
||||
pbit = 1;
|
||||
|
||||
#define EC_POINT_CSWAP(c, a, b, w, t) do { \
|
||||
BN_consttime_swap(c, (a)->X, (b)->X, w); \
|
||||
@@ -304,10 +352,12 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
for (i = cardinality_bits - 1; i >= 0; i--) {
|
||||
kbit = BN_is_bit_set(k, i) ^ pbit;
|
||||
EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
|
||||
if (!EC_POINT_add(group, s, r, s, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_dbl(group, r, r, ctx))
|
||||
|
||||
/* Perform a single step of the Montgomery ladder */
|
||||
if (!ec_point_ladder_step(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* pbit logic merges this cswap with that of the
|
||||
* next iteration
|
||||
@@ -318,12 +368,18 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|
||||
EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
|
||||
#undef EC_POINT_CSWAP
|
||||
|
||||
/* Finalize ladder (and recover full point coordinates) */
|
||||
if (!ec_point_ladder_post(group, r, s, p, ctx)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EC_POINT_free(p);
|
||||
EC_POINT_free(s);
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(new_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -355,7 +411,6 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
const EC_POINT *generator = NULL;
|
||||
EC_POINT *tmp = NULL;
|
||||
size_t totalnum;
|
||||
@@ -380,56 +435,35 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
* precomputation is not available */
|
||||
int ret = 0;
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((scalar == NULL) && (num == 0)) {
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {
|
||||
/*-
|
||||
* Handle the common cases where the scalar is secret, enforcing a constant
|
||||
* time scalar multiplication algorithm.
|
||||
* Handle the common cases where the scalar is secret, enforcing a
|
||||
* scalar multiplication implementation based on a Montgomery ladder,
|
||||
* with various timing attack defenses.
|
||||
*/
|
||||
if ((scalar != NULL) && (num == 0)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * GeneratorPoint: this
|
||||
* codepath is reached most prominently by (ephemeral) key generation
|
||||
* of EC cryptosystems (i.e. ECDSA keygen and sign setup, ECDH
|
||||
* keygen/first half), where the scalar is always secret. This is why
|
||||
* we ignore if BN_FLG_CONSTTIME is actually set and we always call the
|
||||
* constant time version.
|
||||
* codepath is reached most prominently by (ephemeral) key
|
||||
* generation of EC cryptosystems (i.e. ECDSA keygen and sign setup,
|
||||
* ECDH keygen/first half), where the scalar is always secret. This
|
||||
* is why we ignore if BN_FLG_CONSTTIME is actually set and we
|
||||
* always call the ladder version.
|
||||
*/
|
||||
return ec_mul_consttime(group, r, scalar, NULL, ctx);
|
||||
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
|
||||
}
|
||||
if ((scalar == NULL) && (num == 1)) {
|
||||
/*-
|
||||
* In this case we want to compute scalar * GenericPoint: this codepath
|
||||
* is reached most prominently by the second half of ECDH, where the
|
||||
* secret scalar is multiplied by the peer's public point. To protect
|
||||
* the secret scalar, we ignore if BN_FLG_CONSTTIME is actually set and
|
||||
* we always call the constant time version.
|
||||
* In this case we want to compute scalar * VariablePoint: this
|
||||
* codepath is reached most prominently by the second half of ECDH,
|
||||
* where the secret scalar is multiplied by the peer's public point.
|
||||
* To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is
|
||||
* actually set and we always call the ladder version.
|
||||
*/
|
||||
return ec_mul_consttime(group, r, scalars[0], points[0], ctx);
|
||||
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!ec_point_is_compat(points[i], group)) {
|
||||
ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (scalar != NULL) {
|
||||
generator = EC_GROUP_get0_generator(group);
|
||||
if (generator == NULL) {
|
||||
@@ -736,7 +770,6 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_free(new_ctx);
|
||||
EC_POINT_free(tmp);
|
||||
OPENSSL_free(wsize);
|
||||
OPENSSL_free(wNAF_len);
|
||||
|
||||
+37
-94
@@ -10,9 +10,8 @@
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/ec.h>
|
||||
#include "internal/bn_int.h"
|
||||
#include "ec_lcl.h"
|
||||
|
||||
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
|
||||
@@ -53,13 +52,12 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx_in == NULL) {
|
||||
if ((ctx = ctx_in) == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
ctx = ctx_in;
|
||||
}
|
||||
|
||||
k = BN_new(); /* this value is later returned in *kinvp */
|
||||
r = BN_new(); /* this value is later returned in *rp */
|
||||
@@ -73,10 +71,6 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
goto err;
|
||||
}
|
||||
order = EC_GROUP_get0_order(group);
|
||||
if (order == NULL) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Preallocate space */
|
||||
order_bits = BN_num_bits(order);
|
||||
@@ -87,23 +81,23 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
|
||||
do {
|
||||
/* get random k */
|
||||
do
|
||||
do {
|
||||
if (dgst != NULL) {
|
||||
if (!BN_generate_dsa_nonce
|
||||
(k, order, EC_KEY_get0_private_key(eckey), dgst, dlen,
|
||||
ctx)) {
|
||||
if (!BN_generate_dsa_nonce(k, order,
|
||||
EC_KEY_get0_private_key(eckey),
|
||||
dgst, dlen, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP,
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!BN_priv_rand_range(k, order)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP,
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (BN_is_zero(k));
|
||||
} while (BN_is_zero(k));
|
||||
|
||||
/* compute r the x-coordinate of generator * k */
|
||||
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
|
||||
@@ -112,18 +106,16 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
}
|
||||
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
|
||||
NID_X9_62_prime_field) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp
|
||||
(group, tmp_point, X, NULL, ctx)) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, X,
|
||||
NULL, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
else { /* NID_X9_62_characteristic_two_field */
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group,
|
||||
tmp_point, X, NULL,
|
||||
ctx)) {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X,
|
||||
NULL, ctx)) {
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -133,8 +125,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
|
||||
ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (BN_is_zero(r));
|
||||
} while (BN_is_zero(r));
|
||||
|
||||
/* compute the inverse of k */
|
||||
if (!ec_group_do_inverse_ord(group, k, k, ctx)) {
|
||||
@@ -172,8 +163,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
EC_KEY *eckey)
|
||||
{
|
||||
int ok = 0, i;
|
||||
BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *blind = NULL;
|
||||
BIGNUM *blindm = NULL;
|
||||
BIGNUM *kinv = NULL, *s, *m = NULL;
|
||||
const BIGNUM *order, *ckinv;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_GROUP *group;
|
||||
@@ -206,27 +196,13 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
}
|
||||
s = ret->s;
|
||||
|
||||
ctx = BN_CTX_secure_new();
|
||||
if (ctx == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
m = BN_CTX_get(ctx);
|
||||
blind = BN_CTX_get(ctx);
|
||||
blindm = BN_CTX_get(ctx);
|
||||
if (blindm == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL
|
||||
|| (m = BN_new()) == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
order = EC_GROUP_get0_order(group);
|
||||
if (order == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
i = BN_num_bits(order);
|
||||
/*
|
||||
* Need to truncate digest if it is too long: first truncate whole bytes.
|
||||
@@ -237,7 +213,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
/* If still too long truncate remaining bits with a shift */
|
||||
/* If still too long, truncate remaining bits with a shift */
|
||||
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
@@ -258,59 +234,27 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
}
|
||||
|
||||
/*
|
||||
* The normal signature calculation is:
|
||||
*
|
||||
* s := k^-1 * (m + r * priv_key) mod order
|
||||
*
|
||||
* We will blind this to protect against side channel attacks
|
||||
*
|
||||
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod order
|
||||
* With only one multiplicant being in Montgomery domain
|
||||
* multiplication yields real result without post-conversion.
|
||||
* Also note that all operations but last are performed with
|
||||
* zero-padded vectors. Last operation, BN_mod_mul_montgomery
|
||||
* below, returns user-visible value with removed zero padding.
|
||||
*/
|
||||
|
||||
/* Generate a blinding value */
|
||||
do {
|
||||
if (!BN_priv_rand(blind, BN_num_bits(order) - 1,
|
||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
|
||||
goto err;
|
||||
} while (BN_is_zero(blind));
|
||||
BN_set_flags(blind, BN_FLG_CONSTTIME);
|
||||
BN_set_flags(blindm, BN_FLG_CONSTTIME);
|
||||
BN_set_flags(tmp, BN_FLG_CONSTTIME);
|
||||
|
||||
/* tmp := blind * priv_key * r mod order */
|
||||
if (!BN_mod_mul(tmp, blind, priv_key, order, ctx)) {
|
||||
if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
|
||||
|| !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(tmp, tmp, ret->r, order, ctx)) {
|
||||
if (!bn_mod_add_fixed_top(s, s, m, order)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* blindm := blind * m mod order */
|
||||
if (!BN_mod_mul(blindm, blind, m, order, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s : = (blind * priv_key * r) + (blind * m) mod order */
|
||||
if (!BN_mod_add_quick(s, tmp, blindm, order)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s := s * k^-1 mod order */
|
||||
if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* s:= s * blind^-1 mod order */
|
||||
if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(s, s, blind, order, ctx)) {
|
||||
/*
|
||||
* |s| can still be larger than modulus, because |m| can be. In
|
||||
* such case we count on Montgomery reduction to tie it up.
|
||||
*/
|
||||
if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
|
||||
|| !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -324,11 +268,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES);
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/* s != 0 => we have a valid signature */
|
||||
break;
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
@@ -336,9 +280,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||
ECDSA_SIG_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
BN_clear_free(m);
|
||||
BN_clear_free(kinv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,10 @@ const EC_METHOD *EC_GFp_mont_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -65,7 +65,10 @@ const EC_METHOD *EC_GFp_nist_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -292,7 +292,10 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1393,7 +1396,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int j;
|
||||
unsigned i;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -1410,9 +1412,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -1575,7 +1574,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_felems);
|
||||
|
||||
@@ -1821,7 +1821,12 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
|
||||
ec_key_simple_generate_public_key,
|
||||
0, /* keycopy */
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -2013,7 +2018,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int ret = 0;
|
||||
int j;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -2031,9 +2035,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -2202,7 +2203,6 @@ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_smallfelems);
|
||||
|
||||
@@ -1660,7 +1660,10 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1852,7 +1855,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
int ret = 0;
|
||||
int j;
|
||||
int mixed = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *z, *tmp_scalar;
|
||||
felem_bytearray g_secret;
|
||||
felem_bytearray *secrets = NULL;
|
||||
@@ -1869,9 +1871,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const EC_POINT *p = NULL;
|
||||
const BIGNUM *p_scalar = NULL;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
@@ -2038,7 +2037,6 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
EC_POINT_free(generator);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(secrets);
|
||||
OPENSSL_free(pre_comp);
|
||||
OPENSSL_free(tmp_felems);
|
||||
|
||||
@@ -1139,12 +1139,10 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
const BIGNUM *scalars[], BN_CTX *ctx)
|
||||
{
|
||||
int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0;
|
||||
size_t j;
|
||||
unsigned char p_str[33] = { 0 };
|
||||
const PRECOMP256_ROW *preComputedTable = NULL;
|
||||
const NISTZ256_PRE_COMP *pre_comp = NULL;
|
||||
const EC_POINT *generator = NULL;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
const BIGNUM **new_scalars = NULL;
|
||||
const EC_POINT **new_points = NULL;
|
||||
unsigned int idx = 0;
|
||||
@@ -1162,27 +1160,6 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ec_point_is_compat(r, group)) {
|
||||
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((scalar == NULL) && (num == 0))
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
|
||||
for (j = 0; j < num; j++) {
|
||||
if (!ec_point_is_compat(points[j], group)) {
|
||||
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
if (scalar) {
|
||||
@@ -1380,7 +1357,6 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(new_ctx);
|
||||
OPENSSL_free(new_points);
|
||||
OPENSSL_free(new_scalars);
|
||||
return ret;
|
||||
@@ -1731,7 +1707,10 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
|
||||
0 /* blind_coordinates */
|
||||
0, /* blind_coordinates */
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
|
||||
@@ -64,7 +64,10 @@ const EC_METHOD *EC_GFp_simple_method(void)
|
||||
0, /* keyfinish */
|
||||
ecdh_simple_compute_key,
|
||||
0, /* field_inverse_mod_ord */
|
||||
ec_GFp_simple_blind_coordinates
|
||||
ec_GFp_simple_blind_coordinates,
|
||||
0, /* ladder_pre */
|
||||
0, /* ladder_step */
|
||||
0 /* ladder_post */
|
||||
};
|
||||
|
||||
return &ret;
|
||||
@@ -1418,4 +1421,3 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -361,20 +361,20 @@ static const struct digest_data_st {
|
||||
#endif
|
||||
{ NID_sha1, 20, CRYPTO_SHA1 },
|
||||
#ifndef OPENSSL_NO_RMD160
|
||||
# if !defined(CHECK_BSD_STYLE_MACROS) && defined(CRYPTO_RIPEMD160)
|
||||
# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
|
||||
{ NID_ripemd160, 20, CRYPTO_RIPEMD160 },
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) && defined(CRYPTO_SHA2_224)
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
|
||||
{ NID_sha224, 224 / 8, CRYPTO_SHA2_224 },
|
||||
#endif
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) && defined(CRYPTO_SHA2_256)
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
|
||||
{ NID_sha256, 256 / 8, CRYPTO_SHA2_256 },
|
||||
#endif
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) && defined(CRYPTO_SHA2_384)
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
|
||||
{ NID_sha384, 384 / 8, CRYPTO_SHA2_384 },
|
||||
#endif
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) && defined(CRYPTO_SHA2_512)
|
||||
#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
|
||||
{ NID_sha512, 512 / 8, CRYPTO_SHA2_512 },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -521,8 +521,11 @@ EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY:208:ec_GF2m_montgomery_point_multiply
|
||||
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
|
||||
EC_F_EC_GF2M_SIMPLE_LADDER_POST:285:ec_GF2m_simple_ladder_post
|
||||
EC_F_EC_GF2M_SIMPLE_LADDER_PRE:288:ec_GF2m_simple_ladder_pre
|
||||
EC_F_EC_GF2M_SIMPLE_OCT2POINT:160:ec_GF2m_simple_oct2point
|
||||
EC_F_EC_GF2M_SIMPLE_POINT2OCT:161:ec_GF2m_simple_point2oct
|
||||
EC_F_EC_GF2M_SIMPLE_POINTS_MUL:289:ec_GF2m_simple_points_mul
|
||||
EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES:162:\
|
||||
ec_GF2m_simple_point_get_affine_coordinates
|
||||
EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES:163:\
|
||||
@@ -601,6 +604,7 @@ EC_F_EC_KEY_SIMPLE_PRIV2OCT:260:ec_key_simple_priv2oct
|
||||
EC_F_EC_PKEY_CHECK:273:ec_pkey_check
|
||||
EC_F_EC_PKEY_PARAM_CHECK:274:ec_pkey_param_check
|
||||
EC_F_EC_POINTS_MAKE_AFFINE:136:EC_POINTs_make_affine
|
||||
EC_F_EC_POINTS_MUL:290:EC_POINTs_mul
|
||||
EC_F_EC_POINT_ADD:112:EC_POINT_add
|
||||
EC_F_EC_POINT_BN2POINT:280:EC_POINT_bn2point
|
||||
EC_F_EC_POINT_CMP:113:EC_POINT_cmp
|
||||
@@ -630,6 +634,7 @@ EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP:126:\
|
||||
EC_POINT_set_Jprojective_coordinates_GFp
|
||||
EC_F_EC_POINT_SET_TO_INFINITY:127:EC_POINT_set_to_infinity
|
||||
EC_F_EC_PRE_COMP_NEW:196:ec_pre_comp_new
|
||||
EC_F_EC_SCALAR_MUL_LADDER:284:ec_scalar_mul_ladder
|
||||
EC_F_EC_WNAF_MUL:187:ec_wNAF_mul
|
||||
EC_F_EC_WNAF_PRECOMPUTE_MULT:188:ec_wNAF_precompute_mult
|
||||
EC_F_I2D_ECPARAMETERS:190:i2d_ECParameters
|
||||
@@ -2012,6 +2017,7 @@ CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE:106:no conf or environment variable
|
||||
CONF_R_NO_SECTION:107:no section
|
||||
CONF_R_NO_SUCH_FILE:114:no such file
|
||||
CONF_R_NO_VALUE:108:no value
|
||||
CONF_R_NUMBER_TOO_LARGE:121:number too large
|
||||
CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include
|
||||
CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty
|
||||
CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found
|
||||
@@ -2129,6 +2135,9 @@ EC_R_INVALID_PRIVATE_KEY:123:invalid private key
|
||||
EC_R_INVALID_TRINOMIAL_BASIS:137:invalid trinomial basis
|
||||
EC_R_KDF_PARAMETER_ERROR:148:kdf parameter error
|
||||
EC_R_KEYS_NOT_SET:140:keys not set
|
||||
EC_R_LADDER_POST_FAILURE:136:ladder post failure
|
||||
EC_R_LADDER_PRE_FAILURE:153:ladder pre failure
|
||||
EC_R_LADDER_STEP_FAILURE:162:ladder step failure
|
||||
EC_R_MISSING_PARAMETERS:124:missing parameters
|
||||
EC_R_MISSING_PRIVATE_KEY:125:missing private key
|
||||
EC_R_NEED_NEW_SETUP_VALUES:157:need new setup values
|
||||
@@ -2143,12 +2152,14 @@ EC_R_PEER_KEY_ERROR:149:peer key error
|
||||
EC_R_PKPARAMETERS2GROUP_FAILURE:127:pkparameters2group failure
|
||||
EC_R_POINT_ARITHMETIC_FAILURE:155:point arithmetic failure
|
||||
EC_R_POINT_AT_INFINITY:106:point at infinity
|
||||
EC_R_POINT_COORDINATES_BLIND_FAILURE:163:point coordinates blind failure
|
||||
EC_R_POINT_IS_NOT_ON_CURVE:107:point is not on curve
|
||||
EC_R_RANDOM_NUMBER_GENERATION_FAILED:158:random number generation failed
|
||||
EC_R_SHARED_INFO_ERROR:150:shared info error
|
||||
EC_R_SLOT_FULL:108:slot full
|
||||
EC_R_UNDEFINED_GENERATOR:113:undefined generator
|
||||
EC_R_UNDEFINED_ORDER:128:undefined order
|
||||
EC_R_UNKNOWN_COFACTOR:164:unknown cofactor
|
||||
EC_R_UNKNOWN_GROUP:129:unknown group
|
||||
EC_R_UNKNOWN_ORDER:114:unknown order
|
||||
EC_R_UNSUPPORTED_FIELD:131:unsupported field
|
||||
|
||||
+21
-19
@@ -144,6 +144,22 @@ void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len,
|
||||
const unsigned char iv[16]);
|
||||
#endif
|
||||
|
||||
/* increment counter (64-bit int) by 1 */
|
||||
static void ctr64_inc(unsigned char *counter)
|
||||
{
|
||||
int n = 8;
|
||||
unsigned char c;
|
||||
|
||||
do {
|
||||
--n;
|
||||
c = counter[n];
|
||||
++c;
|
||||
counter[n] = c;
|
||||
if (c)
|
||||
return;
|
||||
} while (n);
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
|
||||
# include "ppc_arch.h"
|
||||
# ifdef VPAES_ASM
|
||||
@@ -1654,7 +1670,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||
* Invocation field will be at least 8 bytes in size and so no need
|
||||
* to check wrap around or increment more than last 8 bytes.
|
||||
*/
|
||||
(*(unsigned long long *)(gctx->iv + gctx->ivlen - 8))++;
|
||||
ctr64_inc(gctx->iv + gctx->ivlen - 8);
|
||||
gctx->iv_set = 1;
|
||||
return 1;
|
||||
|
||||
@@ -2291,7 +2307,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||
memcpy(buf, ptr, arg);
|
||||
cctx->aes.ccm.tls_aad_len = arg;
|
||||
|
||||
len = *(uint16_t *)(buf + arg - 2);
|
||||
len = buf[arg - 2] << 8 | buf[arg - 1];
|
||||
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
|
||||
return 0;
|
||||
|
||||
@@ -2307,7 +2323,9 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||
len -= cctx->aes.ccm.m;
|
||||
}
|
||||
|
||||
*(uint16_t *)(buf + arg - 2) = len;
|
||||
buf[arg - 2] = len >> 8;
|
||||
buf[arg - 1] = len & 0xff;
|
||||
|
||||
/* Extra padding: tag appended to record. */
|
||||
return cctx->aes.ccm.m;
|
||||
|
||||
@@ -2791,22 +2809,6 @@ static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* increment counter (64-bit int) by 1 */
|
||||
static void ctr64_inc(unsigned char *counter)
|
||||
{
|
||||
int n = 8;
|
||||
unsigned char c;
|
||||
|
||||
do {
|
||||
--n;
|
||||
c = counter[n];
|
||||
++c;
|
||||
counter[n] = c;
|
||||
if (c)
|
||||
return;
|
||||
} while (n);
|
||||
}
|
||||
|
||||
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
|
||||
|
||||
@@ -60,4 +60,18 @@ void bn_set_static_words(BIGNUM *a, BN_ULONG *words, int size);
|
||||
*/
|
||||
int bn_set_words(BIGNUM *a, BN_ULONG *words, int num_words);
|
||||
|
||||
/*
|
||||
* Some BIGNUM functions assume most significant limb to be non-zero, which
|
||||
* is customarily arranged by bn_correct_top. Output from below functions
|
||||
* is not processed with bn_correct_top, and for this reason it may not be
|
||||
* returned out of public API. It may only be passed internally into other
|
||||
* functions known to support non-minimal or zero-padded BIGNUMs.
|
||||
*/
|
||||
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx);
|
||||
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m);
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
# ifndef OPENSSL_NO_SM2
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
int ERR_load_SM2_strings(void);
|
||||
|
||||
/*
|
||||
|
||||
+6
-16
@@ -42,22 +42,13 @@ static u32 ocb_ntz(u64 n)
|
||||
static void ocb_block_lshift(const unsigned char *in, size_t shift,
|
||||
unsigned char *out)
|
||||
{
|
||||
unsigned char shift_mask;
|
||||
int i;
|
||||
unsigned char mask[15];
|
||||
unsigned char carry = 0, carry_next;
|
||||
|
||||
shift_mask = 0xff;
|
||||
shift_mask <<= (8 - shift);
|
||||
for (i = 15; i >= 0; i--) {
|
||||
if (i > 0) {
|
||||
mask[i - 1] = in[i] & shift_mask;
|
||||
mask[i - 1] >>= 8 - shift;
|
||||
}
|
||||
out[i] = in[i] << shift;
|
||||
|
||||
if (i != 15) {
|
||||
out[i] ^= mask[i];
|
||||
}
|
||||
carry_next = in[i] >> (8 - shift);
|
||||
out[i] = (in[i] << shift) | carry;
|
||||
carry = carry_next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +65,7 @@ static void ocb_double(OCB_BLOCK *in, OCB_BLOCK *out)
|
||||
*/
|
||||
mask = in->c[0] & 0x80;
|
||||
mask >>= 7;
|
||||
mask *= 135;
|
||||
mask = (0 - mask) & 0x87;
|
||||
|
||||
ocb_block_lshift(in->c, 1, out->c);
|
||||
|
||||
@@ -119,8 +110,7 @@ static OCB_BLOCK *ocb_lookup_l(OCB128_CONTEXT *ctx, size_t idx)
|
||||
* the index.
|
||||
*/
|
||||
ctx->max_l_index += (idx - ctx->max_l_index + 4) & ~3;
|
||||
tmp_ptr =
|
||||
OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK));
|
||||
tmp_ptr = OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK));
|
||||
if (tmp_ptr == NULL) /* prevent ctx->l from being clobbered */
|
||||
return NULL;
|
||||
ctx->l = tmp_ptr;
|
||||
|
||||
@@ -3753,6 +3753,44 @@ poly1305_emit_base2_44:
|
||||
.size poly1305_emit_base2_44,.-poly1305_emit_base2_44
|
||||
___
|
||||
} } }
|
||||
$code.=<<___;
|
||||
.align 64
|
||||
.Lconst:
|
||||
.Lmask24:
|
||||
.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0
|
||||
.L129:
|
||||
.long `1<<24`,0,`1<<24`,0,`1<<24`,0,`1<<24`,0
|
||||
.Lmask26:
|
||||
.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0
|
||||
.Lpermd_avx2:
|
||||
.long 2,2,2,3,2,0,2,1
|
||||
.Lpermd_avx512:
|
||||
.long 0,0,0,1, 0,2,0,3, 0,4,0,5, 0,6,0,7
|
||||
|
||||
.L2_44_inp_permd:
|
||||
.long 0,1,1,2,2,3,7,7
|
||||
.L2_44_inp_shift:
|
||||
.quad 0,12,24,64
|
||||
.L2_44_mask:
|
||||
.quad 0xfffffffffff,0xfffffffffff,0x3ffffffffff,0xffffffffffffffff
|
||||
.L2_44_shift_rgt:
|
||||
.quad 44,44,42,64
|
||||
.L2_44_shift_lft:
|
||||
.quad 8,8,10,64
|
||||
|
||||
.align 64
|
||||
.Lx_mask44:
|
||||
.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff
|
||||
.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff
|
||||
.Lx_mask42:
|
||||
.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff
|
||||
.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
.asciz "Poly1305 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
.align 16
|
||||
___
|
||||
|
||||
{ # chacha20-poly1305 helpers
|
||||
my ($out,$inp,$otp,$len)=$win64 ? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
|
||||
@@ -3857,45 +3895,6 @@ xor128_decrypt_n_pad:
|
||||
.size xor128_decrypt_n_pad,.-xor128_decrypt_n_pad
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
.align 64
|
||||
.Lconst:
|
||||
.Lmask24:
|
||||
.long 0x0ffffff,0,0x0ffffff,0,0x0ffffff,0,0x0ffffff,0
|
||||
.L129:
|
||||
.long `1<<24`,0,`1<<24`,0,`1<<24`,0,`1<<24`,0
|
||||
.Lmask26:
|
||||
.long 0x3ffffff,0,0x3ffffff,0,0x3ffffff,0,0x3ffffff,0
|
||||
.Lpermd_avx2:
|
||||
.long 2,2,2,3,2,0,2,1
|
||||
.Lpermd_avx512:
|
||||
.long 0,0,0,1, 0,2,0,3, 0,4,0,5, 0,6,0,7
|
||||
|
||||
.L2_44_inp_permd:
|
||||
.long 0,1,1,2,2,3,7,7
|
||||
.L2_44_inp_shift:
|
||||
.quad 0,12,24,64
|
||||
.L2_44_mask:
|
||||
.quad 0xfffffffffff,0xfffffffffff,0x3ffffffffff,0xffffffffffffffff
|
||||
.L2_44_shift_rgt:
|
||||
.quad 44,44,42,64
|
||||
.L2_44_shift_lft:
|
||||
.quad 8,8,10,64
|
||||
|
||||
.align 64
|
||||
.Lx_mask44:
|
||||
.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff
|
||||
.quad 0xfffffffffff,0xfffffffffff,0xfffffffffff,0xfffffffffff
|
||||
.Lx_mask42:
|
||||
.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff
|
||||
.quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff
|
||||
___
|
||||
}
|
||||
|
||||
$code.=<<___;
|
||||
.asciz "Poly1305 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
.align 16
|
||||
___
|
||||
|
||||
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
|
||||
# CONTEXT *context,DISPATCHER_CONTEXT *disp)
|
||||
|
||||
+23
-15
@@ -150,32 +150,40 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
|
||||
dblen = num - mdlen - 1;
|
||||
db = OPENSSL_malloc(dblen);
|
||||
em = OPENSSL_malloc(num);
|
||||
if (db == NULL || em == NULL) {
|
||||
if (db == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always do this zero-padding copy (even when num == flen) to avoid
|
||||
* leaking that information. The copy still leaks some side-channel
|
||||
* information, but it's impossible to have a fixed memory access
|
||||
* pattern since we can't read out of the bounds of |from|.
|
||||
*
|
||||
* TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
|
||||
*/
|
||||
memset(em, 0, num);
|
||||
memcpy(em + num - flen, from, flen);
|
||||
if (flen != num) {
|
||||
em = OPENSSL_zalloc(num);
|
||||
if (em == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller is encouraged to pass zero-padded message created with
|
||||
* BN_bn2binpad, but if it doesn't, we do this zero-padding copy
|
||||
* to avoid leaking that information. The copy still leaks some
|
||||
* side-channel information, but it's impossible to have a fixed
|
||||
* memory access pattern since we can't read out of the bounds of
|
||||
* |from|.
|
||||
*/
|
||||
memcpy(em + num - flen, from, flen);
|
||||
from = em;
|
||||
}
|
||||
|
||||
/*
|
||||
* The first byte must be zero, however we must not leak if this is
|
||||
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
|
||||
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
|
||||
*/
|
||||
good = constant_time_is_zero(em[0]);
|
||||
good = constant_time_is_zero(from[0]);
|
||||
|
||||
maskedseed = em + 1;
|
||||
maskeddb = em + 1 + mdlen;
|
||||
maskedseed = from + 1;
|
||||
maskeddb = from + 1 + mdlen;
|
||||
|
||||
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
|
||||
goto cleanup;
|
||||
|
||||
+12
-26
@@ -68,7 +68,7 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
@@ -142,15 +142,10 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
* BN_bn2binpad puts in leading 0 bytes if the number is less than
|
||||
* the length of the modulus.
|
||||
*/
|
||||
j = BN_num_bytes(ret);
|
||||
i = BN_bn2bin(ret, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
r = BN_bn2binpad(ret, to, num);
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
@@ -239,7 +234,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret, *res;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
@@ -354,15 +349,10 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
|
||||
}
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
* BN_bn2binpad puts in leading 0 bytes if the number is less than
|
||||
* the length of the modulus.
|
||||
*/
|
||||
j = BN_num_bytes(res);
|
||||
i = BN_bn2bin(res, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
r = BN_bn2binpad(res, to, num);
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
@@ -376,7 +366,6 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int j, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
@@ -472,8 +461,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
|
||||
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
|
||||
j = BN_bn2binpad(ret, buf, num);
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
@@ -486,7 +474,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
|
||||
r = RSA_padding_check_SSLv23(to, num, buf, j, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, j, num);
|
||||
memcpy(to, buf, (r = j));
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
@@ -509,7 +497,6 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
@@ -574,8 +561,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
|
||||
if (!BN_sub(ret, rsa->n, ret))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
i = BN_bn2bin(ret, p);
|
||||
i = BN_bn2binpad(ret, buf, num);
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
@@ -585,7 +571,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
|
||||
r = RSA_padding_check_X931(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, i, num);
|
||||
memcpy(to, buf, (r = i));
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
|
||||
+21
-18
@@ -175,27 +175,30 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
if (num < 11)
|
||||
goto err;
|
||||
|
||||
em = OPENSSL_zalloc(num);
|
||||
if (em == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
if (flen != num) {
|
||||
em = OPENSSL_zalloc(num);
|
||||
if (em == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Caller is encouraged to pass zero-padded message created with
|
||||
* BN_bn2binpad, but if it doesn't, we do this zero-padding copy
|
||||
* to avoid leaking that information. The copy still leaks some
|
||||
* side-channel information, but it's impossible to have a fixed
|
||||
* memory access pattern since we can't read out of the bounds of
|
||||
* |from|.
|
||||
*/
|
||||
memcpy(em + num - flen, from, flen);
|
||||
from = em;
|
||||
}
|
||||
/*
|
||||
* Always do this zero-padding copy (even when num == flen) to avoid
|
||||
* leaking that information. The copy still leaks some side-channel
|
||||
* information, but it's impossible to have a fixed memory access
|
||||
* pattern since we can't read out of the bounds of |from|.
|
||||
*
|
||||
* TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
|
||||
*/
|
||||
memcpy(em + num - flen, from, flen);
|
||||
|
||||
good = constant_time_is_zero(em[0]);
|
||||
good &= constant_time_eq(em[1], 2);
|
||||
good = constant_time_is_zero(from[0]);
|
||||
good &= constant_time_eq(from[1], 2);
|
||||
|
||||
found_zero_byte = 0;
|
||||
for (i = 2; i < num; i++) {
|
||||
unsigned int equals0 = constant_time_is_zero(em[i]);
|
||||
unsigned int equals0 = constant_time_is_zero(from[i]);
|
||||
zero_index =
|
||||
constant_time_select_int(~found_zero_byte & equals0, i,
|
||||
zero_index);
|
||||
@@ -203,7 +206,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
}
|
||||
|
||||
/*
|
||||
* PS must be at least 8 bytes long, and it starts two bytes into |em|.
|
||||
* PS must be at least 8 bytes long, and it starts two bytes into |from|.
|
||||
* If we never found a 0-byte, then |zero_index| is 0 and the check
|
||||
* also fails.
|
||||
*/
|
||||
@@ -232,7 +235,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(to, em + msg_index, mlen);
|
||||
memcpy(to, from + msg_index, mlen);
|
||||
|
||||
err:
|
||||
OPENSSL_clear_free(em, num);
|
||||
|
||||
@@ -63,6 +63,14 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
/* Accept even zero-padded input */
|
||||
if (flen == num) {
|
||||
if (*(p++) != 0) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_BLOCK_TYPE_IS_NOT_02);
|
||||
return -1;
|
||||
}
|
||||
flen--;
|
||||
}
|
||||
if ((num != (flen + 1)) || (*(p++) != 02)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_BLOCK_TYPE_IS_NOT_02);
|
||||
return -1;
|
||||
|
||||
@@ -32,11 +32,13 @@ should then be retried at a later time.
|
||||
|
||||
If BIO_should_retry() is false then the cause is an error condition.
|
||||
|
||||
BIO_should_read() is true if the cause of the condition is that a BIO
|
||||
needs to read data.
|
||||
BIO_should_read() is true if the cause of the condition is that the BIO
|
||||
has insufficient data to return. Check for readability and/or retry the
|
||||
last operation.
|
||||
|
||||
BIO_should_write() is true if the cause of the condition is that a BIO
|
||||
needs to read data.
|
||||
BIO_should_write() is true if the cause of the condition is that the BIO
|
||||
has pending data to write. Check for writability and/or retry the
|
||||
last operation.
|
||||
|
||||
BIO_should_io_special() is true if some "special" condition, that is a
|
||||
reason other than reading or writing is the cause of the condition.
|
||||
|
||||
@@ -55,8 +55,8 @@ freed later using OPENSSL_free().
|
||||
BN_hex2bn() takes as many characters as possible from the string B<str>,
|
||||
including the leading character '-' which means negative, to form a valid
|
||||
hexadecimal number representation and converts them to a B<BIGNUM> and
|
||||
stores it in **B<bn>. If *B<bn> is NULL, a new B<BIGNUM> is created. If
|
||||
B<bn> is NULL, it only computes the length of valid representation.
|
||||
stores it in **B<a>. If *B<a> is NULL, a new B<BIGNUM> is created. If
|
||||
B<a> is NULL, it only computes the length of valid representation.
|
||||
A "negative zero" is converted to zero.
|
||||
BN_dec2bn() is the same using the decimal system.
|
||||
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SSL_CTX_set_mode, SSL_set_mode, SSL_CTX_get_mode, SSL_get_mode - manipulate SSL engine mode
|
||||
SSL_CTX_set_mode, SSL_CTX_clear_mode, SSL_set_mode, SSL_clear_mode, SSL_CTX_get_mode, SSL_get_mode - manipulate SSL engine mode
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
long SSL_CTX_set_mode(SSL_CTX *ctx, long mode);
|
||||
long SSL_CTX_clear_mode(SSL_CTX *ctx, long mode);
|
||||
long SSL_set_mode(SSL *ssl, long mode);
|
||||
long SSL_clear_mode(SSL *ssl, long mode);
|
||||
|
||||
long SSL_CTX_get_mode(SSL_CTX *ctx);
|
||||
long SSL_get_mode(SSL *ssl);
|
||||
@@ -18,9 +20,11 @@ SSL_CTX_set_mode, SSL_set_mode, SSL_CTX_get_mode, SSL_get_mode - manipulate SSL
|
||||
|
||||
SSL_CTX_set_mode() adds the mode set via bitmask in B<mode> to B<ctx>.
|
||||
Options already set before are not cleared.
|
||||
SSL_CTX_clear_mode() removes the mode set via bitmask in B<mode> from B<ctx>.
|
||||
|
||||
SSL_set_mode() adds the mode set via bitmask in B<mode> to B<ssl>.
|
||||
Options already set before are not cleared.
|
||||
SSL_clear_mode() removes the mode set via bitmask in B<mode> from B<ssl>.
|
||||
|
||||
SSL_CTX_get_mode() returns the mode set for B<ctx>.
|
||||
|
||||
@@ -51,16 +55,31 @@ non-blocking write().
|
||||
|
||||
=item SSL_MODE_AUTO_RETRY
|
||||
|
||||
Never bother the application with retries if the transport is blocking.
|
||||
If a renegotiation take place during normal operation, a
|
||||
L<SSL_read_ex(3)>, L<SSL_read(3)>, L<SSL_write_ex(3)> or L<SSL_write(3)> would
|
||||
return with a failure and indicate the need to retry with SSL_ERROR_WANT_READ.
|
||||
During normal operations, non-application data records might need to be sent or
|
||||
received that the application is not aware of.
|
||||
If a non-application data record was processed,
|
||||
L<SSL_read_ex(3)> and L<SSL_read(3)> can return with a failure and indicate the
|
||||
need to retry with B<SSL_ERROR_WANT_READ>.
|
||||
If such a non-application data record was processed, the flag
|
||||
B<SSL_MODE_AUTO_RETRY> causes it to try to process the next record instead of
|
||||
returning.
|
||||
|
||||
In a non-blocking environment applications must be prepared to handle
|
||||
incomplete read/write operations.
|
||||
Setting B<SSL_MODE_AUTO_RETRY> for a non-blocking B<BIO> will process
|
||||
non-application data records until either no more data is available or
|
||||
an application data record has been processed.
|
||||
|
||||
In a blocking environment, applications are not always prepared to
|
||||
deal with read/write operations returning without success report. The
|
||||
flag SSL_MODE_AUTO_RETRY will cause read/write operations to only
|
||||
return after the handshake and successful completion.
|
||||
deal with the functions returning intermediate reports such as retry
|
||||
requests, and setting the B<SSL_MODE_AUTO_RETRY> flag will cause the functions
|
||||
to only return after successfully processing an application data record or a
|
||||
failure.
|
||||
|
||||
Turning off B<SSL_MODE_AUTO_RETRY> can be useful with blocking B<BIO>s in case
|
||||
they are used in combination with something like select() or poll().
|
||||
Otherwise the call to SSL_read() or SSL_read_ex() might hang when a
|
||||
non-application record was sent and no application data was sent.
|
||||
|
||||
=item SSL_MODE_RELEASE_BUFFERS
|
||||
|
||||
@@ -88,6 +107,9 @@ used to perform cryptographic operations. See L<SSL_get_error(3)>.
|
||||
|
||||
=back
|
||||
|
||||
All modes are off by default except for SSL_MODE_AUTO_RETRY which is on by
|
||||
default since 1.1.1.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
SSL_CTX_set_mode() and SSL_set_mode() return the new mode bitmask
|
||||
|
||||
@@ -25,12 +25,14 @@ many input bytes as possible (for non-blocking reads) or not. For example if
|
||||
B<x> bytes are currently required by OpenSSL, but B<y> bytes are available from
|
||||
the underlying BIO (where B<y> > B<x>), then OpenSSL will read all B<y> bytes
|
||||
into its buffer (providing that the buffer is large enough) if reading ahead is
|
||||
on, or B<x> bytes otherwise. The parameter B<yes> or B<m> should be 0 to ensure
|
||||
reading ahead is off, or non zero otherwise.
|
||||
on, or B<x> bytes otherwise.
|
||||
Setting the parameter B<yes> to 0 turns reading ahead is off, other values turn
|
||||
it on.
|
||||
SSL_CTX_set_default_read_ahead() is identical to SSL_CTX_set_read_ahead().
|
||||
|
||||
SSL_CTX_get_read_ahead() and SSL_get_read_ahead() indicate whether reading
|
||||
ahead has been set or not.
|
||||
SSL_CTX_get_default_read_ahead() is identical to SSL_CTX_get_read_ahead().
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
@@ -39,6 +41,18 @@ SSL_CTX_get_read_head() and SSL_get_read_ahead() are undefined for DTLS. Setting
|
||||
B<read_ahead> can impact the behaviour of the SSL_pending() function
|
||||
(see L<SSL_pending(3)>).
|
||||
|
||||
Since SSL_read() can return B<SSL_ERROR_WANT_READ> for non-application data
|
||||
records, and SSL_has_pending() can't tell the difference between processed and
|
||||
unprocessed data, it's recommended that if read ahead is turned on that
|
||||
B<SSL_MODE_AUTO_RETRY> is not turned off using SSL_CTX_clear_mode().
|
||||
That will prevent getting B<SSL_ERROR_WANT_READ> when there is still a complete
|
||||
record availale that hasn't been processed.
|
||||
|
||||
If the application wants to continue to use the underlying transport (e.g. TCP
|
||||
connection) after the SSL connection is finished using SSL_shutdown() reading
|
||||
ahead should be turned off.
|
||||
Otherwise the SSL structure might read data that it shouldn't.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
SSL_get_read_ahead() and SSL_CTX_get_read_ahead() return 0 if reading ahead is off,
|
||||
|
||||
@@ -46,25 +46,45 @@ indicate that the underlying transport has been closed.
|
||||
|
||||
=item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
|
||||
|
||||
The operation did not complete; the same TLS/SSL I/O function should be
|
||||
called again later. If, by then, the underlying B<BIO> has data
|
||||
available for reading (if the result code is B<SSL_ERROR_WANT_READ>)
|
||||
or allows writing data (B<SSL_ERROR_WANT_WRITE>), then some TLS/SSL
|
||||
protocol progress will take place, i.e. at least part of an TLS/SSL
|
||||
record will be read or written. Note that the retry may again lead to
|
||||
a B<SSL_ERROR_WANT_READ> or B<SSL_ERROR_WANT_WRITE> condition.
|
||||
The operation did not complete and can be retried later.
|
||||
|
||||
B<SSL_ERROR_WANT_READ> is returned when the last operation was a read
|
||||
operation from a non-blocking B<BIO>.
|
||||
It means that not enough data was available at this time to complete the
|
||||
operation.
|
||||
If at a later time the underlying B<BIO> has data available for reading the same
|
||||
function can be called again.
|
||||
|
||||
SSL_read() and SSL_read_ex() can also set B<SSL_ERROR_WANT_READ> when there is
|
||||
still unprocessed data available at either the B<SSL> or the B<BIO> layer, even
|
||||
for a blocking B<BIO>.
|
||||
See L<SSL_read(3)> for more information.
|
||||
|
||||
B<SSL_ERROR_WANT_WRITE> is returned when the last operation was a write
|
||||
to a non-blocking B<BIO> and it was unable to sent all data to the B<BIO>.
|
||||
When the B<BIO> is writeable again, the same function can be called again.
|
||||
|
||||
Note that the retry may again lead to an B<SSL_ERROR_WANT_READ> or
|
||||
B<SSL_ERROR_WANT_WRITE> condition.
|
||||
There is no fixed upper limit for the number of iterations that
|
||||
may be necessary until progress becomes visible at application
|
||||
protocol level.
|
||||
|
||||
It is safe to call SSL_read() or SSL_read_ex() when more data is available
|
||||
even when the call that set this error was an SSL_write() or SSL_write_ex().
|
||||
However if the call was an SSL_write() or SSL_write_ex(), it should be called
|
||||
again to continue sending the application data.
|
||||
|
||||
For socket B<BIO>s (e.g. when SSL_set_fd() was used), select() or
|
||||
poll() on the underlying socket can be used to find out when the
|
||||
TLS/SSL I/O function should be retried.
|
||||
|
||||
Caveat: Any TLS/SSL I/O function can lead to either of
|
||||
B<SSL_ERROR_WANT_READ> and B<SSL_ERROR_WANT_WRITE>. In particular,
|
||||
B<SSL_ERROR_WANT_READ> and B<SSL_ERROR_WANT_WRITE>.
|
||||
In particular,
|
||||
SSL_read_ex(), SSL_read(), SSL_peek_ex(), or SSL_peek() may want to write data
|
||||
and SSL_write() or SSL_write_ex() may want to read data. This is mainly because
|
||||
and SSL_write() or SSL_write_ex() may want to read data.
|
||||
This is mainly because
|
||||
TLS/SSL handshakes may occur at any time during the protocol (initiated by
|
||||
either the client or the server); SSL_read_ex(), SSL_read(), SSL_peek_ex(),
|
||||
SSL_peek(), SSL_write_ex(), and SSL_write() will handle any pending handshakes.
|
||||
@@ -122,6 +142,9 @@ Some non-recoverable I/O error occurred.
|
||||
The OpenSSL error queue may contain more information on the error.
|
||||
For socket I/O on Unix systems, consult B<errno> for details.
|
||||
|
||||
This value can also be returned for other errors, check the error queue for
|
||||
details.
|
||||
|
||||
=item SSL_ERROR_SSL
|
||||
|
||||
A failure in the SSL library occurred, usually a protocol error. The
|
||||
|
||||
+32
-21
@@ -51,40 +51,47 @@ call. If B<num> is higher than the number of bytes buffered then the read
|
||||
functions will return with the bytes buffered. If no more bytes are in the
|
||||
buffer, the read functions will trigger the processing of the next record.
|
||||
Only when the record has been received and processed completely will the read
|
||||
functions return reporting success. At most the contents of the record will
|
||||
functions return reporting success. At most the contents of one record will
|
||||
be returned. As the size of an SSL/TLS record may exceed the maximum packet size
|
||||
of the underlying transport (e.g. TCP), it may be necessary to read several
|
||||
packets from the transport layer before the record is complete and the read call
|
||||
can succeed.
|
||||
|
||||
If B<SSL_MODE_AUTO_RETRY> has been switched off and a non-application data
|
||||
record has been processed, the read function can return and set the error to
|
||||
B<SSL_ERROR_WANT_READ>.
|
||||
In this case there might still be unprocessed data available in the B<BIO>.
|
||||
If read ahead was set using L<SSL_CTX_set_read_ahead(3)>, there might also still
|
||||
be unprocessed data available in the B<SSL>.
|
||||
This behaviour can be controlled using the L<SSL_CTX_set_mode(3)> call.
|
||||
|
||||
If the underlying BIO is B<blocking>, a read function will only return once the
|
||||
read operation has been finished or an error occurred, except when a
|
||||
renegotiation takes place, in which case a SSL_ERROR_WANT_READ may occur. This
|
||||
behaviour can be controlled with the SSL_MODE_AUTO_RETRY flag of the
|
||||
L<SSL_CTX_set_mode(3)> call.
|
||||
non-application data record has been processed and B<SSL_MODE_AUTO_RETRY> is
|
||||
not set.
|
||||
Note that if B<SSL_MODE_AUTO_RETRY> is set and only non-application data is
|
||||
available the call will hang.
|
||||
|
||||
If the underlying BIO is B<non-blocking>, a read function will also return when
|
||||
the underlying BIO could not satisfy the needs of the function to continue the
|
||||
operation. In this case a call to L<SSL_get_error(3)> with the
|
||||
operation.
|
||||
In this case a call to L<SSL_get_error(3)> with the
|
||||
return value of the read function will yield B<SSL_ERROR_WANT_READ> or
|
||||
B<SSL_ERROR_WANT_WRITE>. As at any time a re-negotiation is possible, a
|
||||
a read function can also cause write operations! The calling process then must
|
||||
repeat the call after taking appropriate action to satisfy the needs of the read
|
||||
function. The action depends on the underlying BIO. When using a non-blocking
|
||||
socket, nothing is to be done, but select() can be used to check for the
|
||||
required condition. When using a buffering BIO, like a BIO pair, data must be
|
||||
written into or retrieved out of the BIO before being able to continue.
|
||||
B<SSL_ERROR_WANT_WRITE>.
|
||||
As at any time it's possible that non-application data needs to be sent,
|
||||
a read function can also cause write operations.
|
||||
The calling process then must repeat the call after taking appropriate action
|
||||
to satisfy the needs of the read function.
|
||||
The action depends on the underlying BIO.
|
||||
When using a non-blocking socket, nothing is to be done, but select() can be
|
||||
used to check for the required condition.
|
||||
When using a buffering BIO, like a BIO pair, data must be written into or
|
||||
retrieved out of the BIO before being able to continue.
|
||||
|
||||
L<SSL_pending(3)> can be used to find out whether there
|
||||
are buffered bytes available for immediate retrieval. In this case
|
||||
the read function can be called without blocking or actually receiving
|
||||
new data from the underlying socket.
|
||||
|
||||
=head1 WARNING
|
||||
|
||||
When a read function operation has to be repeated because L<SSL_get_error(3)>
|
||||
returned B<SSL_ERROR_WANT_READ> or B<SSL_ERROR_WANT_WRITE>, it must be repeated
|
||||
with the same arguments.
|
||||
are buffered bytes available for immediate retrieval.
|
||||
In this case the read function can be called without blocking or actually
|
||||
receiving new data from the underlying socket.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
@@ -119,6 +126,10 @@ You should instead call SSL_get_error() to find out if it's retryable.
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
SSL_read_ex() and SSL_peek_ex() were added in OpenSSL 1.1.1.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<SSL_get_error(3)>, L<SSL_write_ex(3)>,
|
||||
|
||||
+11
-6
@@ -34,10 +34,7 @@ L<SSL_set_connect_state(3)> or SSL_set_accept_state()
|
||||
before the first call to a write function.
|
||||
|
||||
If the underlying BIO is B<blocking>, the write functions will only return, once
|
||||
the write operation has been finished or an error occurred, except when a
|
||||
renegotiation take place, in which case a SSL_ERROR_WANT_READ may occur.
|
||||
This behaviour can be controlled with the SSL_MODE_AUTO_RETRY flag of the
|
||||
L<SSL_CTX_set_mode(3)> call.
|
||||
the write operation has been finished or an error occurred.
|
||||
|
||||
If the underlying BIO is B<non-blocking> the write functions will also return
|
||||
when the underlying BIO could not satisfy the needs of the function to continue
|
||||
@@ -65,9 +62,13 @@ write is performed with the size of a message block, which is 16kB.
|
||||
When a write function call has to be repeated because L<SSL_get_error(3)>
|
||||
returned B<SSL_ERROR_WANT_READ> or B<SSL_ERROR_WANT_WRITE>, it must be repeated
|
||||
with the same arguments.
|
||||
The data that was passed might have been partially processed.
|
||||
When B<SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER> was set using L<SSL_CTX_set_mode(3)>
|
||||
the pointer can be different, but the data and length should still be the same.
|
||||
|
||||
When calling the write functions with num=0 bytes to be sent the behaviour is
|
||||
undefined.
|
||||
You should not call SSL_write() with num=0, it will return an error.
|
||||
SSL_write_ex() can be called with num=0, but will not send application data to
|
||||
the peer.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
@@ -103,6 +104,10 @@ You should instead call SSL_get_error() to find out if it's retryable.
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
SSL_write_ex() was added in OpenSSL 1.1.1.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<SSL_get_error(3)>, L<SSL_read_ex(3)>, L<SSL_read(3)>
|
||||
|
||||
+3
@@ -7,6 +7,9 @@
|
||||
|
||||
# Quick transfer to the downloaded Text::Template
|
||||
|
||||
package transfer::Text::Template;
|
||||
$VERSION = 1.46;
|
||||
|
||||
BEGIN {
|
||||
use File::Spec::Functions;
|
||||
use File::Basename;
|
||||
|
||||
@@ -73,6 +73,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||
ctx = SSL_CTX_new(SSLv23_method());
|
||||
|
||||
client = SSL_new(ctx);
|
||||
OPENSSL_assert(SSL_set_min_proto_version(client, 0) == 1);
|
||||
OPENSSL_assert(SSL_set_cipher_list(client, "ALL:eNULL:@SECLEVEL=0") == 1);
|
||||
SSL_set_tlsext_host_name(client, "localhost");
|
||||
in = BIO_new(BIO_s_mem());
|
||||
|
||||
+5
-2
@@ -534,6 +534,11 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||
/* This only fuzzes the initial flow from the client so far. */
|
||||
ctx = SSL_CTX_new(SSLv23_method());
|
||||
|
||||
ret = SSL_CTX_set_min_proto_version(ctx, 0);
|
||||
OPENSSL_assert(ret == 1);
|
||||
ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:@SECLEVEL=0");
|
||||
OPENSSL_assert(ret == 1);
|
||||
|
||||
/* RSA */
|
||||
bufp = kRSAPrivateKeyDER;
|
||||
privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER));
|
||||
@@ -602,8 +607,6 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||
/* TODO: Set up support for SRP and PSK */
|
||||
|
||||
server = SSL_new(ctx);
|
||||
ret = SSL_set_cipher_list(server, "ALL:eNULL:@SECLEVEL=0");
|
||||
OPENSSL_assert(ret == 1);
|
||||
in = BIO_new(BIO_s_mem());
|
||||
out = BIO_new(BIO_s_mem());
|
||||
SSL_set_bio(server, in, out);
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
# ifndef OPENSSL_NO_DSO
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
int ERR_load_DSO_strings(void);
|
||||
|
||||
/*
|
||||
|
||||
@@ -58,6 +58,7 @@ int ERR_load_CONF_strings(void);
|
||||
# define CONF_R_NO_SECTION 107
|
||||
# define CONF_R_NO_SUCH_FILE 114
|
||||
# define CONF_R_NO_VALUE 108
|
||||
# define CONF_R_NUMBER_TOO_LARGE 121
|
||||
# define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111
|
||||
# define CONF_R_SSL_COMMAND_SECTION_EMPTY 117
|
||||
# define CONF_R_SSL_COMMAND_SECTION_NOT_FOUND 118
|
||||
|
||||
+10
-6
@@ -64,8 +64,11 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
|
||||
# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
|
||||
# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
|
||||
# define EC_F_EC_GF2M_SIMPLE_LADDER_POST 285
|
||||
# define EC_F_EC_GF2M_SIMPLE_LADDER_PRE 288
|
||||
# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
|
||||
# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
|
||||
# define EC_F_EC_GF2M_SIMPLE_POINTS_MUL 289
|
||||
# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
|
||||
# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
|
||||
# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
|
||||
@@ -133,6 +136,7 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_F_EC_PKEY_CHECK 273
|
||||
# define EC_F_EC_PKEY_PARAM_CHECK 274
|
||||
# define EC_F_EC_POINTS_MAKE_AFFINE 136
|
||||
# define EC_F_EC_POINTS_MUL 290
|
||||
# define EC_F_EC_POINT_ADD 112
|
||||
# define EC_F_EC_POINT_BN2POINT 280
|
||||
# define EC_F_EC_POINT_CMP 113
|
||||
@@ -156,6 +160,7 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
|
||||
# define EC_F_EC_POINT_SET_TO_INFINITY 127
|
||||
# define EC_F_EC_PRE_COMP_NEW 196
|
||||
# define EC_F_EC_SCALAR_MUL_LADDER 284
|
||||
# define EC_F_EC_WNAF_MUL 187
|
||||
# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
|
||||
# define EC_F_I2D_ECPARAMETERS 190
|
||||
@@ -183,12 +188,6 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_F_PKEY_EC_KEYGEN 199
|
||||
# define EC_F_PKEY_EC_PARAMGEN 219
|
||||
# define EC_F_PKEY_EC_SIGN 218
|
||||
# define EC_F_PKEY_SM2_CTRL 284
|
||||
# define EC_F_PKEY_SM2_CTRL_STR 285
|
||||
# define EC_F_PKEY_SM2_INIT 287
|
||||
# define EC_F_PKEY_SM2_KEYGEN 288
|
||||
# define EC_F_PKEY_SM2_PARAMGEN 289
|
||||
# define EC_F_PKEY_SM2_SIGN 290
|
||||
# define EC_F_VALIDATE_ECX_DERIVE 278
|
||||
|
||||
/*
|
||||
@@ -228,6 +227,9 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_R_INVALID_TRINOMIAL_BASIS 137
|
||||
# define EC_R_KDF_PARAMETER_ERROR 148
|
||||
# define EC_R_KEYS_NOT_SET 140
|
||||
# define EC_R_LADDER_POST_FAILURE 136
|
||||
# define EC_R_LADDER_PRE_FAILURE 153
|
||||
# define EC_R_LADDER_STEP_FAILURE 162
|
||||
# define EC_R_MISSING_PARAMETERS 124
|
||||
# define EC_R_MISSING_PRIVATE_KEY 125
|
||||
# define EC_R_NEED_NEW_SETUP_VALUES 157
|
||||
@@ -242,12 +244,14 @@ int ERR_load_EC_strings(void);
|
||||
# define EC_R_PKPARAMETERS2GROUP_FAILURE 127
|
||||
# define EC_R_POINT_ARITHMETIC_FAILURE 155
|
||||
# define EC_R_POINT_AT_INFINITY 106
|
||||
# define EC_R_POINT_COORDINATES_BLIND_FAILURE 163
|
||||
# define EC_R_POINT_IS_NOT_ON_CURVE 107
|
||||
# define EC_R_RANDOM_NUMBER_GENERATION_FAILED 158
|
||||
# define EC_R_SHARED_INFO_ERROR 150
|
||||
# define EC_R_SLOT_FULL 108
|
||||
# define EC_R_UNDEFINED_GENERATOR 113
|
||||
# define EC_R_UNDEFINED_ORDER 128
|
||||
# define EC_R_UNKNOWN_COFACTOR 164
|
||||
# define EC_R_UNKNOWN_GROUP 129
|
||||
# define EC_R_UNKNOWN_ORDER 114
|
||||
# define EC_R_UNSUPPORTED_FIELD 131
|
||||
|
||||
@@ -68,10 +68,14 @@ extern "C" {
|
||||
* still won't see them if the library has been built to disable deprecated
|
||||
* functions.
|
||||
*/
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
|
||||
#else
|
||||
#ifndef DECLARE_DEPRECATED
|
||||
# define DECLARE_DEPRECATED(f) f;
|
||||
# ifdef __GNUC__
|
||||
# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
|
||||
# undef DECLARE_DEPRECATED
|
||||
# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_FILE
|
||||
|
||||
+22
-9
@@ -995,22 +995,35 @@ int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
|
||||
ctx->cert->sec_ex);
|
||||
}
|
||||
|
||||
int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
|
||||
if (ssl_cert_info[i].nid == nid) {
|
||||
*pidx = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
|
||||
{
|
||||
int nid = EVP_PKEY_id(pk);
|
||||
size_t i;
|
||||
size_t tmpidx;
|
||||
|
||||
if (nid == NID_undef)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
|
||||
if (ssl_cert_info[i].nid == nid) {
|
||||
if (pidx != NULL)
|
||||
*pidx = i;
|
||||
return &ssl_cert_info[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
if (!ssl_cert_lookup_by_nid(nid, &tmpidx))
|
||||
return NULL;
|
||||
|
||||
if (pidx != NULL)
|
||||
*pidx = tmpidx;
|
||||
|
||||
return &ssl_cert_info[tmpidx];
|
||||
}
|
||||
|
||||
const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
|
||||
|
||||
+3
-1
@@ -2332,6 +2332,7 @@ __owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other);
|
||||
__owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid,
|
||||
void *other);
|
||||
|
||||
__owur int ssl_cert_lookup_by_nid(int nid, size_t *pidx);
|
||||
__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk,
|
||||
size_t *pidx);
|
||||
__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx);
|
||||
@@ -2412,7 +2413,8 @@ __owur int ssl3_handshake_write(SSL *s);
|
||||
|
||||
__owur int ssl_allow_compression(SSL *s);
|
||||
|
||||
__owur int ssl_version_supported(const SSL *s, int version);
|
||||
__owur int ssl_version_supported(const SSL *s, int version,
|
||||
const SSL_METHOD **meth);
|
||||
|
||||
__owur int ssl_set_client_hello_version(SSL *s);
|
||||
__owur int ssl_check_version_downgrade(SSL *s);
|
||||
|
||||
@@ -1014,6 +1014,8 @@ static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
|
||||
{
|
||||
SSL_SESSION *tmpsess = NULL;
|
||||
|
||||
s->ext.ticket_expected = 1;
|
||||
|
||||
switch (PACKET_remaining(tick)) {
|
||||
case 0:
|
||||
return SSL_TICKET_EMPTY;
|
||||
@@ -1031,7 +1033,6 @@ static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
|
||||
if (tmpsess == NULL)
|
||||
return SSL_TICKET_NO_DECRYPT;
|
||||
|
||||
s->ext.ticket_expected = 1;
|
||||
*sess = tmpsess;
|
||||
return SSL_TICKET_SUCCESS;
|
||||
}
|
||||
|
||||
+3
-1
@@ -179,7 +179,9 @@ int ossl_statem_skip_early_data(SSL *s)
|
||||
if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
|
||||
return 0;
|
||||
|
||||
if (!s->server || s->statem.hand_state != TLS_ST_EARLY_DATA)
|
||||
if (!s->server
|
||||
|| s->statem.hand_state != TLS_ST_EARLY_DATA
|
||||
|| s->hello_retry_request == SSL_HRR_COMPLETE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -1119,7 +1119,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
|
||||
}
|
||||
|
||||
if (sess == NULL
|
||||
|| !ssl_version_supported(s, sess->ssl_version)
|
||||
|| !ssl_version_supported(s, sess->ssl_version, NULL)
|
||||
|| !SSL_SESSION_is_resumable(sess)) {
|
||||
if (s->hello_retry_request == SSL_HRR_NONE
|
||||
&& !ssl_get_new_session(s, 0)) {
|
||||
|
||||
+48
-20
@@ -1485,6 +1485,40 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only called by servers. Returns 1 if the server has a TLSv1.3 capable
|
||||
* certificate type, or has PSK configured. Otherwise returns 0.
|
||||
*/
|
||||
static int is_tls13_capable(const SSL *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
if (s->psk_server_callback != NULL)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if (s->psk_find_session_cb != NULL)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
/* Skip over certs disallowed for TLSv1.3 */
|
||||
switch (i) {
|
||||
case SSL_PKEY_DSA_SIGN:
|
||||
case SSL_PKEY_GOST01:
|
||||
case SSL_PKEY_GOST12_256:
|
||||
case SSL_PKEY_GOST12_512:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ssl_has_cert(s, i))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl_version_supported - Check that the specified `version` is supported by
|
||||
* `SSL *` instance
|
||||
@@ -1494,7 +1528,7 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
|
||||
*
|
||||
* Returns 1 when supported, otherwise 0
|
||||
*/
|
||||
int ssl_version_supported(const SSL *s, int version)
|
||||
int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth)
|
||||
{
|
||||
const version_info *vent;
|
||||
const version_info *table;
|
||||
@@ -1514,9 +1548,14 @@ int ssl_version_supported(const SSL *s, int version)
|
||||
for (vent = table;
|
||||
vent->version != 0 && version_cmp(s, version, vent->version) <= 0;
|
||||
++vent) {
|
||||
if (vent->cmeth != NULL &&
|
||||
version_cmp(s, version, vent->version) == 0 &&
|
||||
ssl_method_error(s, vent->cmeth()) == 0) {
|
||||
if (vent->cmeth != NULL
|
||||
&& version_cmp(s, version, vent->version) == 0
|
||||
&& ssl_method_error(s, vent->cmeth()) == 0
|
||||
&& (!s->server
|
||||
|| version != TLS1_3_VERSION
|
||||
|| is_tls13_capable(s))) {
|
||||
if (meth != NULL)
|
||||
*meth = vent->cmeth();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1625,11 +1664,11 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
|
||||
static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd)
|
||||
{
|
||||
if (vers == TLS1_2_VERSION
|
||||
&& ssl_version_supported(s, TLS1_3_VERSION)) {
|
||||
&& ssl_version_supported(s, TLS1_3_VERSION, NULL)) {
|
||||
*dgrd = DOWNGRADE_TO_1_2;
|
||||
} else if (!SSL_IS_DTLS(s) && vers < TLS1_2_VERSION
|
||||
&& (ssl_version_supported(s, TLS1_2_VERSION)
|
||||
|| ssl_version_supported(s, TLS1_3_VERSION))) {
|
||||
&& (ssl_version_supported(s, TLS1_2_VERSION, NULL)
|
||||
|| ssl_version_supported(s, TLS1_3_VERSION, NULL))) {
|
||||
*dgrd = DOWNGRADE_TO_1_1;
|
||||
} else {
|
||||
*dgrd = DOWNGRADE_NONE;
|
||||
@@ -1735,19 +1774,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
|
||||
*/
|
||||
if (version_cmp(s, candidate_vers, best_vers) <= 0)
|
||||
continue;
|
||||
for (vent = table;
|
||||
vent->version != 0 && vent->version != (int)candidate_vers;
|
||||
++vent)
|
||||
continue;
|
||||
if (vent->version != 0 && vent->smeth != NULL) {
|
||||
const SSL_METHOD *method;
|
||||
|
||||
method = vent->smeth();
|
||||
if (ssl_method_error(s, method) == 0) {
|
||||
best_vers = candidate_vers;
|
||||
best_method = method;
|
||||
}
|
||||
}
|
||||
if (ssl_version_supported(s, candidate_vers, &best_method))
|
||||
best_vers = candidate_vers;
|
||||
}
|
||||
if (PACKET_remaining(&versionslist) != 0) {
|
||||
/* Trailing data? */
|
||||
|
||||
@@ -3649,8 +3649,6 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|
||||
*/
|
||||
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||
int m = s->session_ctx->session_cache_mode;
|
||||
|
||||
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
@@ -3658,13 +3656,6 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (m & SSL_SESS_CACHE_SERVER) {
|
||||
/*
|
||||
* Remove the old session from the cache. We carry on if this fails
|
||||
*/
|
||||
SSL_CTX_remove_session(s->session_ctx, s->session);
|
||||
}
|
||||
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = new_sess;
|
||||
}
|
||||
|
||||
+50
-1
@@ -955,7 +955,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
|
||||
const uint16_t *sent_sigs;
|
||||
const EVP_MD *md = NULL;
|
||||
char sigalgstr[2];
|
||||
size_t sent_sigslen, i;
|
||||
size_t sent_sigslen, i, cidx;
|
||||
int pkeyid = EVP_PKEY_id(pkey);
|
||||
const SIGALG_LOOKUP *lu;
|
||||
|
||||
@@ -986,6 +986,14 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
|
||||
SSL_R_WRONG_SIGNATURE_TYPE);
|
||||
return 0;
|
||||
}
|
||||
/* Check the sigalg is consistent with the key OID */
|
||||
if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx)
|
||||
|| lu->sig_idx != (int)cidx) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
|
||||
SSL_R_WRONG_SIGNATURE_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (pkeyid == EVP_PKEY_EC) {
|
||||
|
||||
@@ -1519,9 +1527,50 @@ static int tls12_sigalg_allowed(SSL *s, int op, const SIGALG_LOOKUP *lu)
|
||||
|| lu->hash_idx == SSL_MD_MD5_IDX
|
||||
|| lu->hash_idx == SSL_MD_SHA224_IDX))
|
||||
return 0;
|
||||
|
||||
/* See if public key algorithm allowed */
|
||||
if (ssl_cert_is_disabled(lu->sig_idx))
|
||||
return 0;
|
||||
|
||||
if (lu->sig == NID_id_GostR3410_2012_256
|
||||
|| lu->sig == NID_id_GostR3410_2012_512
|
||||
|| lu->sig == NID_id_GostR3410_2001) {
|
||||
/* We never allow GOST sig algs on the server with TLSv1.3 */
|
||||
if (s->server && SSL_IS_TLS13(s))
|
||||
return 0;
|
||||
if (!s->server
|
||||
&& s->method->version == TLS_ANY_VERSION
|
||||
&& s->s3->tmp.max_ver >= TLS1_3_VERSION) {
|
||||
int i, num;
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
|
||||
/*
|
||||
* We're a client that could negotiate TLSv1.3. We only allow GOST
|
||||
* sig algs if we could negotiate TLSv1.2 or below and we have GOST
|
||||
* ciphersuites enabled.
|
||||
*/
|
||||
|
||||
if (s->s3->tmp.min_ver >= TLS1_3_VERSION)
|
||||
return 0;
|
||||
|
||||
sk = SSL_get_ciphers(s);
|
||||
num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0;
|
||||
for (i = 0; i < num; i++) {
|
||||
const SSL_CIPHER *c;
|
||||
|
||||
c = sk_SSL_CIPHER_value(sk, i);
|
||||
/* Skip disabled ciphers */
|
||||
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
|
||||
continue;
|
||||
|
||||
if ((c->algorithm_mkey & SSL_kGOST) != 0)
|
||||
break;
|
||||
}
|
||||
if (i == num)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lu->hash == NID_undef)
|
||||
return 1;
|
||||
/* Security bits: half digest bits */
|
||||
|
||||
+5
-1
@@ -50,7 +50,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
||||
recordlentest drbgtest drbg_cavs_test sslbuffertest \
|
||||
time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
|
||||
servername_test ocspapitest rsa_mp_test fatalerrtest tls13ccstest \
|
||||
sysdefaulttest errtest
|
||||
sysdefaulttest errtest gosttest
|
||||
|
||||
SOURCE[versions]=versions.c
|
||||
INCLUDE[versions]=../include
|
||||
@@ -537,6 +537,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
||||
SOURCE[errtest]=errtest.c
|
||||
INCLUDE[errtest]=../include
|
||||
DEPEND[errtest]=../libcrypto libtestutil.a
|
||||
|
||||
SOURCE[gosttest]=gosttest.c ssltestlib.c
|
||||
INCLUDE[gosttest]=../include ..
|
||||
DEPEND[gosttest]=../libcrypto ../libssl libtestutil.a
|
||||
ENDIF
|
||||
|
||||
{-
|
||||
|
||||
@@ -153,6 +153,31 @@ static int test_check_null_numbers(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_check_overflow(void)
|
||||
{
|
||||
#if defined(_BSD_SOURCE) \
|
||||
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
|
||||
|| (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
|
||||
long val = 0;
|
||||
char max[(sizeof(long) * 8) / 3 + 3];
|
||||
char *p;
|
||||
|
||||
p = max + sprintf(max, "0%ld", LONG_MAX) - 1;
|
||||
setenv("FNORD", max, 1);
|
||||
if (!TEST_true(NCONF_get_number(NULL, "missing", "FNORD", &val))
|
||||
|| !TEST_long_eq(val, LONG_MAX))
|
||||
return 0;
|
||||
|
||||
while (++*p > '9')
|
||||
*p-- = '0';
|
||||
|
||||
setenv("FNORD", max, 1);
|
||||
if (!TEST_false(NCONF_get_number(NULL, "missing", "FNORD", &val)))
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
const char *conf_file;
|
||||
@@ -181,6 +206,7 @@ int setup_tests(void)
|
||||
|
||||
ADD_TEST(test_load_config);
|
||||
ADD_TEST(test_check_null_numbers);
|
||||
ADD_TEST(test_check_overflow);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -31,6 +31,7 @@ static int group_order_tests(EC_GROUP *group)
|
||||
{
|
||||
BIGNUM *n1 = NULL, *n2 = NULL, *order = NULL;
|
||||
EC_POINT *P = NULL, *Q = NULL, *R = NULL, *S = NULL;
|
||||
const EC_POINT *G = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int i = 0, r = 0;
|
||||
|
||||
@@ -38,6 +39,7 @@ static int group_order_tests(EC_GROUP *group)
|
||||
|| !TEST_ptr(n2 = BN_new())
|
||||
|| !TEST_ptr(order = BN_new())
|
||||
|| !TEST_ptr(ctx = BN_CTX_new())
|
||||
|| !TEST_ptr(G = EC_GROUP_get0_generator(group))
|
||||
|| !TEST_ptr(P = EC_POINT_new(group))
|
||||
|| !TEST_ptr(Q = EC_POINT_new(group))
|
||||
|| !TEST_ptr(R = EC_POINT_new(group))
|
||||
@@ -49,7 +51,15 @@ static int group_order_tests(EC_GROUP *group)
|
||||
|| !TEST_true(EC_POINT_is_at_infinity(group, Q))
|
||||
|| !TEST_true(EC_GROUP_precompute_mult(group, ctx))
|
||||
|| !TEST_true(EC_POINT_mul(group, Q, order, NULL, NULL, ctx))
|
||||
|| !TEST_true(EC_POINT_is_at_infinity(group, Q)))
|
||||
|| !TEST_true(EC_POINT_is_at_infinity(group, Q))
|
||||
|| !TEST_true(EC_POINT_copy(P, G))
|
||||
|| !TEST_true(BN_one(n1))
|
||||
|| !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
|
||||
|| !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx))
|
||||
|| !TEST_true(BN_sub(n1, order, n1))
|
||||
|| !TEST_true(EC_POINT_mul(group, Q, n1, NULL, NULL, ctx))
|
||||
|| !TEST_true(EC_POINT_invert(group, Q, ctx))
|
||||
|| !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, ctx)))
|
||||
goto err;
|
||||
|
||||
for (i = 1; i <= 2; i++) {
|
||||
@@ -62,6 +72,7 @@ static int group_order_tests(EC_GROUP *group)
|
||||
* EC_GROUP_precompute_mult has set up precomputation.
|
||||
*/
|
||||
|| !TEST_true(EC_POINT_mul(group, P, n1, NULL, NULL, ctx))
|
||||
|| (i == 1 && !TEST_int_eq(0, EC_POINT_cmp(group, P, G, ctx)))
|
||||
|| !TEST_true(BN_one(n1))
|
||||
/* n1 = 1 - order */
|
||||
|| !TEST_true(BN_sub(n1, n1, order))
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "ssltestlib.h"
|
||||
#include "testutil.h"
|
||||
#include "internal/nelem.h"
|
||||
|
||||
static char *cert1 = NULL;
|
||||
static char *privkey1 = NULL;
|
||||
static char *cert2 = NULL;
|
||||
static char *privkey2 = NULL;
|
||||
|
||||
static struct {
|
||||
char *cipher;
|
||||
int expected_prot;
|
||||
int certnum;
|
||||
} ciphers[] = {
|
||||
/* Server doesn't have a cert with appropriate sig algs - should fail */
|
||||
{"AES128-SHA", 0, 0},
|
||||
/* Server doesn't have a TLSv1.3 capable cert - should use TLSv1.2 */
|
||||
{"GOST2012-GOST8912-GOST8912", TLS1_2_VERSION, 0},
|
||||
/* Server doesn't have a TLSv1.3 capable cert - should use TLSv1.2 */
|
||||
{"GOST2012-GOST8912-GOST8912", TLS1_2_VERSION, 1},
|
||||
/* Server doesn't have a TLSv1.3 capable cert - should use TLSv1.2 */
|
||||
{"GOST2001-GOST89-GOST89", TLS1_2_VERSION, 0},
|
||||
};
|
||||
|
||||
/* Test that we never negotiate TLSv1.3 if using GOST */
|
||||
static int test_tls13(int idx)
|
||||
{
|
||||
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||
SSL *clientssl = NULL, *serverssl = NULL;
|
||||
int testresult = 0;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
|
||||
TLS_client_method(),
|
||||
TLS1_VERSION,
|
||||
TLS_MAX_VERSION,
|
||||
&sctx, &cctx,
|
||||
ciphers[idx].certnum == 0 ? cert1
|
||||
: cert2,
|
||||
ciphers[idx].certnum == 0 ? privkey1
|
||||
: privkey2)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(SSL_CTX_set_cipher_list(cctx, ciphers[idx].cipher))
|
||||
|| !TEST_true(SSL_CTX_set_cipher_list(sctx, ciphers[idx].cipher))
|
||||
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||
NULL, NULL)))
|
||||
goto end;
|
||||
|
||||
if (ciphers[idx].expected_prot == 0) {
|
||||
if (!TEST_false(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
} else {
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE))
|
||||
|| !TEST_int_eq(SSL_version(clientssl),
|
||||
ciphers[idx].expected_prot))
|
||||
goto end;
|
||||
}
|
||||
|
||||
testresult = 1;
|
||||
|
||||
end:
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(cert1 = test_get_argument(0))
|
||||
|| !TEST_ptr(privkey1 = test_get_argument(1))
|
||||
|| !TEST_ptr(cert2 = test_get_argument(2))
|
||||
|| !TEST_ptr(privkey2 = test_get_argument(3)))
|
||||
return 0;
|
||||
|
||||
ADD_ALL_TESTS(test_tls13, OSSL_NELEM(ciphers));
|
||||
return 1;
|
||||
}
|
||||
+19
-15
@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||
|
||||
setup("test_req");
|
||||
|
||||
plan tests => 8;
|
||||
plan tests => 9;
|
||||
|
||||
require_ok(srctop_file('test','recipes','tconversion.pl'));
|
||||
|
||||
@@ -23,26 +23,30 @@ open RND, ">>", ".rnd";
|
||||
print RND "string to make the random number generator think it has randomness";
|
||||
close RND;
|
||||
|
||||
# Check for duplicate -addext parameters
|
||||
# What type of key to generate?
|
||||
my @req_new;
|
||||
if (disabled("rsa")) {
|
||||
@req_new = ("-newkey", "dsa:".srctop_file("apps", "dsa512.pem"));
|
||||
} else {
|
||||
@req_new = ("-new");
|
||||
note("There should be a 2 sequences of .'s and some +'s.");
|
||||
note("There should not be more that at most 80 per line");
|
||||
}
|
||||
|
||||
# Check for duplicate -addext parameters, and one "working" case.
|
||||
my @addext_args = ( "openssl", "req", "-new", "-out", "testreq.pem",
|
||||
"-config", srctop_file("test", "test.cnf"), @req_new );
|
||||
my $val = "subjectAltName=DNS:example.com";
|
||||
my $val2 = " " . $val;
|
||||
my $val3 = $val;
|
||||
$val3 =~ s/=/ =/;
|
||||
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val])));
|
||||
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val2])));
|
||||
ok(!run(app(["openssl", "req", "-new", "-addext", $val, "-addext", $val3])));
|
||||
ok(!run(app(["openssl", "req", "-new", "-addext", $val2, "-addext", $val3])));
|
||||
ok( run(app([@addext_args, "-addext", $val])));
|
||||
ok(!run(app([@addext_args, "-addext", $val, "-addext", $val])));
|
||||
ok(!run(app([@addext_args, "-addext", $val, "-addext", $val2])));
|
||||
ok(!run(app([@addext_args, "-addext", $val, "-addext", $val3])));
|
||||
ok(!run(app([@addext_args, "-addext", $val2, "-addext", $val3])));
|
||||
|
||||
subtest "generating certificate requests" => sub {
|
||||
my @req_new;
|
||||
if (disabled("rsa")) {
|
||||
@req_new = ("-newkey", "dsa:".srctop_file("apps", "dsa512.pem"));
|
||||
} else {
|
||||
@req_new = ("-new");
|
||||
note("There should be a 2 sequences of .'s and some +'s.");
|
||||
note("There should not be more that at most 80 per line");
|
||||
}
|
||||
|
||||
plan tests => 2;
|
||||
|
||||
ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"),
|
||||
|
||||
@@ -18436,3 +18436,41 @@ Ctrl = digest:SM3
|
||||
Input = D7AD397F6FFA5D4F7F11E7217F241607DC30618C236D2C09C1B9EA8FDADEE2E8
|
||||
Output = 3045022100f11bf36e75bb304f094fb42a4ca22377d0cc768637c5011cd59fb9ed4b130c98022035545ffe2c2efb3abee4fee661468946d886004fae8ea5311593e48f7fe21b91
|
||||
Result = KEYOP_MISMATCH
|
||||
|
||||
Title = Chosen Wycheproof vectors
|
||||
|
||||
PrivateKeyRaw = WychePRIVATE0:X25519:288796bc5aff4b81a37501757bc0753a3c21964790d38699308debc17a6eaf8d
|
||||
|
||||
PublicKeyRaw = WychePUBLIC0:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
|
||||
|
||||
Derive=WychePRIVATE0
|
||||
PeerKey=WychePUBLIC0
|
||||
SharedSecret=b4e0dd76da7b071728b61f856771aa356e57eda78a5b1655cc3820fb5f854c5c
|
||||
|
||||
PrivateKeyRaw = WychePRIVATE1:X25519:60887b3dc72443026ebedbbbb70665f42b87add1440e7768fbd7e8e2ce5f639d
|
||||
|
||||
PublicKeyRaw = WychePUBLIC1:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
|
||||
Derive=WychePRIVATE1
|
||||
PeerKey=WychePUBLIC1
|
||||
SharedSecret=38d6304c4a7e6d9f7959334fb5245bd2c754525d4c91db950206926234c1f633
|
||||
|
||||
PrivateKeyRaw = WychePRIVATE2:X25519:a0a4f130b98a5be4b1cedb7cb85584a3520e142d474dc9ccb909a073a976bf63
|
||||
|
||||
PublicKeyRaw = WychePUBLIC2:X25519:0ab4e76380d84dde4f6833c58f2a9fb8f83bb0169b172be4b6e0592887741a36
|
||||
|
||||
Derive=WychePRIVATE2
|
||||
PeerKey=WychePUBLIC2
|
||||
SharedSecret=0200000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
PublicKeyRaw = WychePUBLIC3:X25519:89e10d5701b4337d2d032181538b1064bd4084401ceca1fd12663a1959388000
|
||||
|
||||
Derive=WychePRIVATE2
|
||||
PeerKey=WychePUBLIC3
|
||||
SharedSecret=0900000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
PublicKeyRaw = WychePUBLIC4:X25519:2b55d3aa4a8f80c8c0b2ae5f933e85af49beac36c2fa7394bab76c8933f8f81d
|
||||
|
||||
Derive=WychePRIVATE2
|
||||
PeerKey=WychePUBLIC4
|
||||
SharedSecret=1000000000000000000000000000000000000000000000000000000000000000
|
||||
@@ -53,12 +53,12 @@ use constant {
|
||||
|
||||
#Test 1: Default sig algs should succeed
|
||||
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
||||
plan tests => 21;
|
||||
plan tests => 22;
|
||||
ok(TLSProxy::Message->success, "Default sigalgs");
|
||||
my $testtype;
|
||||
|
||||
SKIP: {
|
||||
skip "TLSv1.3 disabled", 5 if disabled("tls1_3");
|
||||
skip "TLSv1.3 disabled", 6 if disabled("tls1_3");
|
||||
|
||||
$proxy->filter(\&sigalgs_filter);
|
||||
|
||||
@@ -94,12 +94,21 @@ SKIP: {
|
||||
$testtype = PSS_ONLY_SIG_ALGS;
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.3");
|
||||
|
||||
#Test 7: Modify the CertificateVerify sigalg from rsa_pss_rsae_sha256 to
|
||||
# rsa_pss_pss_sha256. This should fail because the public key OID
|
||||
# in the certificate is rsaEncryption and not rsassaPss
|
||||
$proxy->filter(\&modify_cert_verify_sigalg);
|
||||
$proxy->clear();
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->fail,
|
||||
"Mismatch between CertVerify sigalg and public key OID");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip "EC or TLSv1.3 disabled", 1
|
||||
if disabled("tls1_3") || disabled("ec");
|
||||
#Test 7: Sending a valid sig algs list but not including a sig type that
|
||||
#Test 8: Sending a valid sig algs list but not including a sig type that
|
||||
# matches the certificate should fail in TLSv1.3.
|
||||
$proxy->clear();
|
||||
$proxy->clientflags("-sigalgs ECDSA+SHA256");
|
||||
@@ -112,7 +121,7 @@ SKIP: {
|
||||
skip "EC, TLSv1.3 or TLSv1.2 disabled", 1
|
||||
if disabled("tls1_2") || disabled("tls1_3") || disabled("ec");
|
||||
|
||||
#Test 8: Sending a full list of TLSv1.3 sig algs but negotiating TLSv1.2
|
||||
#Test 9: Sending a full list of TLSv1.3 sig algs but negotiating TLSv1.2
|
||||
# should succeed
|
||||
$proxy->clear();
|
||||
$proxy->serverflags("-no_tls1_3");
|
||||
@@ -127,7 +136,7 @@ SKIP: {
|
||||
|
||||
$proxy->filter(\&sigalgs_filter);
|
||||
|
||||
#Test 9: Sending no sig algs extension in TLSv1.2 should succeed
|
||||
#Test 10: Sending no sig algs extension in TLSv1.2 should succeed
|
||||
$proxy->clear();
|
||||
$testtype = NO_SIG_ALGS_EXT;
|
||||
$proxy->clientflags("-no_tls1_3");
|
||||
@@ -135,7 +144,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "No TLSv1.2 sigalgs");
|
||||
|
||||
#Test 10: Sending an empty sig algs extension in TLSv1.2 should fail
|
||||
#Test 11: Sending an empty sig algs extension in TLSv1.2 should fail
|
||||
$proxy->clear();
|
||||
$testtype = EMPTY_SIG_ALGS_EXT;
|
||||
$proxy->clientflags("-no_tls1_3");
|
||||
@@ -143,7 +152,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->fail, "Empty TLSv1.2 sigalgs");
|
||||
|
||||
#Test 11: Sending a list with no recognised sig algs in TLSv1.2 should fail
|
||||
#Test 12: Sending a list with no recognised sig algs in TLSv1.2 should fail
|
||||
$proxy->clear();
|
||||
$testtype = NO_KNOWN_SIG_ALGS;
|
||||
$proxy->clientflags("-no_tls1_3");
|
||||
@@ -151,7 +160,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->fail, "No known TLSv1.3 sigalgs");
|
||||
|
||||
#Test 12: Sending a sig algs list without pss for an RSA cert in TLSv1.2
|
||||
#Test 13: Sending a sig algs list without pss for an RSA cert in TLSv1.2
|
||||
# should succeed
|
||||
$proxy->clear();
|
||||
$testtype = NO_PSS_SIG_ALGS;
|
||||
@@ -160,7 +169,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "No PSS TLSv1.2 sigalgs");
|
||||
|
||||
#Test 13: Sending only TLSv1.3 PSS sig algs in TLSv1.2 should succeed
|
||||
#Test 14: Sending only TLSv1.3 PSS sig algs in TLSv1.2 should succeed
|
||||
$proxy->clear();
|
||||
$testtype = PSS_ONLY_SIG_ALGS;
|
||||
$proxy->serverflags("-no_tls1_3");
|
||||
@@ -168,7 +177,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "PSS only sigalgs in TLSv1.2");
|
||||
|
||||
#Test 14: Responding with a sig alg we did not send in TLSv1.2 should fail
|
||||
#Test 15: Responding with a sig alg we did not send in TLSv1.2 should fail
|
||||
# We send rsa_pkcs1_sha256 and respond with rsa_pss_rsae_sha256
|
||||
# TODO(TLS1.3): Add a similar test to the TLSv1.3 section above
|
||||
# when we have an API capable of configuring the TLSv1.3 sig algs
|
||||
@@ -179,7 +188,7 @@ SKIP: {
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->fail, "Sigalg we did not send in TLSv1.2");
|
||||
|
||||
#Test 15: Sending a valid sig algs list but not including a sig type that
|
||||
#Test 16: Sending a valid sig algs list but not including a sig type that
|
||||
# matches the certificate should fail in TLSv1.2
|
||||
$proxy->clear();
|
||||
$proxy->clientflags("-no_tls1_3 -sigalgs ECDSA+SHA256");
|
||||
@@ -189,7 +198,7 @@ SKIP: {
|
||||
ok(TLSProxy::Message->fail, "No matching TLSv1.2 sigalgs");
|
||||
$proxy->filter(\&sigalgs_filter);
|
||||
|
||||
#Test 16: No sig algs extension, ECDSA cert, TLSv1.2 should succeed
|
||||
#Test 17: No sig algs extension, ECDSA cert, TLSv1.2 should succeed
|
||||
$proxy->clear();
|
||||
$testtype = NO_SIG_ALGS_EXT;
|
||||
$proxy->clientflags("-no_tls1_3");
|
||||
@@ -205,7 +214,7 @@ SKIP: {
|
||||
my ($dsa_status, $sha1_status, $sha224_status);
|
||||
SKIP: {
|
||||
skip "TLSv1.3 disabled", 2 if disabled("tls1_3") || disabled("dsa");
|
||||
#Test 17: signature_algorithms with 1.3-only ClientHello
|
||||
#Test 18: signature_algorithms with 1.3-only ClientHello
|
||||
$testtype = PURE_SIGALGS;
|
||||
$dsa_status = $sha1_status = $sha224_status = 0;
|
||||
$proxy->clear();
|
||||
@@ -215,7 +224,7 @@ SKIP: {
|
||||
ok($dsa_status && $sha1_status && $sha224_status,
|
||||
"DSA/SHA2 sigalg sent for 1.3-only ClientHello");
|
||||
|
||||
#Test 18: signature_algorithms with backwards compatible ClientHello
|
||||
#Test 19: signature_algorithms with backwards compatible ClientHello
|
||||
SKIP: {
|
||||
skip "TLSv1.2 disabled", 1 if disabled("tls1_2");
|
||||
$testtype = COMPAT_SIGALGS;
|
||||
@@ -230,21 +239,21 @@ SKIP: {
|
||||
|
||||
SKIP: {
|
||||
skip "TLSv1.3 disabled", 3 if disabled("tls1_3");
|
||||
#Test 19: Insert signature_algorithms_cert that match normal sigalgs
|
||||
#Test 20: Insert signature_algorithms_cert that match normal sigalgs
|
||||
$testtype = SIGALGS_CERT_ALL;
|
||||
$proxy->clear();
|
||||
$proxy->filter(\&modify_sigalgs_cert_filter);
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3");
|
||||
|
||||
#Test 19: Insert signature_algorithms_cert that forces PKCS#1 cert
|
||||
#Test 21: Insert signature_algorithms_cert that forces PKCS#1 cert
|
||||
$testtype = SIGALGS_CERT_PKCS;
|
||||
$proxy->clear();
|
||||
$proxy->filter(\&modify_sigalgs_cert_filter);
|
||||
$proxy->start();
|
||||
ok(TLSProxy::Message->success, "sigalgs_cert in TLSv1.3 with PKCS#1 cert");
|
||||
|
||||
#Test 19: Insert signature_algorithms_cert that fails
|
||||
#Test 22: Insert signature_algorithms_cert that fails
|
||||
$testtype = SIGALGS_CERT_INVALID;
|
||||
$proxy->clear();
|
||||
$proxy->filter(\&modify_sigalgs_cert_filter);
|
||||
@@ -380,3 +389,20 @@ sub modify_sigalgs_cert_filter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub modify_cert_verify_sigalg
|
||||
{
|
||||
my $proxy = shift;
|
||||
|
||||
# We're only interested in the CertificateVerify
|
||||
if ($proxy->flight != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach my $message (@{$proxy->message_list}) {
|
||||
if ($message->mt == TLSProxy::Message::MT_CERTIFICATE_VERIFY) {
|
||||
$message->sigalg(TLSProxy::Message::SIG_ALG_RSA_PSS_PSS_SHA256);
|
||||
$message->repack();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
use OpenSSL::Test::Utils;
|
||||
use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||
|
||||
setup("test_gost");
|
||||
|
||||
# The GOST ciphers are dynamically loaded via the GOST engine, so we must be
|
||||
# able to support that. The engine also uses DSA and CMS symbols, so we skip
|
||||
# this test on no-dsa or no-cms.
|
||||
plan skip_all => "GOST support is disabled in this OpenSSL build"
|
||||
if disabled("gost") || disabled("engine") || disabled("dynamic-engine")
|
||||
|| disabled("dsa") || disabled("cms");
|
||||
|
||||
plan skip_all => "TLSv1.3 or TLSv1.2 are disabled in this OpenSSL build"
|
||||
if disabled("tls1_3") || disabled("tls1_2");
|
||||
|
||||
plan skip_all => "No test GOST engine found"
|
||||
if !$ENV{OPENSSL_GOST_ENGINE_SO};
|
||||
|
||||
plan tests => 1;
|
||||
|
||||
$ENV{OPENSSL_CONF} = srctop_file("test", "recipes", "90-test_gost_data",
|
||||
"gost.conf");
|
||||
|
||||
ok(run(test(["gosttest",
|
||||
srctop_file("test", "recipes", "90-test_gost_data",
|
||||
"server-cert2001.pem"),
|
||||
srctop_file("test", "recipes", "90-test_gost_data",
|
||||
"server-key2001.pem"),
|
||||
srctop_file("test", "recipes", "90-test_gost_data",
|
||||
"server-cert2012.pem"),
|
||||
srctop_file("test", "recipes", "90-test_gost_data",
|
||||
"server-key2012.pem")])),
|
||||
"running gosttest");
|
||||
@@ -0,0 +1,13 @@
|
||||
openssl_conf = openssl_def
|
||||
[openssl_def]
|
||||
engines = engine_section
|
||||
|
||||
[engine_section]
|
||||
gost = gost_section
|
||||
|
||||
[gost_section]
|
||||
engine_id = gost
|
||||
dynamic_path = $ENV::OPENSSL_GOST_ENGINE_SO
|
||||
default_algorithms = ALL
|
||||
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB4jCCAY+gAwIBAgIUNKO10+LkPoYGkOqNJ2wv1YI8RpQwCgYGKoUDAgIDBQAw
|
||||
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
|
||||
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xODA3MTMxNTAzMDFaFw0yODA3MTAx
|
||||
NTAzMDFaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
|
||||
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwYzAcBgYqhQMCAhMwEgYHKoUD
|
||||
AgIjAQYHKoUDAgIeAQNDAARAyDUhXsZP1JSLkvZ3xaU4aHXxAGKDwpawJ89+3B+N
|
||||
lD7FS48QUIeoQrv9hn1B/kVuVxJwU4CeZRQohLvc5IkzJ6NTMFEwHQYDVR0OBBYE
|
||||
FEz6BbScOOWYqklNGMTbyikZG/cRMB8GA1UdIwQYMBaAFEz6BbScOOWYqklNGMTb
|
||||
yikZG/cRMA8GA1UdEwEB/wQFMAMBAf8wCgYGKoUDAgIDBQADQQAbkdWo441FqSbB
|
||||
13JTW498NOzHZn69wnjYsOmMHLCdEHBTHVCa/g1wHPc4CyYk4UfMRWz5awzb6zNB
|
||||
TncjMl2a
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB6TCCAZSgAwIBAgIUVF/ajykAyHqQm1n6K1JdMFX/O6owDAYIKoUDBwEBAwIF
|
||||
ADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwY
|
||||
SW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE4MDcxMzE0MzcxNVoXDTI4MDcx
|
||||
MDE0MzcxNVowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf
|
||||
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBmMB8GCCqFAwcBAQEBMBMG
|
||||
ByqFAwICIwEGCCqFAwcBAQICA0MABEDIj2JgFybRexBIdkG7bI//Z8woXbpC/hpg
|
||||
62qflBE/dHnWVnbzpJUVeSd5sAkP7Ta0qrrs5YdW4MBIM/VPbDVOo1MwUTAdBgNV
|
||||
HQ4EFgQUFZtRh6plQ3nHf1A+7ayjYw9B1X0wHwYDVR0jBBgwFoAUFZtRh6plQ3nH
|
||||
f1A+7ayjYw9B1X0wDwYDVR0TAQH/BAUwAwEB/zAMBggqhQMHAQEDAgUAA0EAMttA
|
||||
fMPa3YFO9db/xIS9wMB7ntbtibeZEJlngaPu5gvfdNmCY0uzjY2c3yPr9dDq84j7
|
||||
gSqY1VwVBLuKrpLC+w==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MEMCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIJgoLqJR/05zND0f
|
||||
8Wnma1MFMxE7ezisZhkS/DL4DXb6
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MEYCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEILemtIak5CeX
|
||||
Jd75HfVqAMi1MfhxW7kGvGDj8l1/nF45
|
||||
-----END PRIVATE KEY-----
|
||||
+204
-49
@@ -1233,11 +1233,92 @@ static int post_handshake_verify(SSL *sssl, SSL *cssl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_tickets(int idx)
|
||||
static int setup_ticket_test(int stateful, int idx, SSL_CTX **sctx,
|
||||
SSL_CTX **cctx)
|
||||
{
|
||||
int sess_id_ctx = 1;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
|
||||
TLS1_VERSION, TLS_MAX_VERSION, sctx,
|
||||
cctx, cert, privkey))
|
||||
|| !TEST_true(SSL_CTX_set_num_tickets(*sctx, idx))
|
||||
|| !TEST_true(SSL_CTX_set_session_id_context(*sctx,
|
||||
(void *)&sess_id_ctx,
|
||||
sizeof(sess_id_ctx))))
|
||||
return 0;
|
||||
|
||||
if (stateful)
|
||||
SSL_CTX_set_options(*sctx, SSL_OP_NO_TICKET);
|
||||
|
||||
SSL_CTX_set_session_cache_mode(*cctx, SSL_SESS_CACHE_CLIENT
|
||||
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
|
||||
SSL_CTX_sess_set_new_cb(*cctx, new_cachesession_cb);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_resumption(int idx, SSL_CTX *sctx, SSL_CTX *cctx, int succ)
|
||||
{
|
||||
SSL *serverssl = NULL, *clientssl = NULL;
|
||||
int i;
|
||||
|
||||
/* Test that we can resume with all the tickets we got given */
|
||||
for (i = 0; i < idx * 2; i++) {
|
||||
new_called = 0;
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
|
||||
&clientssl, NULL, NULL))
|
||||
|| !TEST_true(SSL_set_session(clientssl, sesscache[i])))
|
||||
goto end;
|
||||
|
||||
SSL_force_post_handshake_auth(clientssl);
|
||||
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Following a successful resumption we only get 1 ticket. After a
|
||||
* failed one we should get idx tickets.
|
||||
*/
|
||||
if (succ) {
|
||||
if (!TEST_true(SSL_session_reused(clientssl))
|
||||
|| !TEST_int_eq(new_called, 1))
|
||||
goto end;
|
||||
} else {
|
||||
if (!TEST_false(SSL_session_reused(clientssl))
|
||||
|| !TEST_int_eq(new_called, idx))
|
||||
goto end;
|
||||
}
|
||||
|
||||
new_called = 0;
|
||||
/* After a post-handshake authentication we should get 1 new ticket */
|
||||
if (succ
|
||||
&& (!post_handshake_verify(serverssl, clientssl)
|
||||
|| !TEST_int_eq(new_called, 1)))
|
||||
goto end;
|
||||
|
||||
SSL_shutdown(clientssl);
|
||||
SSL_shutdown(serverssl);
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
serverssl = clientssl = NULL;
|
||||
SSL_SESSION_free(sesscache[i]);
|
||||
sesscache[i] = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
end:
|
||||
SSL_free(clientssl);
|
||||
SSL_free(serverssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_tickets(int stateful, int idx)
|
||||
{
|
||||
SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||
SSL *serverssl = NULL, *clientssl = NULL;
|
||||
int testresult = 0, i;
|
||||
int testresult = 0;
|
||||
size_t j;
|
||||
|
||||
/* idx is the test number, but also the number of tickets we want */
|
||||
@@ -1245,15 +1326,52 @@ static int test_tickets(int idx)
|
||||
new_called = 0;
|
||||
do_cache = 1;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
|
||||
TLS1_VERSION, TLS_MAX_VERSION, &sctx,
|
||||
&cctx, cert, privkey))
|
||||
|| !TEST_true(SSL_CTX_set_num_tickets(sctx, idx)))
|
||||
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
|
||||
goto end;
|
||||
|
||||
SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT
|
||||
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
|
||||
SSL_CTX_sess_set_new_cb(cctx, new_cachesession_cb);
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
|
||||
&clientssl, NULL, NULL)))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE))
|
||||
/* Check we got the number of tickets we were expecting */
|
||||
|| !TEST_int_eq(idx, new_called))
|
||||
goto end;
|
||||
|
||||
SSL_shutdown(clientssl);
|
||||
SSL_shutdown(serverssl);
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
clientssl = serverssl = NULL;
|
||||
sctx = cctx = NULL;
|
||||
|
||||
/*
|
||||
* Now we try to resume with the tickets we previously created. The
|
||||
* resumption attempt is expected to fail (because we're now using a new
|
||||
* SSL_CTX). We should see idx number of tickets issued again.
|
||||
*/
|
||||
|
||||
/* Stop caching sessions - just count them */
|
||||
do_cache = 0;
|
||||
|
||||
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
|
||||
goto end;
|
||||
|
||||
if (!check_resumption(idx, sctx, cctx, 0))
|
||||
goto end;
|
||||
|
||||
/* Start again with caching sessions */
|
||||
new_called = 0;
|
||||
do_cache = 1;
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
sctx = cctx = NULL;
|
||||
|
||||
if (!setup_ticket_test(stateful, idx, &sctx, &cctx))
|
||||
goto end;
|
||||
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
|
||||
&clientssl, NULL, NULL)))
|
||||
@@ -1281,37 +1399,12 @@ static int test_tickets(int idx)
|
||||
/* Stop caching sessions - just count them */
|
||||
do_cache = 0;
|
||||
|
||||
/* Test that we can resume with all the tickets we got given */
|
||||
for (i = 0; i < idx * 2; i++) {
|
||||
new_called = 0;
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
|
||||
&clientssl, NULL, NULL))
|
||||
|| !TEST_true(SSL_set_session(clientssl, sesscache[i])))
|
||||
goto end;
|
||||
|
||||
SSL_force_post_handshake_auth(clientssl);
|
||||
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE))
|
||||
|| !TEST_true(SSL_session_reused(clientssl))
|
||||
/* Following a resumption we only get 1 ticket */
|
||||
|| !TEST_int_eq(new_called, 1))
|
||||
goto end;
|
||||
|
||||
new_called = 0;
|
||||
/* After a post-handshake authentication we should get 1 new ticket */
|
||||
if (!post_handshake_verify(serverssl, clientssl)
|
||||
|| !TEST_int_eq(new_called, 1))
|
||||
goto end;
|
||||
|
||||
SSL_shutdown(clientssl);
|
||||
SSL_shutdown(serverssl);
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
serverssl = clientssl = NULL;
|
||||
SSL_SESSION_free(sesscache[i]);
|
||||
sesscache[i] = NULL;
|
||||
}
|
||||
/*
|
||||
* Check we can resume with all the tickets we created. This time around the
|
||||
* resumptions should all be successful.
|
||||
*/
|
||||
if (!check_resumption(idx, sctx, cctx, 1))
|
||||
goto end;
|
||||
|
||||
testresult = 1;
|
||||
|
||||
@@ -1327,6 +1420,16 @@ static int test_tickets(int idx)
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
static int test_stateless_tickets(int idx)
|
||||
{
|
||||
return test_tickets(0, idx);
|
||||
}
|
||||
|
||||
static int test_stateful_tickets(int idx)
|
||||
{
|
||||
return test_tickets(1, idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define USE_NULL 0
|
||||
@@ -2316,7 +2419,8 @@ static int test_early_data_replay(int idx)
|
||||
* handle a connection from a client where the early data should be skipped.
|
||||
* testtype: 0 == No HRR
|
||||
* testtype: 1 == HRR
|
||||
* testtype: 2 == recv_max_early_data set to 0
|
||||
* testtype: 2 == HRR, invalid early_data sent after HRR
|
||||
* testtype: 3 == recv_max_early_data set to 0
|
||||
*/
|
||||
static int early_data_skip_helper(int testtype, int idx)
|
||||
{
|
||||
@@ -2331,7 +2435,7 @@ static int early_data_skip_helper(int testtype, int idx)
|
||||
&serverssl, &sess, idx)))
|
||||
goto end;
|
||||
|
||||
if (testtype == 1) {
|
||||
if (testtype == 1 || testtype == 2) {
|
||||
/* Force an HRR to occur */
|
||||
if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256")))
|
||||
goto end;
|
||||
@@ -2351,7 +2455,7 @@ static int early_data_skip_helper(int testtype, int idx)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (testtype == 2
|
||||
if (testtype == 3
|
||||
&& !TEST_true(SSL_set_recv_max_early_data(serverssl, 0)))
|
||||
goto end;
|
||||
|
||||
@@ -2370,7 +2474,12 @@ static int early_data_skip_helper(int testtype, int idx)
|
||||
SSL_EARLY_DATA_REJECTED))
|
||||
goto end;
|
||||
|
||||
if (testtype == 1) {
|
||||
switch (testtype) {
|
||||
case 0:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/*
|
||||
* Finish off the handshake. We perform the same writes and reads as
|
||||
* further down but we expect them to fail due to the incomplete
|
||||
@@ -2380,10 +2489,40 @@ static int early_data_skip_helper(int testtype, int idx)
|
||||
|| !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
|
||||
&readbytes)))
|
||||
goto end;
|
||||
} else if (testtype == 2) {
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
BIO *wbio = SSL_get_wbio(clientssl);
|
||||
/* A record that will appear as bad early_data */
|
||||
const unsigned char bad_early_data[] = {
|
||||
0x17, 0x03, 0x03, 0x00, 0x01, 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* We force the client to attempt a write. This will fail because
|
||||
* we're still in the handshake. It will cause the second
|
||||
* ClientHello to be sent.
|
||||
*/
|
||||
if (!TEST_false(SSL_write_ex(clientssl, MSG2, strlen(MSG2),
|
||||
&written)))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Inject some early_data after the second ClientHello. This should
|
||||
* cause the server to fail
|
||||
*/
|
||||
if (!TEST_true(BIO_write_ex(wbio, bad_early_data,
|
||||
sizeof(bad_early_data), &written)))
|
||||
goto end;
|
||||
}
|
||||
/* fallthrough */
|
||||
|
||||
case 3:
|
||||
/*
|
||||
* This client has sent more early_data than we are willing to skip so
|
||||
* the connection should abort.
|
||||
* This client has sent more early_data than we are willing to skip
|
||||
* (case 3) or sent invalid early_data (case 2) so the connection should
|
||||
* abort.
|
||||
*/
|
||||
if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))
|
||||
|| !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL))
|
||||
@@ -2392,6 +2531,10 @@ static int early_data_skip_helper(int testtype, int idx)
|
||||
/* Connection has failed - nothing more to do */
|
||||
testresult = 1;
|
||||
goto end;
|
||||
|
||||
default:
|
||||
TEST_error("Invalid test type");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2438,13 +2581,23 @@ static int test_early_data_skip_hrr(int idx)
|
||||
return early_data_skip_helper(1, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that a server attempting to read early data can handle a connection
|
||||
* from a client where an HRR occurs and correctly fails if early_data is sent
|
||||
* after the HRR
|
||||
*/
|
||||
static int test_early_data_skip_hrr_fail(int idx)
|
||||
{
|
||||
return early_data_skip_helper(2, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that a server attempting to read early data will abort if it tries to
|
||||
* skip over too much.
|
||||
*/
|
||||
static int test_early_data_skip_abort(int idx)
|
||||
{
|
||||
return early_data_skip_helper(2, idx);
|
||||
return early_data_skip_helper(3, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5272,7 +5425,8 @@ int setup_tests(void)
|
||||
ADD_TEST(test_session_with_only_ext_cache);
|
||||
ADD_TEST(test_session_with_both_cache);
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
ADD_ALL_TESTS(test_tickets, 3);
|
||||
ADD_ALL_TESTS(test_stateful_tickets, 3);
|
||||
ADD_ALL_TESTS(test_stateless_tickets, 3);
|
||||
#endif
|
||||
ADD_ALL_TESTS(test_ssl_set_bio, TOTAL_SSL_SET_BIO_TESTS);
|
||||
ADD_TEST(test_ssl_bio_pop_next_bio);
|
||||
@@ -5298,6 +5452,7 @@ int setup_tests(void)
|
||||
ADD_ALL_TESTS(test_early_data_replay, 2);
|
||||
ADD_ALL_TESTS(test_early_data_skip, 3);
|
||||
ADD_ALL_TESTS(test_early_data_skip_hrr, 3);
|
||||
ADD_ALL_TESTS(test_early_data_skip_hrr_fail, 3);
|
||||
ADD_ALL_TESTS(test_early_data_skip_abort, 3);
|
||||
ADD_ALL_TESTS(test_early_data_not_sent, 3);
|
||||
ADD_ALL_TESTS(test_early_data_psk, 8);
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ package OpenSSL::Template;
|
||||
use File::Basename;
|
||||
use File::Spec::Functions;
|
||||
use lib "$FindBin::Bin/perl";
|
||||
use with_fallback qw(Text::Template);
|
||||
use with_fallback "Text::Template 1.46";
|
||||
|
||||
#use parent qw/Text::Template/;
|
||||
use vars qw/@ISA/;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Std;
|
||||
|
||||
our $opt_n = 0;
|
||||
|
||||
getopts('n') or die "Invalid option: $!\n";
|
||||
|
||||
print join(' ', @ARGV);
|
||||
print "\n" unless $opt_n;
|
||||
@@ -103,11 +103,14 @@ use constant {
|
||||
SIG_ALG_ECDSA_SECP256R1_SHA256 => 0x0403,
|
||||
SIG_ALG_ECDSA_SECP384R1_SHA384 => 0x0503,
|
||||
SIG_ALG_ECDSA_SECP521R1_SHA512 => 0x0603,
|
||||
SIG_ALG_RSA_PSS_SHA256 => 0x0804,
|
||||
SIG_ALG_RSA_PSS_SHA384 => 0x0805,
|
||||
SIG_ALG_RSA_PSS_SHA512 => 0x0806,
|
||||
SIG_ALG_RSA_PSS_RSAE_SHA256 => 0x0804,
|
||||
SIG_ALG_RSA_PSS_RSAE_SHA384 => 0x0805,
|
||||
SIG_ALG_RSA_PSS_RSAE_SHA512 => 0x0806,
|
||||
SIG_ALG_ED25519 => 0x0807,
|
||||
SIG_ALG_ED448 => 0x0808,
|
||||
SIG_ALG_RSA_PSS_PSS_SHA256 => 0x0809,
|
||||
SIG_ALG_RSA_PSS_PSS_SHA384 => 0x080a,
|
||||
SIG_ALG_RSA_PSS_PSS_SHA512 => 0x080b,
|
||||
SIG_ALG_RSA_PKCS1_SHA1 => 0x0201,
|
||||
SIG_ALG_ECDSA_SHA1 => 0x0203,
|
||||
SIG_ALG_DSA_SHA1 => 0x0202,
|
||||
|
||||
@@ -8,15 +8,17 @@
|
||||
package with_fallback;
|
||||
|
||||
sub import {
|
||||
shift;
|
||||
|
||||
use File::Basename;
|
||||
use File::Spec::Functions;
|
||||
foreach (@_) {
|
||||
eval "require $_";
|
||||
eval "use $_";
|
||||
if ($@) {
|
||||
unshift @INC, catdir(dirname(__FILE__),
|
||||
"..", "..", "external", "perl");
|
||||
my $transfer = "transfer::$_";
|
||||
eval "require $transfer";
|
||||
eval "use $transfer";
|
||||
shift @INC;
|
||||
warn $@ if $@;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user