From 46f6b5e2febd6c7d3e834fec3a11613ddc04628a Mon Sep 17 00:00:00 2001 From: Hakase Date: Thu, 19 Jul 2018 21:47:35 +0900 Subject: [PATCH] Update pre9 --- AUTHORS | 56 +-- CHANGES | 27 +- Configurations/descrip.mms.tmpl | 2 +- Configurations/unix-Makefile.tmpl | 2 +- Configurations/windows-makefile.tmpl | 86 ++--- Configure | 11 +- apps/req.c | 26 +- apps/speed.c | 22 +- crypto/bn/bn_div.c | 1 + crypto/bn/bn_exp.c | 47 +-- crypto/bn/bn_lcl.h | 21 +- crypto/bn/bn_lib.c | 48 +-- crypto/bn/bn_mod.c | 66 +++- crypto/bn/bn_mont.c | 63 ++-- crypto/bn/bn_nist.c | 2 +- crypto/bn/bn_sqr.c | 10 +- crypto/conf/conf_err.c | 1 + crypto/conf/conf_lib.c | 46 ++- crypto/ec/asm/x25519-x86_64.pl | 320 ++++++++++++++++- crypto/ec/curve25519.c | 293 ++++++++-------- crypto/ec/ec2_smpl.c | 328 +++++++++++++++--- crypto/ec/ec_err.c | 21 +- crypto/ec/ec_lcl.h | 81 +++++ crypto/ec/ec_lib.c | 35 +- crypto/ec/ec_mult.c | 195 ++++++----- crypto/ec/ecdsa_ossl.c | 131 ++----- crypto/ec/ecp_mont.c | 5 +- crypto/ec/ecp_nist.c | 5 +- crypto/ec/ecp_nistp224.c | 10 +- crypto/ec/ecp_nistp256.c | 12 +- crypto/ec/ecp_nistp521.c | 10 +- crypto/ec/ecp_nistz256.c | 29 +- crypto/ec/ecp_smpl.c | 6 +- crypto/engine/eng_devcrypto.c | 10 +- crypto/err/openssl.txt | 11 + crypto/evp/e_aes.c | 40 ++- crypto/include/internal/bn_int.h | 14 + crypto/include/internal/sm2err.h | 3 + crypto/modes/ocb128.c | 22 +- crypto/poly1305/asm/poly1305-x86_64.pl | 77 ++-- crypto/rsa/rsa_oaep.c | 38 +- crypto/rsa/rsa_ossl.c | 38 +- crypto/rsa/rsa_pk1.c | 39 ++- crypto/rsa/rsa_ssl.c | 8 + doc/man3/BIO_should_retry.pod | 10 +- doc/man3/BN_bn2bin.pod | 4 +- doc/man3/SSL_CTX_set_mode.pod | 38 +- doc/man3/SSL_CTX_set_read_ahead.pod | 18 +- doc/man3/SSL_get_error.pod | 41 ++- doc/man3/SSL_read.pod | 53 +-- doc/man3/SSL_write.pod | 17 +- external/perl/transfer/Text/Template.pm | 3 + fuzz/client.c | 1 + fuzz/server.c | 7 +- include/internal/dsoerr.h | 3 + include/openssl/conferr.h | 1 + include/openssl/ecerr.h | 16 +- include/openssl/opensslconf.h.in | 10 +- ssl/ssl_cert.c | 31 +- ssl/ssl_locl.h | 4 +- ssl/statem/extensions_srvr.c | 3 +- ssl/statem/statem.c | 4 +- ssl/statem/statem_clnt.c | 2 +- ssl/statem/statem_lib.c | 68 ++-- ssl/statem/statem_srvr.c | 9 - ssl/t1_lib.c | 51 ++- test/build.info | 6 +- test/conf_include_test.c | 26 ++ test/ectest.c | 13 +- test/gosttest.c | 91 +++++ test/recipes/25-test_req.t | 34 +- test/recipes/30-test_evp_data/evppkey.txt | 38 ++ test/recipes/70-test_sslsigalgs.t | 60 +++- test/recipes/90-test_gost.t | 41 +++ test/recipes/90-test_gost_data/gost.conf | 13 + .../90-test_gost_data/server-cert2001.pem | 13 + .../90-test_gost_data/server-cert2012.pem | 13 + .../90-test_gost_data/server-key2001.pem | 4 + .../90-test_gost_data/server-key2012.pem | 4 + test/sslapitest.c | 253 +++++++++++--- util/dofile.pl | 2 +- util/echo.pl | 12 + util/perl/TLSProxy/Message.pm | 9 +- util/perl/with_fallback.pm | 6 +- 84 files changed, 2388 insertions(+), 962 deletions(-) create mode 100644 test/gosttest.c create mode 100644 test/recipes/90-test_gost.t create mode 100644 test/recipes/90-test_gost_data/gost.conf create mode 100644 test/recipes/90-test_gost_data/server-cert2001.pem create mode 100644 test/recipes/90-test_gost_data/server-cert2012.pem create mode 100644 test/recipes/90-test_gost_data/server-key2001.pem create mode 100644 test/recipes/90-test_gost_data/server-key2012.pem create mode 100644 util/echo.pl diff --git a/AUTHORS b/AUTHORS index 48211a27..ac93b2e7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -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 diff --git a/CHANGES b/CHANGES index 2eb90a92..ae59f922 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/Configurations/descrip.mms.tmpl b/Configurations/descrip.mms.tmpl index 70e566ef..0c2695d2 100644 --- a/Configurations/descrip.mms.tmpl +++ b/Configurations/descrip.mms.tmpl @@ -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}}) -} diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index 8d33e843..2423ad28 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -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}}) -} diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index 11acdf00..76efa410 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -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}}); } } } diff --git a/Configure b/Configure index 05b798bc..1b4e1d23 100755 --- a/Configure +++ b/Configure @@ -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); diff --git a/apps/req.c b/apps/req.c index 3d89f200..48f3a3ab 100644 --- a/apps/req.c +++ b/apps/req.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #ifndef OPENSSL_NO_RSA # include @@ -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); diff --git a/apps/speed.c b/apps/speed.c index 181873cc..2c792bd1 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -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; } diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c index b9b85fda..464a4446 100644 --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -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 */ diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 10d3912c..4e24c94a 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -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 */ diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h index f57c87d9..d74b5908 100644 --- a/crypto/bn/bn_lcl.h +++ b/crypto/bn/bn_lcl.h @@ -141,7 +141,16 @@ */ # ifdef BN_DEBUG -# include +/* + * 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) */ diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 5bb996e5..df6ea695 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -12,6 +12,7 @@ #include "internal/cryptlib.h" #include "bn_lcl.h" #include +#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); } diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c index 76adfb74..463d2d69 100644 --- a/crypto/bn/bn_mod.c +++ b/crypto/bn/bn_mod.c @@ -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, diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 5e068c4a..683e8e94 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -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); diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index fcc2b77f..4d71afda 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -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]; diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c index dbfe9b82..40f7b23b 100644 --- a/crypto/bn/bn_sqr.c +++ b/crypto/bn/bn_sqr.c @@ -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; diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index 01f98da8..f7613584 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -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), diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c index 5f976f35..1833b15e 100644 --- a/crypto/conf/conf_lib.c +++ b/crypto/conf/conf_lib.c @@ -11,6 +11,7 @@ #include #include #include "internal/conf.h" +#include "internal/ctype.h" #include #include #include @@ -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; } diff --git a/crypto/ec/asm/x25519-x86_64.pl b/crypto/ec/asm/x25519-x86_64.pl index 930d7bdb..18dc6af9 100755 --- a/crypto/ec/asm/x25519-x86_64.pl +++ b/crypto/ec/asm/x25519-x86_64.pl @@ -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 " ___ +# 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->RipRsp + 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->RipRsp + + 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; diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index 9666de12..abe9b9cb 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -11,149 +11,23 @@ #include "ec_lcl.h" #include -#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; diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index cef6ba4c..9ce332b3 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -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 diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index 342b84fe..cbe204f5 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -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"}, diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index ae380290..8b16971a 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -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; +} diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index 6a2d1b58..457cd359 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -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, diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index 663db57f..7e1b3650 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -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); diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index dfb0d192..ad7a6f75 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -10,9 +10,8 @@ #include #include #include -#include #include -#include +#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; } diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index 358e998e..fda9a231 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -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; diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index 58669d34..2c23525a 100644 --- a/crypto/ec/ecp_nist.c +++ b/crypto/ec/ecp_nist.c @@ -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; diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c index 6155b546..ecae5688 100644 --- a/crypto/ec/ecp_nistp224.c +++ b/crypto/ec/ecp_nistp224.c @@ -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); diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c index 00fcfd5b..22f172be 100644 --- a/crypto/ec/ecp_nistp256.c +++ b/crypto/ec/ecp_nistp256.c @@ -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); diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c index 4e6c0f98..06945b5f 100644 --- a/crypto/ec/ecp_nistp521.c +++ b/crypto/ec/ecp_nistp521.c @@ -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); diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index 045c2e71..4b5fc627 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -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; diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index e0e4996c..768922aa 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -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; } - diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c index 235e84b4..27c6df4f 100644 --- a/crypto/engine/eng_devcrypto.c +++ b/crypto/engine/eng_devcrypto.c @@ -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 }; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index ee68388b..3e2bc699 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -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 diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index eb37b4b3..0add3932 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -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); diff --git a/crypto/include/internal/bn_int.h b/crypto/include/internal/bn_int.h index 9379951d..f7d37d58 100644 --- a/crypto/include/internal/bn_int.h +++ b/crypto/include/internal/bn_int.h @@ -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 diff --git a/crypto/include/internal/sm2err.h b/crypto/include/internal/sm2err.h index f32d26c0..9a7e2b62 100644 --- a/crypto/include/internal/sm2err.h +++ b/crypto/include/internal/sm2err.h @@ -15,6 +15,9 @@ # ifndef OPENSSL_NO_SM2 +# ifdef __cplusplus +extern "C" +# endif int ERR_load_SM2_strings(void); /* diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c index 76591e69..713b9aaf 100644 --- a/crypto/modes/ocb128.c +++ b/crypto/modes/ocb128.c @@ -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; diff --git a/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl index 0b4c56e5..88394b0a 100755 --- a/crypto/poly1305/asm/poly1305-x86_64.pl +++ b/crypto/poly1305/asm/poly1305-x86_64.pl @@ -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 " +.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 " -.align 16 -___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, # CONTEXT *context,DISPATCHER_CONTEXT *disp) diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index d4de71df..dfea0634 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/crypto/rsa/rsa_oaep.c @@ -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; diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index f7b5cdca..feb1ab4f 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -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); diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c index 7d453ff9..a1134f1d 100644 --- a/crypto/rsa/rsa_pk1.c +++ b/crypto/rsa/rsa_pk1.c @@ -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); diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c index cd98584b..97ae12df 100644 --- a/crypto/rsa/rsa_ssl.c +++ b/crypto/rsa/rsa_ssl.c @@ -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; diff --git a/doc/man3/BIO_should_retry.pod b/doc/man3/BIO_should_retry.pod index 60d81390..7a9ce8cc 100644 --- a/doc/man3/BIO_should_retry.pod +++ b/doc/man3/BIO_should_retry.pod @@ -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. diff --git a/doc/man3/BN_bn2bin.pod b/doc/man3/BN_bn2bin.pod index dcff2519..5da1ffd1 100644 --- a/doc/man3/BN_bn2bin.pod +++ b/doc/man3/BN_bn2bin.pod @@ -55,8 +55,8 @@ freed later using OPENSSL_free(). BN_hex2bn() takes as many characters as possible from the string B, including the leading character '-' which means negative, to form a valid hexadecimal number representation and converts them to a B and -stores it in **B. If *B is NULL, a new B is created. If -B is NULL, it only computes the length of valid representation. +stores it in **B. If *B is NULL, a new B is created. If +B 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. diff --git a/doc/man3/SSL_CTX_set_mode.pod b/doc/man3/SSL_CTX_set_mode.pod index e83b5918..e6de1660 100644 --- a/doc/man3/SSL_CTX_set_mode.pod +++ b/doc/man3/SSL_CTX_set_mode.pod @@ -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 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 to B. Options already set before are not cleared. +SSL_CTX_clear_mode() removes the mode set via bitmask in B from B. SSL_set_mode() adds the mode set via bitmask in B to B. Options already set before are not cleared. +SSL_clear_mode() removes the mode set via bitmask in B from B. SSL_CTX_get_mode() returns the mode set for B. @@ -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, L, L or L 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 and L can return with a failure and indicate the +need to retry with B. +If such a non-application data record was processed, the flag +B 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 for a non-blocking B 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 flag will cause the functions +to only return after successfully processing an application data record or a +failure. + +Turning off B can be useful with blocking Bs 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. =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 diff --git a/doc/man3/SSL_CTX_set_read_ahead.pod b/doc/man3/SSL_CTX_set_read_ahead.pod index 3a96ce3c..f2731a0d 100644 --- a/doc/man3/SSL_CTX_set_read_ahead.pod +++ b/doc/man3/SSL_CTX_set_read_ahead.pod @@ -25,12 +25,14 @@ many input bytes as possible (for non-blocking reads) or not. For example if B bytes are currently required by OpenSSL, but B bytes are available from the underlying BIO (where B > B), then OpenSSL will read all B bytes into its buffer (providing that the buffer is large enough) if reading ahead is -on, or B bytes otherwise. The parameter B or B should be 0 to ensure -reading ahead is off, or non zero otherwise. +on, or B bytes otherwise. +Setting the parameter B 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 can impact the behaviour of the SSL_pending() function (see L). +Since SSL_read() can return B 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 is not turned off using SSL_CTX_clear_mode(). +That will prevent getting B 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, diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod index f1050b0c..01446a24 100644 --- a/doc/man3/SSL_get_error.pod +++ b/doc/man3/SSL_get_error.pod @@ -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 has data -available for reading (if the result code is B) -or allows writing data (B), 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 or B condition. +The operation did not complete and can be retried later. + +B is returned when the last operation was a read +operation from a non-blocking B. +It means that not enough data was available at this time to complete the +operation. +If at a later time the underlying B has data available for reading the same +function can be called again. + +SSL_read() and SSL_read_ex() can also set B when there is +still unprocessed data available at either the B or the B layer, even +for a blocking B. +See L for more information. + +B is returned when the last operation was a write +to a non-blocking B and it was unable to sent all data to the B. +When the B is writeable again, the same function can be called again. + +Note that the retry may again lead to an B or +B 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 Bs (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 and B. In particular, +B and B. +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 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 diff --git a/doc/man3/SSL_read.pod b/doc/man3/SSL_read.pod index 215d4c52..b1b20020 100644 --- a/doc/man3/SSL_read.pod +++ b/doc/man3/SSL_read.pod @@ -51,40 +51,47 @@ call. If B 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 has been switched off and a non-application data +record has been processed, the read function can return and set the error to +B. +In this case there might still be unprocessed data available in the B. +If read ahead was set using L, there might also still +be unprocessed data available in the B. +This behaviour can be controlled using the L call. + If the underlying BIO is B, 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 call. +non-application data record has been processed and B is +not set. +Note that if B is set and only non-application data is +available the call will hang. If the underlying BIO is B, 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 with the +operation. +In this case a call to L with the return value of the read function will yield B or -B. 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. +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 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 -returned B or B, 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, L, diff --git a/doc/man3/SSL_write.pod b/doc/man3/SSL_write.pod index 14b651a1..d5284428 100644 --- a/doc/man3/SSL_write.pod +++ b/doc/man3/SSL_write.pod @@ -34,10 +34,7 @@ L or SSL_set_accept_state() before the first call to a write function. If the underlying BIO is B, 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 call. +the write operation has been finished or an error occurred. If the underlying BIO is B 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 returned B or B, it must be repeated with the same arguments. +The data that was passed might have been partially processed. +When B was set using L +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, L, L diff --git a/external/perl/transfer/Text/Template.pm b/external/perl/transfer/Text/Template.pm index 7dbfe3f8..fa2acc3f 100644 --- a/external/perl/transfer/Text/Template.pm +++ b/external/perl/transfer/Text/Template.pm @@ -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; diff --git a/fuzz/client.c b/fuzz/client.c index ce6d8cc8..bc01f622 100644 --- a/fuzz/client.c +++ b/fuzz/client.c @@ -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()); diff --git a/fuzz/server.c b/fuzz/server.c index 2f7403e2..7f9f9fa0 100644 --- a/fuzz/server.c +++ b/fuzz/server.c @@ -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); diff --git a/include/internal/dsoerr.h b/include/internal/dsoerr.h index ac6bdcd0..a54a1854 100644 --- a/include/internal/dsoerr.h +++ b/include/internal/dsoerr.h @@ -15,6 +15,9 @@ # ifndef OPENSSL_NO_DSO +# ifdef __cplusplus +extern "C" +# endif int ERR_load_DSO_strings(void); /* diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h index 4574636b..d1c92f45 100644 --- a/include/openssl/conferr.h +++ b/include/openssl/conferr.h @@ -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 diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h index 8db79676..967d6e0c 100644 --- a/include/openssl/ecerr.h +++ b/include/openssl/ecerr.h @@ -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 diff --git a/include/openssl/opensslconf.h.in b/include/openssl/opensslconf.h.in index 96f791ec..b793d482 100644 --- a/include/openssl/opensslconf.h.in +++ b/include/openssl/opensslconf.h.in @@ -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 diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index b2b34276..df5cff79 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -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) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index b1ff0950..ab08f9cb 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -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); diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index ab38a4f1..f5ab5bb8 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -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; } diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index e8367696..cf6472c7 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -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; diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 88c34376..ad79fef8 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -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)) { diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 68dd92a7..3bbe0764 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -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? */ diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 92ff9319..3e824311 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -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; } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index abf523e4..df27ba6b 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -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 */ diff --git a/test/build.info b/test/build.info index 9fe511ac..8dbe0c2f 100644 --- a/test/build.info +++ b/test/build.info @@ -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 {- diff --git a/test/conf_include_test.c b/test/conf_include_test.c index ba79d2c2..ee02d9b3 100644 --- a/test/conf_include_test.c +++ b/test/conf_include_test.c @@ -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; } diff --git a/test/ectest.c b/test/ectest.c index ead23d72..2945cd73 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -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)) diff --git a/test/gosttest.c b/test/gosttest.c new file mode 100644 index 00000000..1a31a339 --- /dev/null +++ b/test/gosttest.c @@ -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; +} diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t index fa79219e..b6d23354 100644 --- a/test/recipes/25-test_req.t +++ b/test/recipes/25-test_req.t @@ -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"), diff --git a/test/recipes/30-test_evp_data/evppkey.txt b/test/recipes/30-test_evp_data/evppkey.txt index 74351258..d482c147 100644 --- a/test/recipes/30-test_evp_data/evppkey.txt +++ b/test/recipes/30-test_evp_data/evppkey.txt @@ -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 diff --git a/test/recipes/70-test_sslsigalgs.t b/test/recipes/70-test_sslsigalgs.t index 95af8a19..f805dcf2 100644 --- a/test/recipes/70-test_sslsigalgs.t +++ b/test/recipes/70-test_sslsigalgs.t @@ -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(); + } + } +} diff --git a/test/recipes/90-test_gost.t b/test/recipes/90-test_gost.t new file mode 100644 index 00000000..c7bbb4ed --- /dev/null +++ b/test/recipes/90-test_gost.t @@ -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"); diff --git a/test/recipes/90-test_gost_data/gost.conf b/test/recipes/90-test_gost_data/gost.conf new file mode 100644 index 00000000..1f42b9d8 --- /dev/null +++ b/test/recipes/90-test_gost_data/gost.conf @@ -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 + diff --git a/test/recipes/90-test_gost_data/server-cert2001.pem b/test/recipes/90-test_gost_data/server-cert2001.pem new file mode 100644 index 00000000..e287821f --- /dev/null +++ b/test/recipes/90-test_gost_data/server-cert2001.pem @@ -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----- diff --git a/test/recipes/90-test_gost_data/server-cert2012.pem b/test/recipes/90-test_gost_data/server-cert2012.pem new file mode 100644 index 00000000..85d13c63 --- /dev/null +++ b/test/recipes/90-test_gost_data/server-cert2012.pem @@ -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----- diff --git a/test/recipes/90-test_gost_data/server-key2001.pem b/test/recipes/90-test_gost_data/server-key2001.pem new file mode 100644 index 00000000..92a59d8e --- /dev/null +++ b/test/recipes/90-test_gost_data/server-key2001.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEMCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIJgoLqJR/05zND0f +8Wnma1MFMxE7ezisZhkS/DL4DXb6 +-----END PRIVATE KEY----- diff --git a/test/recipes/90-test_gost_data/server-key2012.pem b/test/recipes/90-test_gost_data/server-key2012.pem new file mode 100644 index 00000000..e932f0dd --- /dev/null +++ b/test/recipes/90-test_gost_data/server-key2012.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MEYCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEILemtIak5CeX +Jd75HfVqAMi1MfhxW7kGvGDj8l1/nF45 +-----END PRIVATE KEY----- diff --git a/test/sslapitest.c b/test/sslapitest.c index cdac8bc4..c65bf59f 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -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); diff --git a/util/dofile.pl b/util/dofile.pl index b0e20681..c3bc9ba9 100644 --- a/util/dofile.pl +++ b/util/dofile.pl @@ -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/; diff --git a/util/echo.pl b/util/echo.pl new file mode 100644 index 00000000..d90e5212 --- /dev/null +++ b/util/echo.pl @@ -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; diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm index 4a60ba01..56570f9b 100644 --- a/util/perl/TLSProxy/Message.pm +++ b/util/perl/TLSProxy/Message.pm @@ -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, diff --git a/util/perl/with_fallback.pm b/util/perl/with_fallback.pm index 2af1d5fb..fc5638dd 100644 --- a/util/perl/with_fallback.pm +++ b/util/perl/with_fallback.pm @@ -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 $@; }