Add more commentary about recursive Provider intialisation in the FIPS module master
authorMatt Caswell <matt@openssl.org>
Tue, 21 May 2019 15:25:24 +0000 (16:25 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 23 May 2019 10:02:19 +0000 (11:02 +0100)
In addition this commit ensures that the "provctx" value is defaulted to the current
library context when we are recurively initialising the FIPS provider when already inside
the FIPS module.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8728)

202 files changed:
CHANGES
Configurations/platform/Unix.pm
Configurations/shared-info.pl
Configurations/windows-makefile.tmpl
Configure
INSTALL
NOTES.PERL
NOTES.VALGRIND [new file with mode: 0644]
apps/cms.c
apps/dsaparam.c
apps/gendsa.c
apps/genrsa.c
apps/info.c
apps/rsautl.c
apps/s_server.c
apps/version.c
build.info
crypto/asn1/p5_scrypt.c
crypto/bsearch.c [new file with mode: 0644]
crypto/build.info
crypto/chacha/asm/chacha-s390x.pl
crypto/context.c
crypto/core_fetch.c
crypto/core_namemap.c [new file with mode: 0644]
crypto/cpt_err.c
crypto/dh/dh_pmeth.c
crypto/dsa/dsa_ossl.c
crypto/dsa/dsa_pmeth.c
crypto/ec/ec_pmeth.c
crypto/ec/ecdh_kdf.c
crypto/engine/eng_openssl.c
crypto/err/err_all.c
crypto/err/openssl.txt
crypto/evp/build.info
crypto/evp/c_allkdf.c [new file with mode: 0644]
crypto/evp/digest.c
crypto/evp/e_aes.c
crypto/evp/e_aria.c
crypto/evp/e_chacha20_poly1305.c
crypto/evp/e_des.c
crypto/evp/e_des3.c
crypto/evp/evp_enc.c
crypto/evp/evp_err.c
crypto/evp/evp_fetch.c
crypto/evp/evp_lib.c
crypto/evp/evp_locl.h
crypto/evp/kdf_lib.c
crypto/evp/names.c
crypto/evp/p5_crpt.c
crypto/evp/p5_crpt2.c
crypto/ex_data.c
crypto/include/internal/evp_int.h
crypto/init.c
crypto/kdf/hkdf.c
crypto/kdf/kdf_err.c
crypto/kdf/pbkdf2.c
crypto/kdf/scrypt.c
crypto/kdf/sshkdf.c
crypto/kdf/sskdf.c
crypto/kdf/tls1_prf.c
crypto/lhash/build.info
crypto/mem_sec.c
crypto/modes/ccm128.c
crypto/objects/obj_dat.c
crypto/objects/obj_dat.h
crypto/objects/obj_mac.num
crypto/objects/objects.txt
crypto/params.c
crypto/perlasm/s390x.pm
crypto/poly1305/asm/poly1305-s390x.pl
crypto/ppccap.c
crypto/property/build.info
crypto/property/defn_cache.c
crypto/property/properties.ebnf
crypto/property/properties.xhtml [changed mode: 0644->0755]
crypto/property/property.c
crypto/property/property_lcl.h
crypto/property/property_parse.c
crypto/property/property_string.c
crypto/provider_core.c
crypto/provider_predefined.c
crypto/rand/build.info
crypto/rand/drbg_lib.c
crypto/rand/rand_crng_test.c
crypto/rand/rand_lcl.h
crypto/rand/rand_unix.c
crypto/rand/rand_vxworks.c [new file with mode: 0644]
crypto/rsa/rsa_chk.c
crypto/rsa/rsa_pmeth.c
crypto/stack/build.info
crypto/stack/stack.c
crypto/threads_pthread.c
doc/internal/man3/OSSL_METHOD_STORE.pod
doc/internal/man3/evp_generic_fetch.pod
doc/internal/man3/openssl_ctx_get_data.pod
doc/internal/man3/ossl_method_construct.pod
doc/internal/man3/ossl_namemap_new.pod [new file with mode: 0644]
doc/internal/man3/ossl_provider_new.pod
doc/man1/dsaparam.pod
doc/man1/gendsa.pod
doc/man1/genpkey.pod
doc/man1/genrsa.pod
doc/man1/s_server.pod
doc/man3/ECDSA_SIG_new.pod
doc/man3/EVP_EncryptInit.pod
doc/man3/EVP_KDF_CTX.pod
doc/man3/EVP_PKEY_meth_new.pod
doc/man3/OSSL_PARAM_TYPE.pod
doc/man3/RAND_add.pod
doc/man3/SSL_session_reused.pod
doc/man3/SSL_write.pod
doc/man7/EVP_KDF_X963.pod [new file with mode: 0644]
doc/man7/RAND_DRBG.pod
e_os.h
fuzz/oids.txt
include/internal/core.h
include/internal/cryptlib.h
include/internal/ktls.h
include/internal/namemap.h [new file with mode: 0644]
include/internal/property.h
include/internal/provider.h
include/openssl/bio.h
include/openssl/core.h
include/openssl/core_numbers.h
include/openssl/crmf.h
include/openssl/crmferr.h
include/openssl/crypto.h
include/openssl/cryptoerr.h
include/openssl/err.h
include/openssl/evperr.h
include/openssl/kdf.h
include/openssl/kdferr.h
include/openssl/obj_mac.h
include/openssl/objects.h
include/openssl/ossl_typ.h
include/openssl/ssl.h
include/openssl/sslerr.h
providers/build.info
providers/common/ciphers/aes.c
providers/common/ciphers/ciphers_locl.h
providers/common/digests/sha2.c
providers/default/defltprov.c
providers/fips/fipsprov.c
providers/legacy/legacyprov.c
ssl/d1_msg.c
ssl/record/rec_layer_d1.c
ssl/record/rec_layer_s3.c
ssl/record/ssl3_record.c
ssl/record/ssl3_record_tls13.c
ssl/s3_cbc.c
ssl/s3_enc.c
ssl/s3_lib.c
ssl/s3_msg.c
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/statem/extensions.c
ssl/statem/extensions_clnt.c
ssl/statem/extensions_srvr.c
ssl/statem/statem.c
ssl/statem/statem_clnt.c
ssl/statem/statem_dtls.c
ssl/statem/statem_lib.c
ssl/statem/statem_srvr.c
ssl/t1_enc.c
ssl/t1_lib.c
ssl/t1_trce.c
ssl/tls13_enc.c
test/bntest.c
test/build.info
test/context_internal_test.c
test/drbg_cavs_test.c
test/drbgtest.c
test/evp_kdf_test.c
test/evp_test.c
test/p_test.c
test/params_conversion_test.c [new file with mode: 0644]
test/property_test.c
test/recipes/04-test_params_conversion.t [new file with mode: 0644]
test/recipes/04-test_params_conversion_data/native_types.txt [new file with mode: 0644]
test/recipes/15-test_rsapss.t
test/recipes/20-test_kdf.t [changed mode: 0644->0755]
test/recipes/30-test_evp.t
test/recipes/30-test_evp_data/evpccmcavs.txt [new file with mode: 0644]
test/recipes/30-test_evp_data/evpciph.txt
test/recipes/30-test_evp_data/evpkdf.txt
test/recipes/80-test_cms.t
test/sslapitest.c
test/test_test.c
test/testutil.h
test/testutil/driver.c
test/testutil/tests.c
test/testutil/tu_local.h
test/tls13encryptiontest.c
util/cavs-to-evptest.pl [new file with mode: 0644]
util/find-doc-nits
util/libcrypto.num
util/libssl.num
util/mkerr.pl
util/private.num

diff --git a/CHANGES b/CHANGES
index a5d6950..86da7f1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,12 @@
 
  Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
 
+  *) Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
+     This changes the size when using the genpkey app when no size is given. It
+     fixes an omission in earlier changes that changed all RSA, DSA and DH
+     generation apps to use 2048 bits by default.
+     [Kurt Roeckx]
+
   *) Added command 'openssl kdf' that uses the EVP_KDF API.
      [Shane Lontis]
 
index ca8d6bb..bb93d38 100644 (file)
@@ -13,7 +13,8 @@ require platform::BASE;
 use configdata;
 
 sub binext              { $target{exe_extension} || '' }
-sub dsoext              { $target{dso_extension} || '.so' }
+sub dsoext              { $target{dso_extension} || platform->shlibextsimple()
+                              || '.so' }
 # Because these are also used in scripts and not just Makefile, we must
 # convert $(SHLIB_VERSION_NUMBER) to the actual number.
 sub shlibext            { (my $x = $target{shared_extension}
index 83f28bd..f942078 100644 (file)
@@ -33,9 +33,10 @@ my %shared_info;
             %{$shared_info{'gnu-shared'}},
             shared_defflag    => '-Wl,--version-script=',
             dso_ldflags       =>
-                $disabled{asan} && $disabled{msan} && $disabled{ubsan}
-                ? '-z defs'
-                : '',
+                (grep /(?:^|\s)-fsanitize/,
+                 @{$config{CFLAGS}}, @{$config{cflags}})
+                ? ''
+                : '-z defs',
         };
     },
     'bsd-gcc-shared' => sub { return $shared_info{'linux-shared'}; },
index a1daf7d..de59794 100644 (file)
@@ -206,6 +206,7 @@ AS={- $config{AS} -}
 ASFLAGS={- join(' ', @{$config{ASFLAGS}}) -}
 
 RC={- $config{RC} -}
+RCFLAGS={- join(' ', @{$config{RCFLAGS}}) -}
 
 ECHO="$(PERL)" "$(SRCDIR)\util\echo.pl"
 
@@ -630,7 +631,7 @@ EOF
          my $res = platform->res($args{obj});
          return <<"EOF";
 $res: $deps
-       \$(RC) \$(RCOUTFLAG)\$\@ $srcs
+       \$(RC) \$(RCFLAGS) \$(RCOUTFLAG)\$\@ $srcs
 EOF
      }
      my $obj = platform->obj($args{obj});
index 8b6d237..96c8e40 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -345,9 +345,9 @@ my @disablables = (
     "cast",
     "chacha",
     "cmac",
+    "cmp",
     "cms",
     "comp",
-    "crmf",
     "crypto-mdebug",
     "crypto-mdebug-backtrace",
     "ct",
@@ -433,6 +433,14 @@ foreach my $proto ((@tls, @dtls))
         push(@disablables, "$proto-method") unless $proto eq "tls1_3";
         }
 
+# Internal disablables, for aliasing purposes.  They serve no special
+# purpose here, but allow scripts to get to know them through configdata.pm,
+# where these are merged with @disablables.
+# The actual aliasing mechanism is done via %disable_cascades
+my @disablables_int = qw(
+    crmf
+    );
+
 my %deprecated_disablables = (
     "ssl2" => undef,
     "buf-freelists" => undef,
@@ -534,6 +542,8 @@ my @disable_cascades = (
 
     sub { $disabled{cmac}; } => [ "siv" ],
     "legacy"                 => [ "md2" ],
+
+    "cmp"               => [ "crmf" ],
     );
 
 # Avoid protocol support holes.  Also disable all versions below N, if version
@@ -594,7 +604,7 @@ my %user = (
     PERL        => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
     RANLIB      => env('RANLIB'),
     RC          => env('RC') || env('WINDRES'),
-    RCFLAGS     => [],
+    RCFLAGS     => [ env('RCFLAGS') || () ],
     RM          => undef,
    );
 # Info about what "make variables" may be prefixed with the cross compiler
@@ -611,6 +621,7 @@ my %useradd = (
     CXXFLAGS    => [],
     LDFLAGS     => [],
     LDLIBS      => [],
+    RCFLAGS     => [],
    );
 
 my %user_synonyms = (
@@ -1110,44 +1121,6 @@ foreach (keys %target_attr_translate) {
 
 %target = ( %{$table{DEFAULTS}}, %target );
 
-# Make the flags to build DSOs the same as for shared libraries unless they
-# are already defined
-$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
-$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
-$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
-{
-    my $shared_info_pl =
-        catfile(dirname($0), "Configurations", "shared-info.pl");
-    my %shared_info = read_eval_file($shared_info_pl);
-    push @{$target{_conf_fname_int}}, $shared_info_pl;
-    my $si = $target{shared_target};
-    while (ref $si ne "HASH") {
-        last if ! defined $si;
-        if (ref $si eq "CODE") {
-            $si = $si->();
-        } else {
-            $si = $shared_info{$si};
-        }
-    }
-
-    # Some of the 'shared_target' values don't have any entried in
-    # %shared_info.  That's perfectly fine, AS LONG AS the build file
-    # template knows how to handle this.  That is currently the case for
-    # Windows and VMS.
-    if (defined $si) {
-        # Just as above, copy certain shared_* attributes to the corresponding
-        # module_ attribute unless the latter is already defined
-        $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
-        $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
-        $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
-        foreach (sort keys %$si) {
-            $target{$_} = defined $target{$_}
-                ? add($si->{$_})->($target{$_})
-                : $si->{$_};
-        }
-    }
-}
-
 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
 $config{conf_files} = [ sort keys %conf_files ];
 
@@ -1687,7 +1660,48 @@ unless ($disabled{ktls}) {
 
 push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
 
-# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
+# Get the extra flags used when building shared libraries and modules.  We
+# do this late because some of them depend on %disabled.
+
+# Make the flags to build DSOs the same as for shared libraries unless they
+# are already defined
+$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
+$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
+$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
+{
+    my $shared_info_pl =
+        catfile(dirname($0), "Configurations", "shared-info.pl");
+    my %shared_info = read_eval_file($shared_info_pl);
+    push @{$target{_conf_fname_int}}, $shared_info_pl;
+    my $si = $target{shared_target};
+    while (ref $si ne "HASH") {
+        last if ! defined $si;
+        if (ref $si eq "CODE") {
+            $si = $si->();
+        } else {
+            $si = $shared_info{$si};
+        }
+    }
+
+    # Some of the 'shared_target' values don't have any entries in
+    # %shared_info.  That's perfectly fine, AS LONG AS the build file
+    # template knows how to handle this.  That is currently the case for
+    # Windows and VMS.
+    if (defined $si) {
+        # Just as above, copy certain shared_* attributes to the corresponding
+        # module_ attribute unless the latter is already defined
+        $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
+        $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
+        $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
+        foreach (sort keys %$si) {
+            $target{$_} = defined $target{$_}
+                ? add($si->{$_})->($target{$_})
+                : $si->{$_};
+        }
+    }
+}
+
+# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
 
 # If we use the unified build, collect information from build.info files
 my %unified_info = ();
@@ -2411,7 +2425,7 @@ use warnings;
 use Exporter;
 #use vars qw(\@ISA \@EXPORT);
 our \@ISA = qw(Exporter);
-our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
+our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables \@disablables_int);
 
 EOF
 print OUT "our %config = (\n";
@@ -2473,6 +2487,15 @@ print OUT <<"EOF";
 );
 
 EOF
+print OUT "# The following come from Configure's @disablables_int\n";
+print OUT "our \@disablables_int = (\n";
+foreach (@disablables_int) {
+    print OUT "  ", quotify("perl", $_), ",\n";
+}
+print OUT <<"EOF";
+);
+
+EOF
 print OUT "our \%disabled = (\n";
 foreach (sort keys %disabled) {
     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
diff --git a/INSTALL b/INSTALL
index 50722a1..88425a8 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -23,6 +23,7 @@
   * NOTES.WIN (any supported Windows)
   * NOTES.DJGPP (DOS platform with DJGPP)
   * NOTES.ANDROID (obviously Android [NDK])
+  * NOTES.VALGRIND (testing with Valgrind)
 
  Notational conventions in this document
  ---------------------------------------
index 46d585a..42c6127 100644 (file)
@@ -78,7 +78,7 @@
  ---------------------------------
 
  There are a number of ways to install a perl module.  In all
- descriptions below, Text::Template will server as an example.
+ descriptions below, Text::Template will serve as an example.
 
  1. for Linux users, the easiest is to install with the use of your
     favorite package manager.  Usually, all you need to do is search
diff --git a/NOTES.VALGRIND b/NOTES.VALGRIND
new file mode 100644 (file)
index 0000000..f128927
--- /dev/null
@@ -0,0 +1,70 @@
+
+NOTES FOR VALGRIND
+==================
+
+Valgrind is a test harness that includes many tools such as memcheck,
+which is commonly used to check for memory leaks, etc. The default tool
+run by Valgrind is memcheck. There are other tools available, but this
+will focus on memcheck.
+
+Valgrind runs programs in a virtual machine, this means OpenSSL unit
+tests run under Valgrind will take longer than normal.
+
+Requirements
+------------
+
+1. Platform supported by Valgrind
+   See: http://valgrind.org/info/platforms.html
+2. Valgrind installed on the platform
+   See: http://valgrind.org/downloads/current.html
+3. OpensSSL compiled
+   See: INSTALL
+
+Running Tests
+-------------
+
+Test behavior can be modified by adjusting environment variables.
+
+EXE_SHELL
+
+This variable is used to specify the shell used to execute OpenSSL test
+programs. The default program (util/shlib_wrap.sh) initializes the
+environment to allow programs to find shared libraries. The variable can
+be modified to specify a different executable environment.
+
+   EXE_SHELL="`/bin/pwd`/util/shlib_wrap.sh valgrind --error-exitcode=1 --leak-check=full -q"
+
+This will start up Valgrind with the default checker (memcheck).
+The --error-exitcode=1 option specifies that Valgrind should exit with an
+error code of 1 when memory leaks occur.
+The --leak-check=full option specifies extensive memory checking.
+The -q option prints only error messages.
+Additional Valgrind options may be added to the EXE_SHELL variable.
+
+OPENSSL_ia32cap
+
+This variable controls the processor-specific code on Intel processors.
+By default, OpenSSL will attempt to figure out the capabilities of a
+processor, and use it to its fullest capability. This variable can be
+used to control what capabilities OpenSSL uses.
+
+As of valgrind-3.15.0 on Linux/x86_64, instructions up to AVX2 are
+supported. Setting the following disables instructions beyond AVX2:
+
+   OPENSSL_ia32cap=":0"
+
+This variable may need to be set to something different based on the
+processor and Valgrind version you are running tests on. More information
+may be found in docs/man3/OPENSSL_ia32cap.pod.
+
+Additional variables (i.e. VERBOSE and TESTS) are described in the
+INSTALL file in the root of the OpenSSL source tree.
+
+Example command line:
+
+   make test EXE_SHELL="`/bin/pwd`/util/shlib_wrap.sh valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0"
+
+If an error occurs, you can then run the specific test via the TESTS
+variable with the VERBOSE option to gather additional information.
+
+   make test VERBOSE=1 TESTS=test_test EXE_SHELL="`/bin/pwd`/util/shlib_wrap.sh valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0"
index b2037b4..2863a92 100644 (file)
@@ -640,6 +640,7 @@ int cms_main(int argc, char **argv)
             goto opthelp;
         }
     } else if (!operation) {
+        BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n");
         goto opthelp;
     }
 
index 70135a6..959c331 100644 (file)
@@ -25,12 +25,15 @@ NON_EMPTY_TRANSLATION_UNIT
 # include <openssl/x509.h>
 # include <openssl/pem.h>
 
+static int verbose = 0;
+
 static int dsa_cb(int p, int n, BN_GENCB *cb);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
-    OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM
+    OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dsaparam_options[] = {
@@ -47,6 +50,7 @@ const OPTIONS dsaparam_options[] = {
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
 # endif
+    {"verbose", OPT_VERBOSE, '-', "Verbose output"},
     {NULL}
 };
 
@@ -107,6 +111,9 @@ int dsaparam_main(int argc, char **argv)
         case OPT_NOOUT:
             noout = 1;
             break;
+        case OPT_VERBOSE:
+            verbose = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -145,9 +152,11 @@ int dsaparam_main(int argc, char **argv)
             BIO_printf(bio_err, "Error allocating DSA object\n");
             goto end;
         }
-        BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
-                   num);
-        BIO_printf(bio_err, "This could take some time\n");
+        if (verbose) {
+            BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n",
+                       num);
+            BIO_printf(bio_err, "This could take some time\n");
+        }
         if (!DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) {
             ERR_print_errors(bio_err);
             BIO_printf(bio_err, "Error, DSA key generation failed\n");
@@ -251,6 +260,9 @@ static int dsa_cb(int p, int n, BN_GENCB *cb)
     static const char symbols[] = ".+*\n";
     char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?';
 
+    if (!verbose)
+        return 1;
+
     BIO_write(BN_GENCB_get_arg(cb), &c, 1);
     (void)BIO_flush(BN_GENCB_get_arg(cb));
     return 1;
index c44311b..9671b23 100644 (file)
@@ -27,7 +27,7 @@ NON_EMPTY_TRANSLATION_UNIT
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER,
+    OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE,
     OPT_R_ENUM
 } OPTION_CHOICE;
 
@@ -42,6 +42,7 @@ const OPTIONS gendsa_options[] = {
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 # endif
+    {"verbose", OPT_VERBOSE, '-', "Verbose output"},
     {NULL}
 };
 
@@ -54,7 +55,7 @@ int gendsa_main(int argc, char **argv)
     char *dsaparams = NULL;
     char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog;
     OPTION_CHOICE o;
-    int ret = 1, private = 0;
+    int ret = 1, private = 0, verbose = 0;
     const BIGNUM *p = NULL;
 
     prog = opt_init(argc, argv, gendsa_options);
@@ -86,6 +87,9 @@ int gendsa_main(int argc, char **argv)
             if (!opt_cipher(opt_unknown(), &enc))
                 goto end;
             break;
+        case OPT_VERBOSE:
+            verbose = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -124,7 +128,8 @@ int gendsa_main(int argc, char **argv)
                    "         Your key size is %d! Larger key size may behave not as expected.\n",
                    OPENSSL_DSA_MAX_MODULUS_BITS, BN_num_bits(p));
 
-    BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
+    if (verbose)
+        BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
     if (!DSA_generate_key(dsa))
         goto end;
 
index 6477bcd..ebf9c55 100644 (file)
@@ -30,12 +30,14 @@ NON_EMPTY_TRANSLATION_UNIT
 # define DEFBITS 2048
 # define DEFPRIMES 2
 
+static int verbose = 0;
+
 static int genrsa_cb(int p, int n, BN_GENCB *cb);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_3, OPT_F4, OPT_ENGINE,
-    OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES,
+    OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
     OPT_R_ENUM
 } OPTION_CHOICE;
 
@@ -52,6 +54,7 @@ const OPTIONS genrsa_options[] = {
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 # endif
     {"primes", OPT_PRIMES, 'p', "Specify number of primes"},
+    {"verbose", OPT_VERBOSE, '-', "Verbose output"},
     {NULL}
 };
 
@@ -115,6 +118,9 @@ opthelp:
             if (!opt_int(opt_arg(), &primes))
                 goto end;
             break;
+        case OPT_VERBOSE:
+            verbose = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -143,8 +149,9 @@ opthelp:
     if (out == NULL)
         goto end;
 
-    BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
-               num, primes);
+    if (verbose)
+        BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus (%d primes)\n",
+                   num, primes);
     rsa = eng ? RSA_new_method(eng) : RSA_new();
     if (rsa == NULL)
         goto end;
@@ -156,7 +163,7 @@ opthelp:
     RSA_get0_key(rsa, NULL, &e, NULL);
     hexe = BN_bn2hex(e);
     dece = BN_bn2dec(e);
-    if (hexe && dece) {
+    if (hexe && dece && verbose) {
         BIO_printf(bio_err, "e is %s (0x%s)\n", dece, hexe);
     }
     OPENSSL_free(hexe);
@@ -186,6 +193,9 @@ static int genrsa_cb(int p, int n, BN_GENCB *cb)
 {
     char c = '*';
 
+    if (!verbose)
+        return 1;
+
     if (p == 0)
         c = '.';
     if (p == 1)
index aa019ad..a2c359e 100644 (file)
@@ -42,8 +42,7 @@ int info_main(int argc, char **argv)
     prog = opt_init(argc, argv, info_options);
     while ((o = opt_next()) != OPT_EOF) {
         switch (o) {
-        case OPT_EOF:
-        case OPT_ERR:
+        default:
 opthelp:
             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
             goto end;
index df90c01..6939e42 100644 (file)
@@ -31,7 +31,7 @@ NON_EMPTY_TRANSLATION_UNIT
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
-    OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
+    OPT_RSA_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
     OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
     OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM,
     OPT_R_ENUM
@@ -46,7 +46,7 @@ const OPTIONS rsautl_options[] = {
     {"pubin", OPT_PUBIN, '-', "Input is an RSA public"},
     {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
     {"ssl", OPT_SSL, '-', "Use SSL v2 padding"},
-    {"raw", OPT_RAW, '-', "Use no padding"},
+    {"raw", OPT_RSA_RAW, '-', "Use no padding"},
     {"pkcs", OPT_PKCS, '-', "Use PKCS#1 v1.5 padding (default)"},
     {"oaep", OPT_OAEP, '-', "Use PKCS#1 OAEP"},
     {"sign", OPT_SIGN, '-', "Sign with private key"},
@@ -112,7 +112,7 @@ int rsautl_main(int argc, char **argv)
         case OPT_HEXDUMP:
             hexdump = 1;
             break;
-        case OPT_RAW:
+        case OPT_RSA_RAW:
             pad = RSA_NO_PADDING;
             break;
         case OPT_OAEP:
index 381b1c9..3ded4f8 100644 (file)
@@ -123,6 +123,8 @@ static SSL_SESSION *psksess = NULL;
 static char *psk_identity = "Client_identity";
 char *psk_key = NULL;           /* by default PSK is not used */
 
+static char http_server_binmode = 0; /* for now: 0/1 = default/binary */
+
 #ifndef OPENSSL_NO_PSK
 static unsigned int psk_server_cb(SSL *ssl, const char *identity,
                                   unsigned char *psk,
@@ -752,6 +754,7 @@ typedef enum OPTION_choice {
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
     OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
     OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
+    OPT_HTTP_SERVER_BINMODE,
     OPT_R_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
@@ -966,6 +969,7 @@ const OPTIONS s_server_options[] = {
      "The number of TLSv1.3 session tickets that a server will automatically  issue" },
     {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"},
     {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"},
+    {"http_server_binmode", OPT_HTTP_SERVER_BINMODE, '-', "opening files in binary mode when acting as http server (-WWW and -HTTP)"},
     {NULL, OPT_EOF, 0, NULL}
 };
 
@@ -1595,6 +1599,9 @@ int s_server_main(int argc, char *argv[])
             if (max_early_data == -1)
                 max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
             break;
+        case OPT_HTTP_SERVER_BINMODE:
+            http_server_binmode = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -2956,6 +2963,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
 #endif
     int width;
     fd_set readfds;
+    const char *opmode;
 
     /* Set width for a select call if needed */
     width = s + 1;
@@ -3249,9 +3257,10 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
                 break;
             }
 
-            if ((file = BIO_new_file(p, "r")) == NULL) {
+            opmode = (http_server_binmode == 1) ? "rb" : "r";
+            if ((file = BIO_new_file(p, opmode)) == NULL) {
                 BIO_puts(io, text);
-                BIO_printf(io, "Error opening '%s'\r\n", p);
+                BIO_printf(io, "Error opening '%s' mode='%s'\r\n", p, opmode);
                 ERR_print_errors(io);
                 break;
             }
index 279aeff..35bfb95 100644 (file)
@@ -122,35 +122,30 @@ opthelp:
     if (!dirty)
         version = 1;
 
-    if (version) {
-        if (strcmp(OpenSSL_version(OPENSSL_FULL_VERSION_STRING),
-                   OPENSSL_FULL_VERSION_STR) == 0)
-            printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
-        else
-            printf("%s (Library: %s)\n",
-                   OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
-    }
+    if (version)
+        printf("%s (Library: %s)\n",
+               OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
     if (date)
         printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
     if (platform)
         printf("%s\n", OpenSSL_version(OPENSSL_PLATFORM));
     if (options) {
-        printf("options:  ");
-        printf("%s ", BN_options());
+        printf("options: ");
+        printf(" %s", BN_options());
 #ifndef OPENSSL_NO_MD2
-        printf("%s ", MD2_options());
+        printf(" %s", MD2_options());
 #endif
 #ifndef OPENSSL_NO_RC4
-        printf("%s ", RC4_options());
+        printf(" %s", RC4_options());
 #endif
 #ifndef OPENSSL_NO_DES
-        printf("%s ", DES_options());
+        printf(" %s", DES_options());
 #endif
 #ifndef OPENSSL_NO_IDEA
-        printf("%s ", IDEA_options());
+        printf(" %s", IDEA_options());
 #endif
 #ifndef OPENSSL_NO_BF
-        printf("%s ", BF_options());
+        printf(" %s", BF_options());
 #endif
         printf("\n");
     }
index ce5dfd0..a0ecb21 100644 (file)
@@ -3,7 +3,7 @@
 SUBDIRS=crypto ssl apps test util tools fuzz engines providers
 
 LIBS=libcrypto libssl
-INCLUDE[libcrypto]=. crypto/include include providers/common/include
+INCLUDE[libcrypto]=. crypto/include include
 INCLUDE[libssl]=. include
 DEPEND[libssl]=libcrypto
 
index 0382a5f..d6f38e8 100644 (file)
@@ -217,7 +217,7 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     uint64_t p, r, N;
     size_t saltlen;
     size_t keylen = 0;
-    int rv = 0;
+    int t, rv = 0;
     SCRYPT_PARAMS *sparam = NULL;
 
     if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
@@ -234,7 +234,12 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
         goto err;
     }
 
-    keylen = EVP_CIPHER_CTX_key_length(ctx);
+    t = EVP_CIPHER_CTX_key_length(ctx);
+    if (t < 0) {
+        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_INVALID_KEY_LENGTH);
+        goto err;
+    }
+    keylen = t;
 
     /* Now check the parameters of sparam */
 
diff --git a/crypto/bsearch.c b/crypto/bsearch.c
new file mode 100644 (file)
index 0000000..f812c4f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stddef.h>
+#include "internal/cryptlib.h"
+
+const void *ossl_bsearch(const void *key, const void *base, int num,
+                         int size, int (*cmp) (const void *, const void *),
+                         int flags)
+{
+    const char *base_ = base;
+    int l, h, i = 0, c = 0;
+    const char *p = NULL;
+
+    if (num == 0)
+        return NULL;
+    l = 0;
+    h = num;
+    while (l < h) {
+        i = (l + h) / 2;
+        p = &(base_[i * size]);
+        c = (*cmp) (key, p);
+        if (c < 0)
+            h = i;
+        else if (c > 0)
+            l = i + 1;
+        else
+            break;
+    }
+    if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH))
+        p = NULL;
+    else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) {
+        while (i > 0 && (*cmp) (key, &(base_[(i - 1) * size])) == 0)
+            i--;
+        p = &(base_[i * size]);
+    }
+    return p;
+}
index 30dcf8c..db6d6af 100644 (file)
@@ -10,7 +10,10 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
 LIBS=../libcrypto
 # The Core
 SOURCE[../libcrypto]=provider_core.c provider_predefined.c provider_conf.c \
-        core_fetch.c
+        core_fetch.c core_namemap.c
+
+SOURCE[../providers/fips]=provider_core.c provider_predefined.c \
+        core_fetch.c core_namemap.c
 
 # Central utilities
 SOURCE[../libcrypto]=\
@@ -18,12 +21,14 @@ SOURCE[../libcrypto]=\
         ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
         threads_pthread.c threads_win.c threads_none.c getenv.c \
         o_init.c o_fips.c mem_sec.c init.c context.c sparse_array.c \
-        trace.c provider.c params.c \
+        trace.c provider.c params.c bsearch.c \
         {- $target{cpuid_asm_src} -} {- $target{uplink_aux_src} -}
 
 # FIPS module
 SOURCE[../providers/fips]=\
-        cryptlib.c mem.c mem_clr.c params.c
+        cryptlib.c mem.c mem_clr.c params.c bsearch.c ex_data.c o_str.c \
+        ctype.c threads_pthread.c threads_win.c threads_none.c context.c \
+        sparse_array.c
 
 
 DEPEND[cversion.o]=buildinf.h
index 51efe64..1f22b26 100755 (executable)
@@ -40,7 +40,7 @@
 use strict;
 use FindBin qw($Bin);
 use lib "$Bin/../..";
-use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE);
+use perlasm::s390x qw(:DEFAULT :VX :LD AUTOLOAD LABEL INCLUDE);
 
 my $flavour = shift;
 
index 752711b..7a976c0 100644 (file)
 #include "internal/cryptlib.h"
 #include "internal/thread_once.h"
 
+struct openssl_ctx_onfree_list_st {
+    openssl_ctx_onfree_fn *fn;
+    struct openssl_ctx_onfree_list_st *next;
+};
+
 struct openssl_ctx_st {
     CRYPTO_RWLOCK *lock;
     CRYPTO_EX_DATA data;
+
+    /*
+     * For most data in the OPENSSL_CTX we just use ex_data to store it. But
+     * that doesn't work for ex_data itself - so we store that directly.
+     */
+    OSSL_EX_DATA_GLOBAL global;
+
+    /* Map internal static indexes to dynamically created indexes */
+    int dyn_indexes[OPENSSL_CTX_MAX_INDEXES];
+
+    CRYPTO_RWLOCK *oncelock;
+    int run_once_done[OPENSSL_CTX_MAX_RUN_ONCE];
+    int run_once_ret[OPENSSL_CTX_MAX_RUN_ONCE];
+    struct openssl_ctx_onfree_list_st *onfreelist;
 };
 
-static OPENSSL_CTX default_context;
+#ifndef FIPS_MODE
+static OPENSSL_CTX default_context_int;
+
+/* Always points at default_context_int if it has been initialised */
+static OPENSSL_CTX *default_context = NULL;
+#endif
 
 static int context_init(OPENSSL_CTX *ctx)
 {
-    return (ctx->lock = CRYPTO_THREAD_lock_new()) != NULL
-        && CRYPTO_new_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
-                              &ctx->data);
+    size_t i;
+
+    ctx->lock = CRYPTO_THREAD_lock_new();
+    if (ctx->lock == NULL)
+        return 0;
+
+    ctx->oncelock = CRYPTO_THREAD_lock_new();
+    if (ctx->oncelock == NULL)
+        goto err;
+
+    for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++)
+        ctx->dyn_indexes[i] = -1;
+
+    if (!do_ex_data_init(ctx))
+        goto err;
+
+    if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
+                               &ctx->data)) {
+        crypto_cleanup_all_ex_data_int(ctx);
+        goto err;
+    }
+
+    return 1;
+ err:
+    CRYPTO_THREAD_lock_free(ctx->oncelock);
+    CRYPTO_THREAD_lock_free(ctx->lock);
+    ctx->lock = NULL;
+    return 0;
 }
 
 static int context_deinit(OPENSSL_CTX *ctx)
 {
+    struct openssl_ctx_onfree_list_st *tmp, *onfree;
+
+    if (ctx == NULL)
+        return 1;
+
+    onfree = ctx->onfreelist;
+    while (onfree != NULL) {
+        onfree->fn(ctx);
+        tmp = onfree;
+        onfree = onfree->next;
+        OPENSSL_free(tmp);
+    }
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data);
+    crypto_cleanup_all_ex_data_int(ctx);
+    CRYPTO_THREAD_lock_free(ctx->oncelock);
     CRYPTO_THREAD_lock_free(ctx->lock);
+    ctx->lock = NULL;
     return 1;
 }
 
-static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
-static void do_default_context_deinit(void)
+#ifndef FIPS_MODE
+void openssl_ctx_default_deinit(void)
 {
-    context_deinit(&default_context);
+    context_deinit(default_context);
 }
+
+static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
 DEFINE_RUN_ONCE_STATIC(do_default_context_init)
 {
-    return OPENSSL_init_crypto(0, NULL)
-        && context_init(&default_context)
-        && OPENSSL_atexit(do_default_context_deinit);
+    if (context_init(&default_context_int))
+        default_context = &default_context_int;
+
+    return 1;
 }
+#endif
 
 OPENSSL_CTX *OPENSSL_CTX_new(void)
 {
@@ -66,7 +134,7 @@ static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
                                     long argl_ign, void *argp)
 {
     const OPENSSL_CTX_METHOD *meth = argp;
-    void *ptr = meth->new_func();
+    void *ptr = meth->new_func(crypto_ex_data_get_openssl_ctx(ad));
 
     if (ptr != NULL)
         CRYPTO_set_ex_data(ad, index, ptr);
@@ -79,32 +147,136 @@ static void openssl_ctx_generic_free(void *parent_ign, void *ptr,
 
     meth->free_func(ptr);
 }
-int openssl_ctx_new_index(const OPENSSL_CTX_METHOD *meth)
+
+/* Non-static so we can use it in context_internal_test */
+static int openssl_ctx_init_index(OPENSSL_CTX *ctx, int static_index,
+                                  const OPENSSL_CTX_METHOD *meth)
 {
-    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_OPENSSL_CTX, 0, (void *)meth,
-                                   openssl_ctx_generic_new, NULL,
-                                   openssl_ctx_generic_free);
+    int idx;
+
+#ifndef FIPS_MODE
+    if (ctx == NULL) {
+        if (!RUN_ONCE(&default_context_init, do_default_context_init))
+            return 0;
+        ctx = default_context;
+    }
+#endif
+    if (ctx == NULL)
+        return 0;
+
+    idx = crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, 0,
+                                     (void *)meth,
+                                     openssl_ctx_generic_new,
+                                     NULL, openssl_ctx_generic_free);
+    if (idx < 0)
+        return 0;
+
+    ctx->dyn_indexes[static_index] = idx;
+    return 1;
 }
 
-void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index)
+void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,
+                           const OPENSSL_CTX_METHOD *meth)
 {
     void *data = NULL;
 
+#ifndef FIPS_MODE
     if (ctx == NULL) {
         if (!RUN_ONCE(&default_context_init, do_default_context_init))
-            return 0;
-        ctx = &default_context;
+            return NULL;
+        ctx = default_context;
     }
+#endif
+    if (ctx == NULL)
+        return NULL;
 
     CRYPTO_THREAD_read_lock(ctx->lock);
 
+    if (ctx->dyn_indexes[index] == -1
+            && !openssl_ctx_init_index(ctx, index, meth)) {
+        CRYPTO_THREAD_unlock(ctx->lock);
+        return NULL;
+    }
+
     /* The alloc call ensures there's a value there */
     if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
-                             &ctx->data, index))
-        data = CRYPTO_get_ex_data(&ctx->data, index);
+                             &ctx->data, ctx->dyn_indexes[index]))
+        data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
 
     CRYPTO_THREAD_unlock(ctx->lock);
 
     return data;
 }
 
+OSSL_EX_DATA_GLOBAL *openssl_ctx_get_ex_data_global(OPENSSL_CTX *ctx)
+{
+    /*
+     * The default context code is not needed in FIPS_MODE and ctx should never
+     * be NULL in the FIPS provider. However we compile this code out to ensure
+     * we fail immediately if ctx == NULL in FIPS_MODE
+     */
+#ifndef FIPS_MODE
+    if (ctx == NULL) {
+        if (!RUN_ONCE(&default_context_init, do_default_context_init))
+            return NULL;
+        ctx = default_context;
+    }
+#endif
+    if (ctx == NULL)
+        return NULL;
+    return &ctx->global;
+}
+
+int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
+                         openssl_ctx_run_once_fn run_once_fn)
+{
+    int done = 0, ret = 0;
+
+#ifndef FIPS_MODE
+    if (ctx == NULL) {
+        if (!RUN_ONCE(&default_context_init, do_default_context_init))
+            return 0;
+        ctx = default_context;
+    }
+#endif
+    if (ctx == NULL)
+        return 0;
+
+    CRYPTO_THREAD_read_lock(ctx->oncelock);
+    done = ctx->run_once_done[idx];
+    if (done)
+        ret = ctx->run_once_ret[idx];
+    CRYPTO_THREAD_unlock(ctx->oncelock);
+
+    if (done)
+        return ret;
+
+    CRYPTO_THREAD_write_lock(ctx->oncelock);
+    if (ctx->run_once_done[idx]) {
+        ret = ctx->run_once_ret[idx];
+        CRYPTO_THREAD_unlock(ctx->oncelock);
+        return ret;
+    }
+
+    ret = run_once_fn(ctx);
+    ctx->run_once_done[idx] = 1;
+    ctx->run_once_ret[idx] = ret;
+    CRYPTO_THREAD_unlock(ctx->oncelock);
+
+    return ret;
+}
+
+int openssl_ctx_onfree(OPENSSL_CTX *ctx, openssl_ctx_onfree_fn onfreefn)
+{
+    struct openssl_ctx_onfree_list_st *newonfree
+        = OPENSSL_malloc(sizeof(*newonfree));
+
+    if (newonfree == NULL)
+        return 0;
+
+    newonfree->fn = onfreefn;
+    newonfree->next = ctx->onfreelist;
+    ctx->onfreelist = newonfree;
+
+    return 1;
+}
index 2c4b0d7..227f920 100644 (file)
@@ -56,14 +56,14 @@ static int ossl_method_construct_this(OSSL_PROVIDER *provider, void *cbdata)
              * If we haven't been told not to store,
              * add to the global store
              */
-            data->mcm->put(data->libctx, NULL,
-                           thismap->property_definition,
-                           method, data->mcm_data);
+            data->mcm->put(data->libctx, NULL, method,
+                           thismap->algorithm_name,
+                           thismap->property_definition, data->mcm_data);
         }
 
-        data->mcm->put(data->libctx, data->store,
-                       thismap->property_definition,
-                       method, data->mcm_data);
+        data->mcm->put(data->libctx, data->store, method,
+                       thismap->algorithm_name, thismap->property_definition,
+                       data->mcm_data);
 
         /* refcnt-- because we're dropping the reference */
         data->mcm->destruct(method, data->mcm_data);
@@ -79,14 +79,15 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
 {
     void *method = NULL;
 
-    if ((method = mcm->get(libctx, NULL, propquery, mcm_data)) == NULL) {
+    if ((method =
+         mcm->get(libctx, NULL, name, propquery, mcm_data)) == NULL) {
         struct construct_data_st cbdata;
 
         /*
          * We have a temporary store to be able to easily search among new
          * items, or items that should find themselves in the global store.
          */
-        if ((cbdata.store = mcm->alloc_tmp_store()) == NULL)
+        if ((cbdata.store = mcm->alloc_tmp_store(libctx)) == NULL)
             goto fin;
 
         cbdata.libctx = libctx;
@@ -97,7 +98,7 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
         ossl_provider_forall_loaded(libctx, ossl_method_construct_this,
                                     &cbdata);
 
-        method = mcm->get(libctx, cbdata.store, propquery, mcm_data);
+        method = mcm->get(libctx, cbdata.store, name, propquery, mcm_data);
         mcm->dealloc_tmp_store(cbdata.store);
     }
 
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
new file mode 100644 (file)
index 0000000..5155a22
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/namemap.h"
+#include <openssl/lhash.h>
+#include <openssl/safestack.h>
+
+/* The namemap entry */
+typedef struct {
+    int number;
+    const char *name;
+    char body[1];        /* Sized appropriately to contain the name */
+} NAMEMAP_ENTRY;
+
+DEFINE_LHASH_OF(NAMEMAP_ENTRY);
+DEFINE_STACK_OF(NAMEMAP_ENTRY)
+
+/* The namemap, which provides for bidirectional indexing */
+
+struct ossl_namemap_st {
+    /* Flags */
+    unsigned int stored:1; /* If 1, it's stored in a library context */
+
+    CRYPTO_RWLOCK *lock;
+    LHASH_OF(NAMEMAP_ENTRY) *namenum;  /* Name->number mapping */
+    STACK_OF(NAMEMAP_ENTRY) *numname;  /* Number->name mapping */
+};
+
+/* LHASH callbacks */
+
+static unsigned long namemap_hash(const NAMEMAP_ENTRY *n)
+{
+    return OPENSSL_LH_strhash(n->name);
+}
+
+static int namemap_cmp(const NAMEMAP_ENTRY *a, const NAMEMAP_ENTRY *b)
+{
+    return strcmp(a->name, b->name);
+}
+
+static void namemap_free(NAMEMAP_ENTRY *n)
+{
+    OPENSSL_free(n);
+}
+
+/* OPENSSL_CTX_METHOD functions for a namemap stored in a library context */
+
+static void *stored_namemap_new(OPENSSL_CTX *libctx)
+{
+    OSSL_NAMEMAP *namemap = ossl_namemap_new();
+
+    if (namemap != NULL)
+        namemap->stored = 1;
+
+    return namemap;
+}
+
+static void stored_namemap_free(void *vnamemap)
+{
+    OSSL_NAMEMAP *namemap = vnamemap;
+
+    /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
+    namemap->stored = 0;
+    ossl_namemap_free(namemap);
+}
+
+static const OPENSSL_CTX_METHOD stored_namemap_method = {
+    stored_namemap_new,
+    stored_namemap_free,
+};
+
+/* API functions */
+
+OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)
+{
+    return openssl_ctx_get_data(libctx, OPENSSL_CTX_NAMEMAP_INDEX,
+                                &stored_namemap_method);
+}
+
+OSSL_NAMEMAP *ossl_namemap_new(void)
+{
+    OSSL_NAMEMAP *namemap;
+
+    if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
+        && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
+        && (namemap->numname = sk_NAMEMAP_ENTRY_new_null()) != NULL
+        && (namemap->namenum =
+            lh_NAMEMAP_ENTRY_new(namemap_hash, namemap_cmp)) != NULL) {
+        return namemap;
+    }
+
+    ossl_namemap_free(namemap);
+    return NULL;
+}
+
+void ossl_namemap_free(OSSL_NAMEMAP *namemap)
+{
+    if (namemap == NULL || namemap->stored)
+        return;
+
+     /* The elements will be freed by sk_NAMEMAP_ENTRY_pop_free() */
+    lh_NAMEMAP_ENTRY_free(namemap->namenum);
+
+    sk_NAMEMAP_ENTRY_pop_free(namemap->numname, namemap_free);
+
+    CRYPTO_THREAD_lock_free(namemap->lock);
+    OPENSSL_free(namemap);
+}
+
+/*
+ * TODO(3.0) It isn't currently possible to have a default namemap in the
+ * FIPS module because if init and cleanup constraints, so we currently
+ * disable the code that would allow it when FIPS_MODE is defined.
+ */
+
+const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number)
+{
+    NAMEMAP_ENTRY *entry;
+
+#ifndef FIPS_MODE
+    if (namemap == NULL)
+        namemap = ossl_namemap_stored(NULL);
+#endif
+
+    if (namemap == NULL || number == 0)
+        return NULL;
+
+    CRYPTO_THREAD_read_lock(namemap->lock);
+    entry = sk_NAMEMAP_ENTRY_value(namemap->numname, number);
+    CRYPTO_THREAD_unlock(namemap->lock);
+
+    if (entry != NULL)
+        return entry->name;
+    return NULL;
+}
+
+int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name)
+{
+    NAMEMAP_ENTRY *entry, template;
+
+#ifndef FIPS_MODE
+    if (namemap == NULL)
+        namemap = ossl_namemap_stored(NULL);
+#endif
+
+    if (namemap == NULL)
+        return 0;
+
+    template.name = name;
+    CRYPTO_THREAD_read_lock(namemap->lock);
+    entry = lh_NAMEMAP_ENTRY_retrieve(namemap->namenum, &template);
+    CRYPTO_THREAD_unlock(namemap->lock);
+
+    if (entry == NULL)
+        return 0;
+
+    return entry->number;
+}
+
+int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name)
+{
+    NAMEMAP_ENTRY *entry;
+    int number;
+
+#ifndef FIPS_MODE
+    if (namemap == NULL)
+        namemap = ossl_namemap_stored(NULL);
+#endif
+
+    if (name == NULL || namemap == NULL)
+        return 0;
+
+    if ((number = ossl_namemap_number(namemap, name)) != 0)
+        return number;           /* Pretend success */
+
+    if ((entry = OPENSSL_zalloc(sizeof(*entry) + strlen(name))) == NULL)
+        goto err;
+
+    strcpy(entry->body, name);
+    entry->name = entry->body;
+
+    CRYPTO_THREAD_write_lock(namemap->lock);
+
+    entry->number = sk_NAMEMAP_ENTRY_push(namemap->numname, entry);
+
+    if (entry->number == 0)
+        goto err;
+
+    (void)lh_NAMEMAP_ENTRY_insert(namemap->namenum, entry);
+    if (lh_NAMEMAP_ENTRY_error(namemap->namenum))
+        goto err;
+
+    CRYPTO_THREAD_unlock(namemap->lock);
+
+    return entry->number;
+
+ err:
+    if (entry != NULL) {
+        if (entry->number != 0)
+            (void)sk_NAMEMAP_ENTRY_pop(namemap->numname);
+        lh_NAMEMAP_ENTRY_delete(namemap->namenum, entry);
+        CRYPTO_THREAD_unlock(namemap->lock);
+    }
+    return 0;
+}
index 8c38692..25bb813 100644 (file)
@@ -21,9 +21,13 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
      "CRYPTO_free_ex_data"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, 0),
      "CRYPTO_get_ex_new_index"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX, 0),
+     "CRYPTO_get_ex_new_index_ex"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_MEMDUP, 0), "CRYPTO_memdup"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA, 0),
      "CRYPTO_new_ex_data"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_NEW_EX_DATA_EX, 0),
+     "crypto_new_ex_data_ex"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_COPY_CTX, 0),
      "CRYPTO_ocb128_copy_ctx"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_CRYPTO_OCB128_INIT, 0),
@@ -46,10 +50,10 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DEEP_COPY, 0),
      "OPENSSL_sk_deep_copy"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OPENSSL_SK_DUP, 0), "OPENSSL_sk_dup"},
-    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN, 0),
-     "OSSL_PROVIDER_add_builtin"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ACTIVATE, 0),
      "ossl_provider_activate"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_BUILTIN, 0),
+     "OSSL_PROVIDER_add_builtin"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_ADD_PARAMETER, 0),
      "ossl_provider_add_parameter"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_OSSL_PROVIDER_NEW, 0),
index 3497915..f630fd3 100644 (file)
@@ -54,7 +54,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
         DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    dctx->prime_len = 1024;
+    dctx->prime_len = 2048;
     dctx->subprime_len = -1;
     dctx->generator = 2;
     dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
index 37c654d..b66d5ad 100644 (file)
@@ -190,6 +190,12 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
         return 0;
     }
 
+    /* Reject obviously invalid parameters */
+    if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) {
+        DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS);
+        return 0;
+    }
+
     k = BN_new();
     l = BN_new();
     if (k == NULL || l == NULL)
index cfba91c..a21e010 100644 (file)
@@ -20,8 +20,8 @@
 
 typedef struct {
     /* Parameter gen parameters */
-    int nbits;                  /* size of p in bits (default: 1024) */
-    int qbits;                  /* size of q in bits (default: 160) */
+    int nbits;                  /* size of p in bits (default: 2048) */
+    int qbits;                  /* size of q in bits (default: 224) */
     const EVP_MD *pmd;          /* MD for parameter generation */
     /* Keygen callback info */
     int gentmp[2];
@@ -35,8 +35,8 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
 
     if (dctx == NULL)
         return 0;
-    dctx->nbits = 1024;
-    dctx->qbits = 160;
+    dctx->nbits = 2048;
+    dctx->qbits = 224;
     dctx->pmd = NULL;
     dctx->md = NULL;
 
@@ -138,7 +138,11 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
             EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
             EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
             EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
-            EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
             DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
             return 0;
         }
index 68211ed..45798b4 100644 (file)
@@ -323,7 +323,11 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
             EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
             EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
             EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
-            EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
             ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
             return 0;
         }
index f2af38a..f556dc6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #include <string.h>
 #include <openssl/ec.h>
 #include <openssl/evp.h>
+#include <openssl/kdf.h>
 #include "ec_lcl.h"
 
 /* Key derivation function from X9.63/SECG */
-/* Way more than we will ever need */
-#define ECDH_KDF_MAX    (1 << 30)
-
 int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
                    const unsigned char *Z, size_t Zlen,
                    const unsigned char *sinfo, size_t sinfolen,
                    const EVP_MD *md)
 {
-    EVP_MD_CTX *mctx = NULL;
-    int rv = 0;
-    unsigned int i;
-    size_t mdlen;
-    unsigned char ctr[4];
-    if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX
-        || Zlen > ECDH_KDF_MAX)
-        return 0;
-    mctx = EVP_MD_CTX_new();
-    if (mctx == NULL)
-        return 0;
-    mdlen = EVP_MD_size(md);
-    for (i = 1;; i++) {
-        unsigned char mtmp[EVP_MAX_MD_SIZE];
-        if (!EVP_DigestInit_ex(mctx, md, NULL))
-            goto err;
-        ctr[3] = i & 0xFF;
-        ctr[2] = (i >> 8) & 0xFF;
-        ctr[1] = (i >> 16) & 0xFF;
-        ctr[0] = (i >> 24) & 0xFF;
-        if (!EVP_DigestUpdate(mctx, Z, Zlen))
-            goto err;
-        if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr)))
-            goto err;
-        if (!EVP_DigestUpdate(mctx, sinfo, sinfolen))
-            goto err;
-        if (outlen >= mdlen) {
-            if (!EVP_DigestFinal(mctx, out, NULL))
-                goto err;
-            outlen -= mdlen;
-            if (outlen == 0)
-                break;
-            out += mdlen;
-        } else {
-            if (!EVP_DigestFinal(mctx, mtmp, NULL))
-                goto err;
-            memcpy(out, mtmp, outlen);
-            OPENSSL_cleanse(mtmp, mdlen);
-            break;
-        }
-    }
-    rv = 1;
- err:
-    EVP_MD_CTX_free(mctx);
-    return rv;
+    int ret;
+    EVP_KDF_CTX *kctx = NULL;
+
+    kctx = EVP_KDF_CTX_new(EVP_get_kdfbyname(SN_x963kdf));
+    ret =
+        kctx != NULL
+        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, md) > 0
+        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, Z, Zlen) > 0
+        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SHARED_INFO, sinfo, sinfolen) > 0
+        && EVP_KDF_derive(kctx, out, outlen) > 0;
+
+    EVP_KDF_CTX_free(kctx);
+    return ret;
 }
 
 /*-
index 5877a26..d41006f 100644 (file)
@@ -189,12 +189,15 @@ typedef struct {
 static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                              const unsigned char *iv, int enc)
 {
+    const int n = EVP_CIPHER_CTX_key_length(ctx);
+
 # ifdef TEST_ENG_OPENSSL_RC4_P_INIT
     fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
 # endif
-    memcpy(&test(ctx)->key[0], key, EVP_CIPHER_CTX_key_length(ctx));
-    RC4_set_key(&test(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
-                test(ctx)->key);
+    if (n <= 0)
+        return n;
+    memcpy(&test(ctx)->key[0], key, n);
+    RC4_set_key(&test(ctx)->ks, n, test(ctx)->key);
     return 1;
 }
 
index af44467..a56cf9c 100644 (file)
@@ -92,7 +92,7 @@ int err_load_crypto_strings_int(void)
 # ifndef OPENSSL_NO_CMS
         ERR_load_CMS_strings() == 0 ||
 # endif
-# ifndef OPENSSL_NO_CMP
+# ifndef OPENSSL_NO_CRMF
         ERR_load_CRMF_strings() == 0 ||
 # endif
 # ifndef OPENSSL_NO_CT
index 5c444f5..eee3092 100644 (file)
@@ -374,8 +374,10 @@ CRYPTO_F_CMAC_CTX_NEW:120:CMAC_CTX_new
 CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
 CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
 CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX:100:CRYPTO_get_ex_new_index
+CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX:141:crypto_get_ex_new_index_ex
 CRYPTO_F_CRYPTO_MEMDUP:115:CRYPTO_memdup
 CRYPTO_F_CRYPTO_NEW_EX_DATA:112:CRYPTO_new_ex_data
+CRYPTO_F_CRYPTO_NEW_EX_DATA_EX:142:crypto_new_ex_data_ex
 CRYPTO_F_CRYPTO_OCB128_COPY_CTX:121:CRYPTO_ocb128_copy_ctx
 CRYPTO_F_CRYPTO_OCB128_INIT:122:CRYPTO_ocb128_init
 CRYPTO_F_CRYPTO_SET_EX_DATA:102:CRYPTO_set_ex_data
@@ -800,6 +802,7 @@ EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
 EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
 EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl
 EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str
+EVP_F_EVP_KDF_CTX_NEW:240:EVP_KDF_CTX_new
 EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id
 EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
 EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
@@ -922,6 +925,7 @@ KDF_F_SSKDF_MAC2CTRL:136:sskdf_mac2ctrl
 KDF_F_SSKDF_NEW:137:sskdf_new
 KDF_F_SSKDF_SIZE:138:sskdf_size
 KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
+KDF_F_X963KDF_DERIVE:139:x963kdf_derive
 OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
 OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
 OBJ_F_OBJ_CREATE:100:OBJ_create
@@ -1434,6 +1438,7 @@ SSL_F_SSL_RENEGOTIATE:516:SSL_renegotiate
 SSL_F_SSL_RENEGOTIATE_ABBREVIATED:546:SSL_renegotiate_abbreviated
 SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT:320:*
 SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT:321:*
+SSL_F_SSL_SENDFILE:639:SSL_sendfile
 SSL_F_SSL_SESSION_DUP:348:ssl_session_dup
 SSL_F_SSL_SESSION_NEW:189:SSL_SESSION_new
 SSL_F_SSL_SESSION_PRINT_FP:190:SSL_SESSION_print_fp
@@ -2396,6 +2401,7 @@ EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
 EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length
 EVP_R_INVALID_DIGEST:152:invalid digest
 EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
+EVP_R_INVALID_IV_LENGTH:194:invalid iv length
 EVP_R_INVALID_KEY:163:invalid key
 EVP_R_INVALID_KEY_LENGTH:130:invalid key length
 EVP_R_INVALID_OPERATION:148:invalid operation
@@ -2459,6 +2465,7 @@ KDF_R_MISSING_SEED:106:missing seed
 KDF_R_MISSING_SESSION_ID:113:missing session id
 KDF_R_MISSING_TYPE:114:missing type
 KDF_R_MISSING_XCGHASH:115:missing xcghash
+KDF_R_NOT_SUPPORTED:118:not supported
 KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
 KDF_R_UNSUPPORTED_MAC_TYPE:117:unsupported mac type
 KDF_R_VALUE_ERROR:108:value error
index 10ba3a3..61e8880 100644 (file)
@@ -10,7 +10,7 @@ SOURCE[../../libcrypto]=\
         bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
         c_allc.c c_alld.c evp_lib.c bio_ok.c \
         evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
-        pkey_kdf.c \
+        pkey_kdf.c c_allkdf.c \
         e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
         e_chacha20_poly1305.c cmeth_lib.c \
@@ -20,6 +20,10 @@ SOURCE[../../libcrypto]=\
 SOURCE[../../libcrypto]=\
        evp_fetch.c
 
+# FIPS Module
+SOURCE[../../providers/fips]=\
+        digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c
+
 INCLUDE[e_aes.o]=.. ../modes
 INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
 INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes
diff --git a/crypto/evp/c_allkdf.c b/crypto/evp/c_allkdf.c
new file mode 100644 (file)
index 0000000..2233fd9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include "internal/evp_int.h"
+
+void openssl_add_all_kdfs_int(void)
+{
+    EVP_add_kdf(&pbkdf2_kdf_meth);
+#ifndef OPENSSL_NO_SCRYPT
+    EVP_add_kdf(&scrypt_kdf_meth);
+#endif
+    EVP_add_kdf(&tls1_prf_kdf_meth);
+    EVP_add_kdf(&hkdf_kdf_meth);
+    EVP_add_kdf(&sshkdf_kdf_meth);
+    EVP_add_kdf(&ss_kdf_meth);
+    EVP_add_kdf(&x963_kdf_meth);
+}
index 043e456..a1f0154 100644 (file)
@@ -55,10 +55,14 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
      * pctx should be freed by the user of EVP_MD_CTX
      * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
      */
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
         EVP_PKEY_CTX_free(ctx->pctx);
-#ifndef OPENSSL_NO_ENGINE
+
+# ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(ctx->engine);
+# endif
 #endif
     OPENSSL_cleanse(ctx, sizeof(*ctx));
 
@@ -102,8 +106,9 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
 
 int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 {
-    EVP_MD *provmd;
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE *tmpimpl = NULL;
+#endif
 
     EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
 
@@ -111,7 +116,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
         ctx->reqdigest = type;
 
     /* TODO(3.0): Legacy work around code below. Remove this */
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
      * this context may already have an ENGINE! Try to avoid releasing the
@@ -132,7 +137,9 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
      */
     if (ctx->engine != NULL
             || impl != NULL
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
             || tmpimpl != NULL
+#endif
             || ctx->pctx != NULL
             || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
         if (ctx->digest == ctx->fetched_digest)
@@ -160,7 +167,13 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
     /* TODO(3.0): Start of non-legacy code below */
 
     if (type->prov == NULL) {
-        provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
+#ifdef FIPS_MODE
+        /* We only do explict fetches inside the FIPS module */
+        EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+#else
+        EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
+
         if (provmd == NULL) {
             EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -168,11 +181,12 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
         type = provmd;
         EVP_MD_meth_free(ctx->fetched_digest);
         ctx->fetched_digest = provmd;
+#endif
     }
 
     ctx->digest = type;
     if (ctx->provctx == NULL) {
-        ctx->provctx = ctx->digest->newctx();
+        ctx->provctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
         if (ctx->provctx == NULL) {
             EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -189,7 +203,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
     /* TODO(3.0): Remove legacy code below */
  legacy:
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     if (type) {
         /*
          * Ensure an ENGINE left lying around from last time is cleared (the
@@ -247,16 +261,19 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             }
         }
     }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
  skip_to_init:
 #endif
-    if (ctx->pctx) {
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
+    if (ctx->pctx != NULL) {
         int r;
         r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
                               EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
         if (r <= 0 && (r != -2))
             return 0;
     }
+#endif
     if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
         return 1;
     return ctx->digest->init(ctx);
@@ -397,6 +414,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 
     /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
     EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (in->pctx != NULL) {
         out->pctx = EVP_PKEY_CTX_dup(in->pctx);
         if (out->pctx == NULL) {
@@ -405,12 +424,13 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
             return 0;
         }
     }
+#endif
 
     return 1;
 
     /* TODO(3.0): Remove legacy code below */
  legacy:
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /* Make sure it's safe to copy a digest context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
         EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB);
@@ -451,6 +471,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 
     out->update = in->update;
 
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (in->pctx) {
         out->pctx = EVP_PKEY_CTX_dup(in->pctx);
         if (!out->pctx) {
@@ -458,6 +480,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
             return 0;
         }
     }
+#endif
 
     if (out->digest->copy)
         return out->digest->copy(out, in);
@@ -494,13 +517,14 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
     return 0;
 }
 
-static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
-                                    OSSL_PROVIDER *prov)
+static void *evp_md_from_dispatch(const OSSL_DISPATCH *fns,
+                                  OSSL_PROVIDER *prov)
 {
     EVP_MD *md = NULL;
     int fncnt = 0;
 
-    if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
+    /* EVP_MD_fetch() will set the legacy NID if available */
+    if ((md = EVP_MD_meth_new(NID_undef, NID_undef)) == NULL)
         return NULL;
 
     for (; fns->function_id != 0; fns++) {
@@ -587,17 +611,25 @@ static void evp_md_free(void *md)
     EVP_MD_meth_free(md);
 }
 
-static int evp_md_nid(void *vmd)
-{
-    EVP_MD *md = vmd;
-
-    return md->type;
-}
-
 EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                      const char *properties)
 {
-    return evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
-                             evp_md_from_dispatch, evp_md_upref,
-                             evp_md_free, evp_md_nid);
+    EVP_MD *md =
+        evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
+                          evp_md_from_dispatch, evp_md_upref,
+                          evp_md_free);
+
+#ifndef FIPS_MODE
+    /* TODO(3.x) get rid of the need for legacy NIDs */
+    if (md != NULL) {
+        /*
+         * FIPS module note: since internal fetches will be entirely
+         * provider based, we know that none of its code depends on legacy
+         * NIDs or any functionality that use them.
+         */
+        md->type = OBJ_sn2nid(algorithm);
+    }
+#endif
+
+    return md;
 }
index 4f98cdc..c9dbca9 100644 (file)
@@ -15,6 +15,7 @@
 #include <assert.h>
 #include <openssl/aes.h>
 #include "internal/evp_int.h"
+#include "internal/cryptlib.h"
 #include "modes_lcl.h"
 #include <openssl/rand.h>
 #include <openssl/cmac.h>
@@ -22,7 +23,7 @@
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ks;
     block128_f block;
@@ -34,7 +35,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ks;                       /* AES key schedule to use */
     int key_set;                /* Set if key initialised */
@@ -52,7 +53,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ks1, ks2;                 /* AES key schedules to use */
     XTS128_CONTEXT xts;
@@ -64,7 +65,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ks;                       /* AES key schedule to use */
     int key_set;                /* Set if key initialised */
@@ -80,11 +81,11 @@ typedef struct {
 #ifndef OPENSSL_NO_OCB
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ksenc;                    /* AES key schedule to use for encryption */
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ksdec;                    /* AES key schedule to use for decryption */
     int key_set;                /* Set if key initialised */
@@ -1008,7 +1009,7 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         /*-
          * KM-AES parameter block - begin
          * (see z/Architecture Principles of Operation >= SA22-7832-06)
@@ -1023,7 +1024,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         /*-
          * KMO-AES parameter block - begin
          * (see z/Architecture Principles of Operation >= SA22-7832-08)
@@ -1041,7 +1042,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         /*-
          * KMF-AES parameter block - begin
          * (see z/Architecture Principles of Operation >= SA22-7832-08)
@@ -1059,7 +1060,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         /*-
          * KMA-GCM-AES parameter block - begin
          * (see z/Architecture Principles of Operation >= SA22-7832-11)
@@ -1108,7 +1109,7 @@ typedef struct {
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         /*-
          * Padding is chosen so that ccm.kmac_param.k overlaps with key.k and
          * ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's
@@ -2263,9 +2264,6 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     if (!cctx->aes.ccm.iv_set)
         return -1;
 
-    if (!enc && !cctx->aes.ccm.tag_set)
-        return -1;
-
     if (out == NULL) {
         /* Update(): Pass message length. */
         if (in == NULL) {
@@ -2284,6 +2282,10 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
         return len;
     }
 
+    /* The tag must be set before actually decrypting data */
+    if (!enc && !cctx->aes.ccm.tag_set)
+        return -1;
+
     /* Update(): Process message. */
 
     if (!cctx->aes.ccm.len_set) {
@@ -3791,8 +3793,6 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     if (!cctx->iv_set)
         return -1;
 
-    if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
-        return -1;
     if (!out) {
         if (!in) {
             if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
@@ -3807,6 +3807,11 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
         CRYPTO_ccm128_aad(ccm, in, len);
         return len;
     }
+
+    /* The tag must be set before actually decrypting data */
+    if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
+        return -1;
+
     /* If not set length yet do it */
     if (!cctx->len_set) {
         if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
@@ -3853,7 +3858,7 @@ BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         AES_KEY ks;
     } ks;
     /* Indicates if IV has been set */
index 8828494..5404dd4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -27,7 +27,7 @@ typedef struct {
 /* ARIA GCM context */
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         ARIA_KEY ks;
     } ks;                       /* ARIA subkey to use */
     int key_set;                /* Set if key initialised */
@@ -43,7 +43,7 @@ typedef struct {
 /* ARIA CCM context */
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         ARIA_KEY ks;
     } ks;                       /* ARIA key schedule to use */
     int key_set;                /* Set if key initialised */
index 3790200..ccef031 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -20,7 +20,7 @@
 
 typedef struct {
     union {
-        double align;   /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
+        OSSL_UNION_ALIGN;  /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
         unsigned int d[CHACHA_KEY_SIZE / 4];
     } key;
     unsigned int  counter[CHACHA_CTR_SIZE / 4];
index e7486cb..0d8e90c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -18,7 +18,7 @@
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         DES_key_schedule ks;
     } ks;
     union {
index aeaae5f..52fde95 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -19,7 +19,7 @@
 
 typedef struct {
     union {
-        double align;
+        OSSL_UNION_ALIGN;
         DES_key_schedule ks[3];
     } ks;
     union {
@@ -280,15 +280,17 @@ static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 {
 
     DES_cblock *deskey = ptr;
+    int kl;
 
     switch (type) {
     case EVP_CTRL_RAND_KEY:
-        if (RAND_priv_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0)
+        kl = EVP_CIPHER_CTX_key_length(ctx);
+        if (kl < 0 || RAND_priv_bytes(ptr, kl) <= 0)
             return 0;
         DES_set_odd_parity(deskey);
-        if (EVP_CIPHER_CTX_key_length(ctx) >= 16)
+        if (kl >= 16)
             DES_set_odd_parity(deskey + 1);
-        if (EVP_CIPHER_CTX_key_length(ctx) >= 24)
+        if (kl >= 24)
             DES_set_odd_parity(deskey + 2);
         return 1;
 
index 676eaab..b3e97d0 100644 (file)
@@ -51,7 +51,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
             OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
     }
     OPENSSL_free(ctx->cipher_data);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE_finish(ctx->engine);
 #endif
     memset(ctx, 0, sizeof(*ctx));
@@ -81,8 +81,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                       ENGINE *impl, const unsigned char *key,
                       const unsigned char *iv, int enc)
 {
-    EVP_CIPHER *provciph = NULL;
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE *tmpimpl = NULL;
+#endif
     const EVP_CIPHER *tmpcipher;
 
     /*
@@ -105,7 +106,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
     /* TODO(3.0): Legacy work around code below. Remove this */
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
      * this context may already have an ENGINE! Try to avoid releasing the
@@ -126,8 +127,10 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
      * If there are engines involved then we should use legacy handling for now.
      */
     if (ctx->engine != NULL
-            || impl != NULL
-            || tmpimpl != NULL) {
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+            || tmpimpl != NULL
+#endif
+            || impl != NULL) {
         if (ctx->cipher == ctx->fetched_cipher)
             ctx->cipher = NULL;
         EVP_CIPHER_meth_free(ctx->fetched_cipher);
@@ -194,7 +197,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         cipher = ctx->cipher;
 
     if (cipher->prov == NULL) {
-        provciph = EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
+#ifdef FIPS_MODE
+        /* We only do explict fetches inside the FIPS module */
+        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+#else
+        EVP_CIPHER *provciph =
+            EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
+
         if (provciph == NULL) {
             EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -202,11 +212,12 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         cipher = provciph;
         EVP_CIPHER_meth_free(ctx->fetched_cipher);
         ctx->fetched_cipher = provciph;
+#endif
     }
 
     ctx->cipher = cipher;
     if (ctx->provctx == NULL) {
-        ctx->provctx = ctx->cipher->newctx();
+        ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
         if (ctx->provctx == NULL) {
             EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -279,7 +290,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             ctx->encrypt = enc;
             ctx->flags = flags;
         }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
         if (impl != NULL) {
             if (!ENGINE_init(impl)) {
                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
@@ -335,9 +346,12 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             }
         }
     }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
  skip_to_init:
 #endif
+    if (ctx->cipher == NULL)
+        return 0;
+
     /* we assume block size is a power of 2 in *cryptUpdate */
     OPENSSL_assert(ctx->cipher->block_size == 1
                    || ctx->cipher->block_size == 8
@@ -492,11 +506,6 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
 
     bl = ctx->cipher->block_size;
 
-    if (inl <= 0) {
-        *outl = 0;
-        return inl == 0;
-    }
-
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
         /* If block size > 1 then the cipher will have to do this check */
         if (bl == 1 && is_partially_overlapping(out, in, cmpl)) {
@@ -512,6 +521,10 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
         return 1;
     }
 
+    if (inl <= 0) {
+        *outl = 0;
+        return inl == 0;
+    }
     if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) {
         EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
         return 0;
@@ -587,11 +600,14 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                                inl + (blocksize == 1 ? 0 : blocksize), in,
                                (size_t)inl);
 
-    if (soutl > INT_MAX) {
-        EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
-        return 0;
+    if (ret) {
+        if (soutl > INT_MAX) {
+            EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
+            return 0;
+        }
+        *outl = soutl;
     }
-    *outl = soutl;
+
     return ret;
 
     /* TODO(3.0): Remove legacy code below */
@@ -620,7 +636,11 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
         return 0;
     }
 
-    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
+    if (ctx->cipher->prov == NULL)
         goto legacy;
 
     blocksize = EVP_CIPHER_CTX_block_size(ctx);
@@ -633,11 +653,13 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
                               blocksize == 1 ? 0 : blocksize);
 
-    if (soutl > INT_MAX) {
-        EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
-        return 0;
+    if (ret) {
+        if (soutl > INT_MAX) {
+            EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
+            return 0;
+        }
+        *outl = soutl;
     }
-    *outl = soutl;
 
     return ret;
 
@@ -695,7 +717,11 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
         return 0;
     }
 
-    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
+    if (ctx->cipher->prov == NULL)
         goto legacy;
 
     blocksize = EVP_CIPHER_CTX_block_size(ctx);
@@ -726,11 +752,6 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
         cmpl = (cmpl + 7) / 8;
 
-    if (inl <= 0) {
-        *outl = 0;
-        return inl == 0;
-    }
-
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
         if (b == 1 && is_partially_overlapping(out, in, cmpl)) {
             EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING);
@@ -746,6 +767,11 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
         return 1;
     }
 
+    if (inl <= 0) {
+        *outl = 0;
+        return inl == 0;
+    }
+
     if (ctx->flags & EVP_CIPH_NO_PADDING)
         return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
 
@@ -832,6 +858,10 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
  legacy:
 
     *outl = 0;
+    if (ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
 
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
         i = ctx->cipher->do_cipher(ctx, out, NULL, 0);
@@ -947,14 +977,19 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
     return ret;
 }
 
+#if !defined(FIPS_MODE)
+/* TODO(3.0): No support for RAND yet in the FIPS module */
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 {
+    int kl;
     if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
         return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
-    if (RAND_priv_bytes(key, EVP_CIPHER_CTX_key_length(ctx)) <= 0)
+    kl = EVP_CIPHER_CTX_key_length(ctx);
+    if (kl <= 0 || RAND_priv_bytes(key, kl) <= 0)
         return 0;
     return 1;
 }
+#endif
 
 int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
 {
@@ -992,7 +1027,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     /* TODO(3.0): Remove legacy code below */
  legacy:
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /* Make sure it's safe to copy a cipher context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
         EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB);
@@ -1022,13 +1057,17 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     return 1;
 }
 
-static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
+static void *evp_cipher_from_dispatch(const OSSL_DISPATCH *fns,
                                       OSSL_PROVIDER *prov)
 {
     EVP_CIPHER *cipher = NULL;
     int fnciphcnt = 0, fnctxcnt = 0;
 
-    if ((cipher = EVP_CIPHER_meth_new(nid, 0, 0)) == NULL)
+    /*
+     * The legacy NID is set by EVP_CIPHER_fetch() if the name exists in
+     * the object database.
+     */
+    if ((cipher = EVP_CIPHER_meth_new(0, 0, 0)) == NULL)
         return NULL;
 
     for (; fns->function_id != 0; fns++) {
@@ -1145,17 +1184,25 @@ static void evp_cipher_free(void *cipher)
     EVP_CIPHER_meth_free(cipher);
 }
 
-static int evp_cipher_nid(void *vcipher)
-{
-    EVP_CIPHER *cipher = vcipher;
-
-    return cipher->nid;
-}
-
 EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                              const char *properties)
 {
-    return evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
-                             evp_cipher_from_dispatch, evp_cipher_upref,
-                             evp_cipher_free, evp_cipher_nid);
+    EVP_CIPHER *cipher =
+        evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
+                          evp_cipher_from_dispatch, evp_cipher_upref,
+                          evp_cipher_free);
+
+#ifndef FIPS_MODE
+    /* TODO(3.x) get rid of the need for legacy NIDs */
+    if (cipher != NULL) {
+        /*
+         * FIPS module note: since internal fetches will be entirely
+         * provider based, we know that none of its code depends on legacy
+         * NIDs or any functionality that use them.
+         */
+        cipher->nid = OBJ_sn2nid(algorithm);
+    }
+#endif
+
+    return cipher;
 }
index 3555c0e..836f5ee 100644 (file)
@@ -74,6 +74,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL, 0), "EVP_KDF_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL_STR, 0), "EVP_KDF_ctrl_str"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW, 0), "EVP_KDF_CTX_new"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW_ID, 0), "EVP_KDF_CTX_new_id"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
@@ -248,6 +249,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "invalid custom length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST), "invalid digest"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_FIPS_MODE), "invalid fips mode"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_IV_LENGTH), "invalid iv length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
index c054f31..fdd6209 100644 (file)
 #include <openssl/core.h>
 #include "internal/cryptlib.h"
 #include "internal/thread_once.h"
-#include "internal/asn1_int.h"
 #include "internal/property.h"
 #include "internal/core.h"
+#include "internal/namemap.h"
 #include "internal/evp_int.h"    /* evp_locl.h needs it */
 #include "evp_locl.h"
 
-/* The OpenSSL library context index for the default method store */
-static int default_method_store_index = -1;
-
 static void default_method_store_free(void *vstore)
 {
     ossl_method_store_free(vstore);
 }
 
-static void *default_method_store_new(void)
+static void *default_method_store_new(OPENSSL_CTX *ctx)
 {
-    return ossl_method_store_new();
+    return ossl_method_store_new(ctx);
 }
 
 
@@ -38,39 +35,23 @@ static const OPENSSL_CTX_METHOD default_method_store_method = {
     default_method_store_free,
 };
 
-static int default_method_store_init(void)
-{
-    default_method_store_index =
-        openssl_ctx_new_index(&default_method_store_method);
-
-    return default_method_store_index != -1;
-}
-
-static CRYPTO_ONCE default_method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_default_method_store_init)
-{
-    return OPENSSL_init_crypto(0, NULL)
-        && default_method_store_init();
-}
-
 /* Data to be passed through ossl_method_construct() */
 struct method_data_st {
+    OPENSSL_CTX *libctx;
     const char *name;
-    int nid;
+    int id;
     OSSL_METHOD_CONSTRUCT_METHOD *mcm;
-    void *(*method_from_dispatch)(int nid, const OSSL_DISPATCH *,
-                                  OSSL_PROVIDER *);
+    void *(*method_from_dispatch)(const OSSL_DISPATCH *, OSSL_PROVIDER *);
     int (*refcnt_up_method)(void *method);
     void (*destruct_method)(void *method);
-    int (*nid_method)(void *method);
 };
 
 /*
  * Generic routines to fetch / create EVP methods with ossl_method_construct()
  */
-static void *alloc_tmp_method_store(void)
+static void *alloc_tmp_method_store(OPENSSL_CTX *ctx)
 {
-    return ossl_method_store_new();
+    return ossl_method_store_new(ctx);
 }
 
  static void dealloc_tmp_method_store(void *store)
@@ -81,23 +62,28 @@ static void *alloc_tmp_method_store(void)
 
 static OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)
 {
-    if (!RUN_ONCE(&default_method_store_init_flag,
-                  do_default_method_store_init))
-        return NULL;
-    return openssl_ctx_get_data(libctx, default_method_store_index);
+    return openssl_ctx_get_data(libctx, OPENSSL_CTX_DEFAULT_METHOD_STORE_INDEX,
+                                &default_method_store_method);
 }
 
 static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
-                                   const char *propquery, void *data)
+                                   const char *name, const char *propquery,
+                                   void *data)
 {
     struct method_data_st *methdata = data;
     void *method = NULL;
+    OSSL_NAMEMAP *namemap;
+    int id;
 
     if (store == NULL
         && (store = get_default_method_store(libctx)) == NULL)
         return NULL;
 
-    (void)ossl_method_store_fetch(store, methdata->nid, propquery, &method);
+    if ((namemap = ossl_namemap_stored(libctx)) == NULL
+        || (id = ossl_namemap_add(namemap, name)) == 0)
+        return NULL;
+
+    (void)ossl_method_store_fetch(store, id, propquery, &method);
 
     if (method != NULL
         && !methdata->refcnt_up_method(method)) {
@@ -107,13 +93,15 @@ static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
 }
 
 static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
-                               const char *propdef,
-                               void *method, void *data)
+                               void *method, const char *name,
+                               const char *propdef, void *data)
 {
     struct method_data_st *methdata = data;
-    int nid = methdata->nid_method(method);
+    OSSL_NAMEMAP *namemap;
+    int id;
 
-    if (nid == NID_undef)
+    if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
+        || (id = ossl_namemap_add(namemap, name)) == 0)
         return 0;
 
     if (store == NULL
@@ -121,41 +109,18 @@ static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
         return 0;
 
     if (methdata->refcnt_up_method(method)
-        && ossl_method_store_add(store, nid, propdef, method,
+        && ossl_method_store_add(store, id, propdef, method,
                                  methdata->destruct_method))
         return 1;
     return 0;
 }
 
-static void *construct_method(const char *algorithm_name,
-                              const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
-                              void *data)
+static void *construct_method(const char *name, const OSSL_DISPATCH *fns,
+                              OSSL_PROVIDER *prov, void *data)
 {
     struct method_data_st *methdata = data;
-    void *method = NULL;
-    int nid = OBJ_sn2nid(algorithm_name);
-
-    if (nid == NID_undef) {
-        /* Create a new NID for that name on the fly */
-        ASN1_OBJECT tmpobj;
-
-        /* This is the same as OBJ_create() but without requiring a OID */
-        tmpobj.nid = OBJ_new_nid(1);
-        tmpobj.sn = tmpobj.ln = methdata->name;
-        tmpobj.flags = ASN1_OBJECT_FLAG_DYNAMIC;
-        tmpobj.length = 0;
-        tmpobj.data = NULL;
-
-        nid = OBJ_add_object(&tmpobj);
-    }
-
-    if (nid == NID_undef)
-        return NULL;
 
-    method = methdata->method_from_dispatch(nid, fns, prov);
-    if (method == NULL)
-        return NULL;
-    return method;
+    return methdata->method_from_dispatch(fns, prov);
 }
 
 static void destruct_method(void *method, void *data)
@@ -166,22 +131,22 @@ static void destruct_method(void *method, void *data)
 }
 
 void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
-                        const char *algorithm, const char *properties,
-                        void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
+                        const char *name, const char *properties,
+                        void *(*new_method)(const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*upref_method)(void *),
-                        void (*free_method)(void *),
-                        int (*nid_method)(void *))
+                        void (*free_method)(void *))
 {
     OSSL_METHOD_STORE *store = get_default_method_store(libctx);
-    int nid = OBJ_sn2nid(algorithm);
+    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
+    int id;
     void *method = NULL;
 
-    if (store == NULL)
+    if (store == NULL || namemap == NULL)
         return NULL;
 
-    if (nid == NID_undef
-        || !ossl_method_store_cache_get(store, nid, properties, &method)) {
+    if ((id = ossl_namemap_number(namemap, name)) == 0
+        || !ossl_method_store_cache_get(store, id, properties, &method)) {
         OSSL_METHOD_CONSTRUCT_METHOD mcm = {
             alloc_tmp_method_store,
             dealloc_tmp_method_store,
@@ -192,17 +157,16 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
         };
         struct method_data_st mcmdata;
 
-        mcmdata.nid = nid;
         mcmdata.mcm = &mcm;
+        mcmdata.libctx = libctx;
         mcmdata.method_from_dispatch = new_method;
         mcmdata.destruct_method = free_method;
         mcmdata.refcnt_up_method = upref_method;
         mcmdata.destruct_method = free_method;
-        mcmdata.nid_method = nid_method;
-        method = ossl_method_construct(libctx, operation_id, algorithm,
+        method = ossl_method_construct(libctx, operation_id, name,
                                        properties, 0 /* !force_cache */,
                                        &mcm, &mcmdata);
-        ossl_method_store_cache_set(store, nid, properties, method);
+        ossl_method_store_cache_set(store, id, properties, method);
     } else {
         upref_method(method);
     }
index 189c953..faaa69d 100644 (file)
@@ -17,6 +17,7 @@
 #include "internal/provider.h"
 #include "evp_locl.h"
 
+#if !defined(FIPS_MODE)
 int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 {
     int ret;
@@ -146,12 +147,12 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
     }
     return i;
 }
+#endif /* !defined(FIPS_MODE) */
 
 /* Convert the various cipher NIDs and dummies to a proper OID NID */
 int EVP_CIPHER_type(const EVP_CIPHER *ctx)
 {
     int nid;
-    ASN1_OBJECT *otmp;
     nid = EVP_CIPHER_nid(ctx);
 
     switch (nid) {
@@ -198,12 +199,19 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx)
         return NID_des_cfb64;
 
     default:
-        /* Check it has an OID and it is valid */
-        otmp = OBJ_nid2obj(nid);
-        if (OBJ_get0_data(otmp) == NULL)
-            nid = NID_undef;
-        ASN1_OBJECT_free(otmp);
-        return nid;
+#ifdef FIPS_MODE
+        return NID_undef;
+#else
+        {
+            /* Check it has an OID and it is valid */
+            ASN1_OBJECT *otmp = OBJ_nid2obj(nid);
+
+            if (OBJ_get0_data(otmp) == NULL)
+                nid = NID_undef;
+            ASN1_OBJECT_free(otmp);
+            return nid;
+        }
+#endif
     }
 }
 
@@ -232,8 +240,14 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                const unsigned char *in, unsigned int inl)
 {
     if (ctx->cipher->prov != NULL) {
+        size_t outl = 0;         /* ignored */
+        int blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
         if (ctx->cipher->ccipher != NULL)
-            return ctx->cipher->ccipher(ctx->provctx, out, in, (size_t)inl);
+            return
+                ctx->cipher->ccipher(ctx->provctx, out, &outl,
+                                     inl + (blocksize == 1 ? 0 : blocksize),
+                                     in, (size_t)inl);
         return 0;
     }
 
@@ -590,6 +604,8 @@ EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx)
     return ctx->pctx;
 }
 
+#if !defined(FIPS_MODE)
+/* TODO(3.0): EVP_DigestSign* not yet supported in FIPS module */
 void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
 {
     /*
@@ -608,6 +624,7 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
         EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
     }
 }
+#endif /* !defined(FIPS_MODE) */
 
 void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx)
 {
index 3172c49..8876b06 100644 (file)
@@ -56,7 +56,7 @@ struct evp_mac_ctx_st {
 } /* EVP_MAC_CTX */;
 
 struct evp_kdf_ctx_st {
-    const EVP_KDF_METHOD *kmeth;
+    const EVP_KDF *meth;         /* Method structure */
     EVP_KDF_IMPL *impl;          /* Algorithm-specific data */
 } /* EVP_KDF_CTX */ ;
 
@@ -91,8 +91,7 @@ int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
 
 void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
                         const char *algorithm, const char *properties,
-                        void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
+                        void *(*new_method)(const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*upref_method)(void *),
-                        void (*free_method)(void *),
-                        int (*nid_method)(void *));
+                        void (*free_method)(void *));
index de2ab23..6131d8e 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2018, Oracle and/or its affiliates.  All rights reserved.
+ * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, Oracle and/or its affiliates.  All rights reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #include "internal/numbers.h"
 #include "evp_locl.h"
 
-typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
-
-/* This array needs to be in order of NIDs */
-static const EVP_KDF_METHOD *standard_methods[] = {
-    &pbkdf2_kdf_meth,
-#ifndef OPENSSL_NO_SCRYPT
-    &scrypt_kdf_meth,
-#endif
-    &tls1_prf_kdf_meth,
-    &hkdf_kdf_meth,
-    &sshkdf_kdf_meth,
-    &ss_kdf_meth
-};
-
-DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
-                           kmeth);
-
-static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
-                     const EVP_KDF_METHOD *const *b)
+EVP_KDF_CTX *EVP_KDF_CTX_new(const EVP_KDF *kdf)
 {
-    return ((*a)->type - (*b)->type);
-}
-
-IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
-                             kmeth);
+    EVP_KDF_CTX *ctx = NULL;
 
-static const EVP_KDF_METHOD *kdf_meth_find(int type)
-{
-    EVP_KDF_METHOD tmp;
-    const EVP_KDF_METHOD *t = &tmp, **ret;
-
-    tmp.type = type;
-    ret = OBJ_bsearch_kmeth(&t, standard_methods,
-                            OSSL_NELEM(standard_methods));
-    if (ret == NULL || *ret == NULL)
+    if (kdf == NULL)
         return NULL;
 
-    return *ret;
+    ctx = OPENSSL_zalloc(sizeof(EVP_KDF_CTX));
+    if (ctx == NULL || (ctx->impl = kdf->new()) == NULL) {
+        EVPerr(EVP_F_EVP_KDF_CTX_NEW, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(ctx);
+        ctx = NULL;
+    } else {
+        ctx->meth = kdf;
+    }
+    return ctx;
 }
 
 EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
 {
-    EVP_KDF_CTX *ret;
-    const EVP_KDF_METHOD *kmeth;
+    const EVP_KDF *kdf = EVP_get_kdfbynid(id);
 
-    kmeth = kdf_meth_find(id);
-    if (kmeth == NULL) {
-        EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
-        return NULL;
-    }
-
-    ret = OPENSSL_zalloc(sizeof(*ret));
-    if (ret == NULL) {
-        EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
+    return EVP_KDF_CTX_new(kdf);
+}
 
-    if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
-        EVP_KDF_CTX_free(ret);
-        return NULL;
-    }
+int EVP_KDF_nid(const EVP_KDF *kdf)
+{
+    return kdf->type;
+}
 
-    ret->kmeth = kmeth;
-    return ret;
+const EVP_KDF *EVP_KDF_CTX_kdf(EVP_KDF_CTX *ctx)
+{
+    return ctx->meth;
 }
 
 void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
@@ -91,7 +60,7 @@ void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
     if (ctx == NULL)
         return;
 
-    ctx->kmeth->free(ctx->impl);
+    ctx->meth->free(ctx->impl);
     OPENSSL_free(ctx);
 }
 
@@ -100,8 +69,8 @@ void EVP_KDF_reset(EVP_KDF_CTX *ctx)
     if (ctx == NULL)
         return;
 
-    if (ctx->kmeth->reset != NULL)
-        ctx->kmeth->reset(ctx->impl);
+    if (ctx->meth->reset != NULL)
+        ctx->meth->reset(ctx->impl);
 }
 
 int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
@@ -124,7 +93,7 @@ int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
     if (ctx == NULL)
         return 0;
 
-    return ctx->kmeth->ctrl(ctx->impl, cmd, args);
+    return ctx->meth->ctrl(ctx->impl, cmd, args);
 }
 
 int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
@@ -134,12 +103,12 @@ int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
     if (ctx == NULL)
         return 0;
 
-    if (ctx->kmeth->ctrl_str == NULL) {
+    if (ctx->meth->ctrl_str == NULL) {
         EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
     }
 
-    ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
+    ret = ctx->meth->ctrl_str(ctx->impl, type, value);
     if (ret == -2)
         EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
 
@@ -151,10 +120,10 @@ size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
     if (ctx == NULL)
         return 0;
 
-    if (ctx->kmeth->size == NULL)
+    if (ctx->meth->size == NULL)
         return SIZE_MAX;
 
-    return ctx->kmeth->size(ctx->impl);
+    return ctx->meth->size(ctx->impl);
 }
 
 int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
@@ -162,6 +131,5 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
     if (ctx == NULL)
         return 0;
 
-    return ctx->kmeth->derive(ctx->impl, key, keylen);
+    return ctx->meth->derive(ctx->impl, key, keylen);
 }
-
index 4e17926..5237bca 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
+#include <openssl/kdf.h>
 #include "internal/objects.h"
 #include <openssl/x509.h>
 #include "internal/evp_int.h"
@@ -71,6 +72,23 @@ int EVP_add_mac(const EVP_MAC *m)
     return r;
 }
 
+/* TODO(3.0) Is this needed after changing to providers? */
+int EVP_add_kdf(const EVP_KDF *k)
+{
+    int r;
+
+    if (k == NULL)
+        return 0;
+
+    r = OBJ_NAME_add(OBJ_nid2sn(k->type), OBJ_NAME_TYPE_KDF_METH,
+                     (const char *)k);
+    if (r == 0)
+        return 0;
+    r = OBJ_NAME_add(OBJ_nid2ln(k->type), OBJ_NAME_TYPE_KDF_METH,
+                     (const char *)k);
+    return r;
+}
+
 const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
 {
     const EVP_CIPHER *cp;
@@ -104,9 +122,22 @@ const EVP_MAC *EVP_get_macbyname(const char *name)
     return mp;
 }
 
+/* TODO(3.0) Is this API needed after implementing providers? */
+const EVP_KDF *EVP_get_kdfbyname(const char *name)
+{
+    const EVP_KDF *kdf;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_KDFS, NULL))
+        return NULL;
+
+    kdf = (const EVP_KDF *)OBJ_NAME_get(name, OBJ_NAME_TYPE_KDF_METH);
+    return kdf;
+}
+
 void evp_cleanup_int(void)
 {
     OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH);
+    OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH);
     OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
     OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
     /*
@@ -207,6 +238,7 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
 }
 
+/* TODO(3.0) Are these do_all API's needed for MAC? */
 struct doall_mac {
     void *arg;
     void (*fn) (const EVP_MAC *ciph,
@@ -250,4 +282,3 @@ void EVP_MAC_do_all_sorted(void (*fn)
     dc.arg = arg;
     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
 }
-
index 5abc2b9..0f5158e 100644 (file)
@@ -28,7 +28,7 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
     EVP_MD_CTX *ctx;
     unsigned char md_tmp[EVP_MAX_MD_SIZE];
     unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
-    int i;
+    int i, ivl, kl;
     PBEPARAM *pbe;
     int saltlen, iter;
     unsigned char *salt;
@@ -48,6 +48,17 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
         return 0;
     }
 
+    ivl = EVP_CIPHER_iv_length(cipher);
+    if (ivl < 0 || ivl > 16) {
+        EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_INVALID_IV_LENGTH);
+        return 0;
+    }
+    kl = EVP_CIPHER_key_length(cipher);
+    if (kl < 0 || kl > (int)sizeof(md_tmp)) {
+        EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_INVALID_KEY_LENGTH);
+        return 0;
+    }
+
     if (!pbe->iter)
         iter = 1;
     else
@@ -86,11 +97,8 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
         if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
             goto err;
     }
-    OPENSSL_assert(EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp));
-    memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher));
-    OPENSSL_assert(EVP_CIPHER_iv_length(cipher) <= 16);
-    memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)),
-           EVP_CIPHER_iv_length(cipher));
+    memcpy(key, md_tmp, kl);
+    memcpy(iv, md_tmp + (16 - ivl), ivl);
     if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de))
         goto err;
     OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
index ac5b974..c231a32 100644 (file)
@@ -134,7 +134,7 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              const EVP_CIPHER *c, const EVP_MD *md, int en_de)
 {
     unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
-    int saltlen, iter;
+    int saltlen, iter, t;
     int rv = 0;
     unsigned int keylen = 0;
     int prf_nid, hmac_md_nid;
@@ -157,7 +157,12 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
         goto err;
     }
 
-    keylen = EVP_CIPHER_CTX_key_length(ctx);
+    t = EVP_CIPHER_CTX_key_length(ctx);
+    if (t < 0) {
+        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_INVALID_KEY_LENGTH);
+        goto err;
+    }
+    keylen = t;
 
     /* Now check the parameters of the kdf */
 
index 5f83191..055420a 100644 (file)
 #include "internal/cryptlib_int.h"
 #include "internal/thread_once.h"
 
-/*
- * Each structure type (sometimes called a class), that supports
- * exdata has a stack of callbacks for each instance.
- */
-struct ex_callback_st {
-    long argl;                  /* Arbitrary long */
-    void *argp;                 /* Arbitrary void * */
-    CRYPTO_EX_new *new_func;
-    CRYPTO_EX_free *free_func;
-    CRYPTO_EX_dup *dup_func;
-};
-
-/*
- * The state for each class.  This could just be a typedef, but
- * a structure allows future changes.
- */
-typedef struct ex_callbacks_st {
-    STACK_OF(EX_CALLBACK) *meth;
-} EX_CALLBACKS;
-
-static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
-
-static CRYPTO_RWLOCK *ex_data_lock = NULL;
-static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT;
-
-DEFINE_RUN_ONCE_STATIC(do_ex_data_init)
+int do_ex_data_init(OPENSSL_CTX *ctx)
 {
-    if (!OPENSSL_init_crypto(0, NULL))
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+
+    if (global == NULL)
         return 0;
-    ex_data_lock = CRYPTO_THREAD_lock_new();
-    return ex_data_lock != NULL;
+
+    global->ex_data_lock = CRYPTO_THREAD_lock_new();
+    return global->ex_data_lock != NULL;
 }
 
 /*
  * Return the EX_CALLBACKS from the |ex_data| array that corresponds to
  * a given class.  On success, *holds the lock.*
  */
-static EX_CALLBACKS *get_and_lock(int class_index)
+static EX_CALLBACKS *get_and_lock(OPENSSL_CTX *ctx, int class_index)
 {
     EX_CALLBACKS *ip;
+    OSSL_EX_DATA_GLOBAL *global = NULL;
 
     if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) {
         CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT);
         return NULL;
     }
 
-    if (!RUN_ONCE(&ex_data_init, do_ex_data_init)) {
-        CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    if (ex_data_lock == NULL) {
+    global = openssl_ctx_get_ex_data_global(ctx);
+    if (global->ex_data_lock == NULL) {
         /*
          * This can happen in normal operation when using CRYPTO_mem_leaks().
          * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans
@@ -74,8 +49,8 @@ static EX_CALLBACKS *get_and_lock(int class_index)
          return NULL;
     }
 
-    ip = &ex_data[class_index];
-    CRYPTO_THREAD_write_lock(ex_data_lock);
+    ip = &global->ex_data[class_index];
+    CRYPTO_THREAD_write_lock(global->ex_data_lock);
     return ip;
 }
 
@@ -90,19 +65,23 @@ static void cleanup_cb(EX_CALLBACK *funcs)
  * called under potential race-conditions anyway (it's for program shutdown
  * after all).
  */
-void crypto_cleanup_all_ex_data_int(void)
+void crypto_cleanup_all_ex_data_int(OPENSSL_CTX *ctx)
 {
     int i;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+
+    if (global == NULL)
+        return;
 
     for (i = 0; i < CRYPTO_EX_INDEX__COUNT; ++i) {
-        EX_CALLBACKS *ip = &ex_data[i];
+        EX_CALLBACKS *ip = &global->ex_data[i];
 
         sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb);
         ip->meth = NULL;
     }
 
-    CRYPTO_THREAD_lock_free(ex_data_lock);
-    ex_data_lock = NULL;
+    CRYPTO_THREAD_lock_free(global->ex_data_lock);
+    global->ex_data_lock = NULL;
 }
 
 
@@ -127,12 +106,17 @@ static int dummy_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
     return 1;
 }
 
-int CRYPTO_free_ex_index(int class_index, int idx)
+int crypto_free_ex_index_ex(OPENSSL_CTX *ctx, int class_index, int idx)
 {
-    EX_CALLBACKS *ip = get_and_lock(class_index);
+    EX_CALLBACKS *ip = get_and_lock(ctx, class_index);
     EX_CALLBACK *a;
     int toret = 0;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+
+    if (global == NULL)
+        return 0;
 
+    ip = get_and_lock(ctx, class_index);
     if (ip == NULL)
         return 0;
     if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth))
@@ -145,21 +129,32 @@ int CRYPTO_free_ex_index(int class_index, int idx)
     a->free_func = dummy_free;
     toret = 1;
 err:
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
     return toret;
 }
 
+int CRYPTO_free_ex_index(int class_index, int idx)
+{
+    return crypto_free_ex_index_ex(NULL, class_index, idx);
+}
+
 /*
  * Register a new index.
  */
-int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
-                            CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
-                            CRYPTO_EX_free *free_func)
+int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index, long argl,
+                               void *argp, CRYPTO_EX_new *new_func,
+                               CRYPTO_EX_dup *dup_func,
+                               CRYPTO_EX_free *free_func)
 {
     int toret = -1;
     EX_CALLBACK *a;
-    EX_CALLBACKS *ip = get_and_lock(class_index);
+    EX_CALLBACKS *ip;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
 
+    if (global == NULL)
+        return -1;
+
+    ip = get_and_lock(ctx, class_index);
     if (ip == NULL)
         return -1;
 
@@ -169,14 +164,14 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
          * "app_data" routines use ex_data index zero.  See RT 3710. */
         if (ip->meth == NULL
             || !sk_EX_CALLBACK_push(ip->meth, NULL)) {
-            CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+            CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX, ERR_R_MALLOC_FAILURE);
             goto err;
         }
     }
 
     a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a));
     if (a == NULL) {
-        CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+        CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     a->argl = argl;
@@ -186,7 +181,7 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
     a->free_func = free_func;
 
     if (!sk_EX_CALLBACK_push(ip->meth, NULL)) {
-        CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX, ERR_R_MALLOC_FAILURE);
+        CRYPTOerr(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX_EX, ERR_R_MALLOC_FAILURE);
         OPENSSL_free(a);
         goto err;
     }
@@ -194,10 +189,18 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
     (void)sk_EX_CALLBACK_set(ip->meth, toret, a);
 
  err:
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
     return toret;
 }
 
+int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
+                            CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+                            CRYPTO_EX_free *free_func)
+{
+    return crypto_get_ex_new_index_ex(NULL, class_index, argl, argp, new_func,
+                                      dup_func, free_func);
+}
+
 /*
  * Initialise a new CRYPTO_EX_DATA for use in a particular class - including
  * calling new() callbacks for each index in the class used by this variable
@@ -205,17 +208,24 @@ int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
  * in the lock, then using them outside the lock. Note this only applies
  * to the global "ex_data" state (ie. class definitions), not 'ad' itself.
  */
-int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+int crypto_new_ex_data_ex(OPENSSL_CTX *ctx, int class_index, void *obj,
+                          CRYPTO_EX_DATA *ad)
 {
     int mx, i;
     void *ptr;
     EX_CALLBACK **storage = NULL;
     EX_CALLBACK *stack[10];
-    EX_CALLBACKS *ip = get_and_lock(class_index);
+    EX_CALLBACKS *ip;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ctx);
+
+    if (global == NULL)
+        return 0;
 
+    ip = get_and_lock(ctx, class_index);
     if (ip == NULL)
         return 0;
 
+    ad->ctx = ctx;
     ad->sk = NULL;
 
     mx = sk_EX_CALLBACK_num(ip->meth);
@@ -228,10 +238,10 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
             for (i = 0; i < mx; i++)
                 storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
     }
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
 
     if (mx > 0 && storage == NULL) {
-        CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA, ERR_R_MALLOC_FAILURE);
+        CRYPTOerr(CRYPTO_F_CRYPTO_NEW_EX_DATA_EX, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     for (i = 0; i < mx; i++) {
@@ -246,6 +256,11 @@ int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
     return 1;
 }
 
+int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+    return crypto_new_ex_data_ex(NULL, class_index, obj, ad);
+}
+
 /*
  * Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks
  * for each index in the class used by this variable
@@ -259,11 +274,16 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
     EX_CALLBACK **storage = NULL;
     EX_CALLBACKS *ip;
     int toret = 0;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(from->ctx);
+
+    if (global == NULL)
+        return 0;
 
+    to->ctx = from->ctx;
     if (from->sk == NULL)
         /* Nothing to copy over */
         return 1;
-    if ((ip = get_and_lock(class_index)) == NULL)
+    if ((ip = get_and_lock(from->ctx, class_index)) == NULL)
         return 0;
 
     mx = sk_EX_CALLBACK_num(ip->meth);
@@ -279,7 +299,7 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
             for (i = 0; i < mx; i++)
                 storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
     }
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
 
     if (mx == 0)
         return 1;
@@ -325,8 +345,12 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
     EX_CALLBACK *f;
     EX_CALLBACK *stack[10];
     EX_CALLBACK **storage = NULL;
+    OSSL_EX_DATA_GLOBAL *global;
 
-    if ((ip = get_and_lock(class_index)) == NULL)
+    if ((ip = get_and_lock(ad->ctx, class_index)) == NULL)
+        goto err;
+    global = openssl_ctx_get_ex_data_global(ad->ctx);
+    if (global == NULL)
         goto err;
 
     mx = sk_EX_CALLBACK_num(ip->meth);
@@ -339,15 +363,15 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
             for (i = 0; i < mx; i++)
                 storage[i] = sk_EX_CALLBACK_value(ip->meth, i);
     }
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
 
     for (i = 0; i < mx; i++) {
         if (storage != NULL)
             f = storage[i];
         else {
-            CRYPTO_THREAD_write_lock(ex_data_lock);
+            CRYPTO_THREAD_write_lock(global->ex_data_lock);
             f = sk_EX_CALLBACK_value(ip->meth, i);
-            CRYPTO_THREAD_unlock(ex_data_lock);
+            CRYPTO_THREAD_unlock(global->ex_data_lock);
         }
         if (f != NULL && f->free_func != NULL) {
             ptr = CRYPTO_get_ex_data(ad, i);
@@ -360,6 +384,7 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
  err:
     sk_void_free(ad->sk);
     ad->sk = NULL;
+    ad->ctx = NULL;
 }
 
 /*
@@ -372,6 +397,10 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
     EX_CALLBACK *f;
     EX_CALLBACKS *ip;
     void *curval;
+    OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx);
+
+    if (global == NULL)
+        return 0;
 
     curval = CRYPTO_get_ex_data(ad, idx);
 
@@ -379,11 +408,11 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
     if (curval != NULL)
         return 1;
 
-    ip = get_and_lock(class_index);
+    ip = get_and_lock(ad->ctx, class_index);
     if (ip == NULL)
         return 0;
     f = sk_EX_CALLBACK_value(ip->meth, idx);
-    CRYPTO_THREAD_unlock(ex_data_lock);
+    CRYPTO_THREAD_unlock(global->ex_data_lock);
 
     /*
      * This should end up calling CRYPTO_set_ex_data(), which allocates
@@ -432,3 +461,8 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
         return NULL;
     return sk_void_value(ad->sk, idx);
 }
+
+OPENSSL_CTX *crypto_ex_data_get_openssl_ctx(const CRYPTO_EX_DATA *ad)
+{
+    return ad->ctx;
+}
index b3d9694..43932a4 100644 (file)
@@ -151,10 +151,11 @@ const EVP_MD *evp_keccak_kmac256(void);
  * object database.
  */
 int EVP_add_mac(const EVP_MAC *mac);
+int EVP_add_kdf(const EVP_KDF *kdf);
 
 /* struct evp_kdf_impl_st is defined by the implementation */
 typedef struct evp_kdf_impl_st EVP_KDF_IMPL;
-typedef struct {
+struct evp_kdf_st {
     int type;
     EVP_KDF_IMPL *(*new) (void);
     void (*free) (EVP_KDF_IMPL *impl);
@@ -163,14 +164,15 @@ typedef struct {
     int (*ctrl_str) (EVP_KDF_IMPL *impl, const char *type, const char *value);
     size_t (*size) (EVP_KDF_IMPL *impl);
     int (*derive) (EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen);
-} EVP_KDF_METHOD;
+};
 
-extern const EVP_KDF_METHOD pbkdf2_kdf_meth;
-extern const EVP_KDF_METHOD scrypt_kdf_meth;
-extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
-extern const EVP_KDF_METHOD hkdf_kdf_meth;
-extern const EVP_KDF_METHOD sshkdf_kdf_meth;
-extern const EVP_KDF_METHOD ss_kdf_meth;
+extern const EVP_KDF pbkdf2_kdf_meth;
+extern const EVP_KDF scrypt_kdf_meth;
+extern const EVP_KDF tls1_prf_kdf_meth;
+extern const EVP_KDF hkdf_kdf_meth;
+extern const EVP_KDF sshkdf_kdf_meth;
+extern const EVP_KDF ss_kdf_meth;
+extern const EVP_KDF x963_kdf_meth;
 
 struct evp_md_st {
     /* nid */
@@ -528,6 +530,7 @@ struct evp_pkey_st {
 void openssl_add_all_ciphers_int(void);
 void openssl_add_all_digests_int(void);
 void openssl_add_all_macs_int(void);
+void openssl_add_all_kdfs_int(void);
 void evp_cleanup_int(void);
 void evp_app_cleanup_int(void);
 
index 43fe1a6..58fff70 100644 (file)
@@ -293,6 +293,26 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_macs, ossl_init_add_all_macs)
     return 1;
 }
 
+static CRYPTO_ONCE add_all_kdfs = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_kdfs)
+{
+    /*
+     * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
+     * pulling in all the macs during static linking
+     */
+#ifndef OPENSSL_NO_AUTOALGINIT
+    OSSL_TRACE(INIT, "openssl_add_all_kdfs_int()\n");
+    openssl_add_all_kdfs_int();
+#endif
+    return 1;
+}
+
+DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_kdfs, ossl_init_add_all_kdfs)
+{
+    /* Do nothing */
+    return 1;
+}
+
 static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
 static int config_inited = 0;
 static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
@@ -468,6 +488,11 @@ void OPENSSL_cleanup(void)
     OPENSSL_INIT_STOP *currhandler, *lasthandler;
     CRYPTO_THREAD_LOCAL key;
 
+    /*
+     * TODO(3.0): This function needs looking at with a view to moving most/all
+     * of this into onfree handlers in OPENSSL_CTX.
+     */
+
     /* If we've not been inited then no need to deinit */
     if (!base_inited)
         return;
@@ -526,7 +551,7 @@ void OPENSSL_cleanup(void)
      * - rand_cleanup_int could call an ENGINE's RAND cleanup function so
      * must be called before engine_cleanup_int()
      * - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up
-     * before the ex data handlers are wiped in CRYPTO_cleanup_all_ex_data().
+     * before the ex data handlers are wiped during default openssl_ctx deinit.
      * - conf_modules_free_int() can end up in ENGINE code so must be called
      * before engine_cleanup_int()
      * - ENGINEs and additional EVP algorithms might use added OIDs names so
@@ -540,6 +565,7 @@ void OPENSSL_cleanup(void)
 
     OSSL_TRACE(INIT, "OPENSSL_cleanup: conf_modules_free_int()\n");
     conf_modules_free_int();
+
 #ifndef OPENSSL_NO_ENGINE
     OSSL_TRACE(INIT, "OPENSSL_cleanup: engine_cleanup_int()\n");
     engine_cleanup_int();
@@ -547,8 +573,8 @@ void OPENSSL_cleanup(void)
     OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_store_cleanup_int()\n");
     ossl_store_cleanup_int();
 
-    OSSL_TRACE(INIT, "OPENSSL_cleanup: crypto_cleanup_all_ex_data_int()\n");
-    crypto_cleanup_all_ex_data_int();
+    OSSL_TRACE(INIT, "OPENSSL_cleanup: openssl_ctx_default_deinit()\n");
+    openssl_ctx_default_deinit();
 
     OSSL_TRACE(INIT, "OPENSSL_cleanup: bio_cleanup()\n");
     bio_cleanup();
@@ -578,6 +604,11 @@ void OPENSSL_cleanup(void)
  */
 int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
 {
+    /*
+     * TODO(3.0): This function needs looking at with a view to moving most/all
+     * of this into OPENSSL_CTX.
+     */
+
     if (stopped) {
         if (!(opts & OPENSSL_INIT_BASE_ONLY))
             CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL);
@@ -655,6 +686,15 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
             && !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs))
         return 0;
 
+    if ((opts & OPENSSL_INIT_NO_ADD_ALL_KDFS)
+            && !RUN_ONCE_ALT(&add_all_kdfs, ossl_init_no_add_all_kdfs,
+                             ossl_init_add_all_kdfs))
+        return 0;
+
+    if ((opts & OPENSSL_INIT_ADD_ALL_KDFS)
+            && !RUN_ONCE(&add_all_kdfs, ossl_init_add_all_kdfs))
+        return 0;
+
     if ((opts & OPENSSL_INIT_ATFORK)
             && !openssl_init_fork_handlers())
         return 0;
index c8b3f03..f759e30 100644 (file)
@@ -229,7 +229,7 @@ static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
     }
 }
 
-const EVP_KDF_METHOD hkdf_kdf_meth = {
+const EVP_KDF hkdf_kdf_meth = {
     EVP_KDF_HKDF,
     kdf_hkdf_new,
     kdf_hkdf_free,
index 84c330f..49028ab 100644 (file)
@@ -65,6 +65,7 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
     {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_NEW, 0), "sskdf_new"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_SSKDF_SIZE, 0), "sskdf_size"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_X963KDF_DERIVE, 0), "x963kdf_derive"},
     {0, NULL}
 };
 
@@ -84,6 +85,7 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SESSION_ID), "missing session id"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_TYPE), "missing type"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_XCGHASH), "missing xcghash"},
+    {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_NOT_SUPPORTED), "not supported"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE),
     "unknown parameter type"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNSUPPORTED_MAC_TYPE),
index bf1ac6d..7009dfd 100644 (file)
@@ -180,7 +180,7 @@ static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
                             impl->md, key, keylen);
 }
 
-const EVP_KDF_METHOD pbkdf2_kdf_meth = {
+const EVP_KDF pbkdf2_kdf_meth = {
     EVP_KDF_PBKDF2,
     kdf_pbkdf2_new,
     kdf_pbkdf2_free,
index ee77f1e..29ceeb3 100644 (file)
@@ -266,7 +266,7 @@ static int kdf_scrypt_derive(EVP_KDF_IMPL *impl, unsigned char *key,
                       impl->maxmem_bytes, key, keylen);
 }
 
-const EVP_KDF_METHOD scrypt_kdf_meth = {
+const EVP_KDF scrypt_kdf_meth = {
     EVP_KDF_SCRYPT,
     kdf_scrypt_new,
     kdf_scrypt_free,
index 300e1ad..4701c9c 100644 (file)
@@ -125,6 +125,9 @@ static int kdf_sshkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
         return 0;
     }
 
+    if (strcmp(type, "digest") == 0)
+        return kdf_md2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
+    /* alias, for historical reasons */
     if (strcmp(type, "md") == 0)
         return kdf_md2ctrl(impl, kdf_sshkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
 
@@ -200,7 +203,7 @@ static int kdf_sshkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
                   impl->type, key, keylen);
 }
 
-const EVP_KDF_METHOD sshkdf_kdf_meth = {
+const EVP_KDF sshkdf_kdf_meth = {
     EVP_KDF_SSHKDF,
     kdf_sshkdf_new,
     kdf_sshkdf_free,
index 89e4e5b..92bf995 100644 (file)
@@ -66,10 +66,16 @@ static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
 /*
  * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
  * Section 4. One-Step Key Derivation using H(x) = hash(x)
+ * Note: X9.63 also uses this code with the only difference being that the
+ * counter is appended to the secret 'z'.
+ * i.e.
+ *   result[i] = Hash(counter || z || info) for One Step OR
+ *   result[i] = Hash(z || counter || info) for X9.63.
  */
 static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
                           const unsigned char *z, size_t z_len,
                           const unsigned char *info, size_t info_len,
+                          unsigned int append_ctr,
                           unsigned char *derived_key, size_t derived_key_len)
 {
     int ret = 0, hlen;
@@ -104,8 +110,9 @@ static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
         c[3] = (unsigned char)(counter & 0xff);
 
         if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
-                && EVP_DigestUpdate(ctx, c, sizeof(c))
+                && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
                 && EVP_DigestUpdate(ctx, z, z_len)
+                && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
                 && EVP_DigestUpdate(ctx, info, info_len)))
             goto end;
         if (len >= out_len) {
@@ -468,11 +475,32 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
             return 0;
         }
         return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len,
-                              impl->info, impl->info_len, key, keylen);
+                              impl->info, impl->info_len, 0, key, keylen);
     }
 }
 
-const EVP_KDF_METHOD ss_kdf_meth = {
+static int x963kdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
+{
+    if (impl->secret == NULL) {
+        KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_MISSING_SECRET);
+        return 0;
+    }
+
+    if (impl->mac != NULL) {
+        KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_NOT_SUPPORTED);
+        return 0;
+    } else {
+        /* H(x) = hash */
+        if (impl->md == NULL) {
+            KDFerr(KDF_F_X963KDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+            return 0;
+        }
+        return SSKDF_hash_kdm(impl->md, impl->secret, impl->secret_len,
+                              impl->info, impl->info_len, 1, key, keylen);
+    }
+}
+
+const EVP_KDF ss_kdf_meth = {
     EVP_KDF_SS,
     sskdf_new,
     sskdf_free,
@@ -482,3 +510,14 @@ const EVP_KDF_METHOD ss_kdf_meth = {
     sskdf_size,
     sskdf_derive
 };
+
+const EVP_KDF x963_kdf_meth = {
+    EVP_KDF_X963,
+    sskdf_new,
+    sskdf_free,
+    sskdf_reset,
+    sskdf_ctrl,
+    sskdf_ctrl_str,
+    sskdf_size,
+    x963kdf_derive
+};
index 1f8374f..913af29 100644 (file)
@@ -157,7 +157,7 @@ static int kdf_tls1_prf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
                         key, keylen);
 }
 
-const EVP_KDF_METHOD tls1_prf_kdf_meth = {
+const EVP_KDF tls1_prf_kdf_meth = {
     EVP_KDF_TLS1_PRF,
     kdf_tls1_prf_new,
     kdf_tls1_prf_free,
index 30797f2..0aa12a1 100644 (file)
@@ -1,3 +1,5 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
         lhash.c lh_stats.c
+SOURCE[../../providers/fips]=\
+        lhash.c
index cd332c4..65d32f3 100644 (file)
@@ -33,8 +33,8 @@
 #   include <linux/mman.h>
 #   include <errno.h>
 #  endif
+#  include <sys/param.h>
 # endif
-# include <sys/param.h>
 # include <sys/stat.h>
 # include <fcntl.h>
 #endif
index 9edf027..bfa2d46 100644 (file)
@@ -425,7 +425,7 @@ size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
 
     M *= 2;
     M += 2;
-    if (len < M)
+    if (len != M)
         return 0;
     memcpy(tag, ctx->cmac.c, M);
     return M;
index f374d19..ec9e131 100644 (file)
@@ -585,52 +585,32 @@ const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
     return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
 }
 
-const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
+const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
                             int size,
                             int (*cmp) (const void *, const void *),
                             int flags)
 {
-    const char *base = base_;
-    int l, h, i = 0, c = 0;
-    const char *p = NULL;
+    const char *p = ossl_bsearch(key, base, num, size, cmp, flags);
 
-    if (num == 0)
-        return NULL;
-    l = 0;
-    h = num;
-    while (l < h) {
-        i = (l + h) / 2;
-        p = &(base[i * size]);
-        c = (*cmp) (key, p);
-        if (c < 0)
-            h = i;
-        else if (c > 0)
-            l = i + 1;
-        else
-            break;
-    }
 #ifdef CHARSET_EBCDIC
     /*
      * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
      * don't have perl (yet), we revert to a *LINEAR* search when the object
      * wasn't found in the binary search.
      */
-    if (c != 0) {
+    if (p == NULL) {
+        const char *base_ = base;
+        int l, h, i = 0, c = 0;
+
         for (i = 0; i < num; ++i) {
-            p = &(base[i * size]);
+            p = &(base_[i * size]);
             c = (*cmp) (key, p);
-            if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
+            if (c == 0
+                || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
                 return p;
         }
     }
 #endif
-    if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
-        p = NULL;
-    else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) {
-        while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0)
-            i--;
-        p = &(base[i * size]);
-    }
     return p;
 }
 
index c778d45..876bab2 100644 (file)
@@ -1070,7 +1070,7 @@ static const unsigned char so[7775] = {
     0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,       /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */
     0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01,  /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */
     0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,       /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */
-    0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01,  /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
+    0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01,  /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
     0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02,  /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */
     0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03,  /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */
     0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04,  /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */
@@ -1080,7 +1080,7 @@ static const unsigned char so[7775] = {
     0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75,       /* [ 7766] OBJ_SM2_with_SM3 */
 };
 
-#define NUM_NID 1206
+#define NUM_NID 1207
 static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"UNDEF", "undefined", NID_undef},
     {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2288,9 +2288,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"SSHKDF", "sshkdf", NID_sshkdf},
     {"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7766]},
     {"SSKDF", "sskdf", NID_sskdf},
+    {"X963KDF", "x963kdf", NID_x963kdf},
 };
 
-#define NUM_SN 1197
+#define NUM_SN 1198
 static const unsigned int sn_objs[NUM_SN] = {
      364,    /* "AD_DVCS" */
      419,    /* "AES-128-CBC" */
@@ -2591,6 +2592,7 @@ static const unsigned int sn_objs[NUM_SN] = {
      378,    /* "X500algorithms" */
       12,    /* "X509" */
      184,    /* "X9-57" */
+    1206,    /* "X963KDF" */
      185,    /* "X9cm" */
      125,    /* "ZLIB" */
      478,    /* "aRecord" */
@@ -3491,7 +3493,7 @@ static const unsigned int sn_objs[NUM_SN] = {
     1093,    /* "x509ExtAdmission" */
 };
 
-#define NUM_LN 1197
+#define NUM_LN 1198
 static const unsigned int ln_objs[NUM_LN] = {
      363,    /* "AD Time Stamping" */
      405,    /* "ANSI X9.62" */
@@ -4689,6 +4691,7 @@ static const unsigned int ln_objs[NUM_LN] = {
      503,    /* "x500UniqueIdentifier" */
      158,    /* "x509Certificate" */
      160,    /* "x509Crl" */
+    1206,    /* "x963kdf" */
      125,    /* "zlib compression" */
 };
 
@@ -5401,7 +5404,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
     1177,    /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */
     1178,    /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */
     1181,    /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */
-    1183,    /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 1 1 */
+    1183,    /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */
     1148,    /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */
     1184,    /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */
     1185,    /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */
index 44820a7..e0969fe 100644 (file)
@@ -1203,3 +1203,4 @@ blake2smac                1202
 sshkdf         1203
 SM2_with_SM3           1204
 sskdf          1205
+x963kdf                1206
index 2240916..5664389 100644 (file)
@@ -1369,7 +1369,7 @@ id-tc26-algorithms 7      :       id-tc26-wrap
 id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma
 id-tc26-wrap-gostr3412-2015-magma 1    : id-tc26-wrap-gostr3412-2015-magma-kexp15
 id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik
-id-tc26-wrap-gostr3412-2015-magma 1    : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
+id-tc26-wrap-gostr3412-2015-kuznyechik 1       : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
 
 id-tc26 2              : id-tc26-constants
 
@@ -1617,6 +1617,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
 # NID for SSKDF
                             : SSKDF              : sskdf
 
+# NID for X963-2001 KDF
+                            : X963KDF            : x963kdf
+
 # RFC 4556
 1 3 6 1 5 2 3 : id-pkinit
 id-pkinit 4                     : pkInitClientAuth      : PKINIT Client Auth
index bdb1fa9..183884f 100644 (file)
@@ -156,12 +156,54 @@ OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf,
 
 int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
 {
-    if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
+    int64_t i64;
+    uint32_t u32;
+    uint64_t u64;
+    double d;
+
+    if (val == NULL || p == NULL )
         return 0;
 
-    if (p->data_size == sizeof(int32_t)) {
-        *val = *(const int32_t *)p->data;
-        return 1;
+    if (p->data_type == OSSL_PARAM_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            *val = *(const int32_t *)p->data;
+            return 1;
+        case sizeof(int64_t):
+            i64 = *(const int64_t *)p->data;
+            if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
+                *val = (int32_t)i64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            u32 = *(const uint32_t *)p->data;
+            if (u32 <= INT32_MAX) {
+                *val = (int32_t)u32;
+                return 1;
+            }
+            break;
+        case sizeof(uint64_t):
+            u64 = *(const uint64_t *)p->data;
+            if (u64 <= INT32_MAX) {
+                *val = (int32_t)u64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        switch (p->data_size) {
+        case sizeof(double):
+            d = *(const double *)p->data;
+            if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) {
+                *val = (int32_t)d;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
@@ -171,19 +213,35 @@ int OSSL_PARAM_set_int32(const OSSL_PARAM *p, int32_t val)
     if (p == NULL)
         return 0;
     SET_RETURN_SIZE(p, 0);
-    if (p->data_type != OSSL_PARAM_INTEGER)
-        return 0;
-
-    SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */
-    switch (p->data_size) {
-    case sizeof(int32_t):
-        SET_RETURN_SIZE(p, sizeof(int32_t));
-        *(int32_t *)p->data = val;
-        return 1;
-    case sizeof(int64_t):
-        SET_RETURN_SIZE(p, sizeof(int64_t));
-        *(int64_t *)p->data = (int64_t)val;
-        return 1;
+    if (p->data_type == OSSL_PARAM_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            *(int32_t *)p->data = val;
+            return 1;
+        case sizeof(int64_t):
+            SET_RETURN_SIZE(p, sizeof(int64_t));
+            *(int64_t *)p->data = (int64_t)val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
+        SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *(uint32_t *)p->data = (uint32_t)val;
+            return 1;
+        case sizeof(uint64_t):
+            SET_RETURN_SIZE(p, sizeof(uint64_t));
+            *(uint64_t *)p->data = (uint64_t)val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(double):
+            *(double *)p->data = (double)val;
+            return 1;
+        }
     }
     return 0;
 }
@@ -197,35 +255,96 @@ OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf,
 
 int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
 {
-    if (val == NULL
-        || p == NULL
-        || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+    int32_t i32;
+    int64_t i64;
+    uint64_t u64;
+    double d;
+
+    if (val == NULL || p == NULL)
         return 0;
 
-    if (p->data_size == sizeof(uint32_t)) {
-        *val = *(const uint32_t *)p->data;
-        return 1;
+    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *val = *(const uint32_t *)p->data;
+            return 1;
+        case sizeof(uint64_t):
+            u64 = *(const uint64_t *)p->data;
+            if (u64 <= UINT32_MAX) {
+                *val = (uint32_t)u64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            i32 = *(const int32_t *)p->data;
+            if (i32 >= 0) {
+                *val = i32;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            i64 = *(const int64_t *)p->data;
+            if (i64 >= 0 && i64 <= UINT32_MAX) {
+                *val = (uint32_t)i64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        switch (p->data_size) {
+        case sizeof(double):
+            d = *(const double *)p->data;
+            if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) {
+                *val = (uint32_t)d;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
 
 int OSSL_PARAM_set_uint32(const OSSL_PARAM *p, uint32_t val)
 {
-    if (p == NULL) return 0;
-    SET_RETURN_SIZE(p, 0);
-    if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+    if (p == NULL)
         return 0;
+    SET_RETURN_SIZE(p, 0);
 
-    SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */
-    switch (p->data_size) {
-    case sizeof(uint32_t):
-        SET_RETURN_SIZE(p, sizeof(uint32_t));
-        *(uint32_t *)p->data = val;
-        return 1;
-    case sizeof(uint64_t):
-        SET_RETURN_SIZE(p, sizeof(uint64_t));
-        *(uint64_t *)p->data = (uint64_t)val;
-        return 1;
+    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *(uint32_t *)p->data = val;
+            return 1;
+        case sizeof(uint64_t):
+            SET_RETURN_SIZE(p, sizeof(uint64_t));
+            *(uint64_t *)p->data = val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            if (val <= INT32_MAX) {
+                *(int32_t *)p->data = (int32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            SET_RETURN_SIZE(p, sizeof(int64_t));
+            *(int64_t *)p->data = (int64_t)val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(double):
+            *(double *)p->data = (double)val;
+            return 1;
+        }
     }
     return 0;
 }
@@ -239,34 +358,94 @@ OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf,
 
 int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
 {
-    if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
+    uint64_t u64;
+    double d;
+
+    if (val == NULL || p == NULL )
         return 0;
 
-    switch (p->data_size) {
-    case sizeof(int32_t):
-        *val = (int64_t)*(const int32_t *)p->data;
-        return 1;
-    case sizeof(int64_t):
-        *val = *(const int64_t *)p->data;
-        return 1;
+    if (p->data_type == OSSL_PARAM_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            *val = *(const int32_t *)p->data;
+            return 1;
+        case sizeof(int64_t):
+            *val = *(const int64_t *)p->data;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *val = *(const uint32_t *)p->data;
+            return 1;
+        case sizeof(uint64_t):
+            u64 = *(const uint64_t *)p->data;
+            if (u64 <= INT64_MAX) {
+                *val = (int64_t)u64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        switch (p->data_size) {
+        case sizeof(double):
+            d = *(const double *)p->data;
+            if (d >= INT64_MIN && d <= INT64_MAX && d == (int64_t)d) {
+                *val = (int64_t)d;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
 
 int OSSL_PARAM_set_int64(const OSSL_PARAM *p, int64_t val)
 {
+    uint64_t u64;
+
     if (p == NULL)
         return 0;
     SET_RETURN_SIZE(p, 0);
-    if (p->data_type != OSSL_PARAM_INTEGER)
-        return 0;
-
-    SET_RETURN_SIZE(p, sizeof(int64_t)); /* Minimum expected size */
-    switch (p->data_size) {
-    case sizeof(int64_t):
-        SET_RETURN_SIZE(p, sizeof(int64_t));
-        *(int64_t *)p->data = val;
-        return 1;
+    if (p->data_type == OSSL_PARAM_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(int64_t)); /* Expected size */
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            if (val >= INT32_MIN && val <= INT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(int32_t));
+                *(int32_t *)p->data = (int32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            *(int64_t *)p->data = val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
+        SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Expected size */
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            if (val <= UINT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(uint32_t));
+                *(uint32_t *)p->data = (uint32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(uint64_t):
+            *(uint64_t *)p->data = (uint64_t)val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(double):
+            u64 = val < 0 ? -val : val;
+            if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */
+                *(double *)p->data = (double)val;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
@@ -280,18 +459,49 @@ OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf,
 
 int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
 {
-    if (val == NULL
-        || p == NULL
-        || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+    int32_t i32;
+    int64_t i64;
+    double d;
+
+    if (val == NULL || p == NULL)
         return 0;
 
-    switch (p->data_size) {
-    case sizeof(uint32_t):
-        *val = (uint64_t)*(const uint32_t *)p->data;
-        return 1;
-    case sizeof(uint64_t):
-        *val = *(const uint64_t *)p->data;
-        return 1;
+    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *val = *(const uint32_t *)p->data;
+            return 1;
+        case sizeof(uint64_t):
+            *val = *(const uint64_t *)p->data;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            i32 = *(const int32_t *)p->data;
+            if (i32 >= 0) {
+                *val = (uint64_t)i32;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            i64 = *(const int64_t *)p->data;
+            if (i64 >= 0) {
+                *val = (uint64_t)i64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        switch (p->data_size) {
+        case sizeof(double):
+            d = *(const double *)p->data;
+            if (d >= 0 && d <= INT64_MAX && d == (uint64_t)d) {
+                *val = (uint64_t)d;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
@@ -301,15 +511,48 @@ int OSSL_PARAM_set_uint64(const OSSL_PARAM *p, uint64_t val)
     if (p == NULL)
         return 0;
     SET_RETURN_SIZE(p, 0);
-    if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
-        return 0;
 
-    SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Minimum expected size */
-    switch (p->data_size) {
-    case sizeof(uint64_t):
-        SET_RETURN_SIZE(p, sizeof(uint64_t));
-        *(uint64_t *)p->data = val;
-        return 1;
+    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Expected size */
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            if (val <= UINT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(uint32_t));
+                *(uint32_t *)p->data = (uint32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(uint64_t):
+            *(uint64_t *)p->data = val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_INTEGER) {
+        SET_RETURN_SIZE(p, sizeof(int64_t)); /* Expected size */
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            if (val <= INT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(int32_t));
+                *(int32_t *)p->data = (int32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            if (val <= INT64_MAX) {
+                *(int64_t *)p->data = (int64_t)val;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_REAL) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(double):
+            if ((val >> 53) == 0) { /* 53 significant bits in the mantissa */
+                *(double *)p->data = (double)val;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
@@ -402,13 +645,45 @@ OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
 
 int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
 {
-    if (val == NULL || p == NULL || p->data_type != OSSL_PARAM_REAL)
+    int64_t i64;
+    uint64_t u64;
+
+    if (val == NULL || p == NULL)
         return 0;
 
-    switch (p->data_size) {
-    case sizeof(double):
-        *val = *(const double *)p->data;
-        return 1;
+    if (p->data_type == OSSL_PARAM_REAL) {
+        switch (p->data_size) {
+        case sizeof(double):
+            *val = *(const double *)p->data;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            *val = *(const uint32_t *)p->data;
+            return 1;
+        case sizeof(uint64_t):
+            u64 = *(const uint64_t *)p->data;
+            if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */
+                *val = (double)u64;
+                return 1;
+            }
+            break;
+        }
+    } else if (p->data_type == OSSL_PARAM_INTEGER) {
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            *val = *(const int32_t *)p->data;
+            return 1;
+        case sizeof(int64_t):
+            i64 = *(const int64_t *)p->data;
+            u64 = i64 < 0 ? -i64 : i64;
+            if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */
+                *val = 0.0 + i64;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
@@ -418,14 +693,50 @@ int OSSL_PARAM_set_double(const OSSL_PARAM *p, double val)
     if (p == NULL)
         return 0;
     SET_RETURN_SIZE(p, 0);
-    if (p->data_type != OSSL_PARAM_REAL)
-        return 0;
 
-    switch (p->data_size) {
-    case sizeof(double):
+    if (p->data_type == OSSL_PARAM_REAL) {
         SET_RETURN_SIZE(p, sizeof(double));
-        *(double *)p->data = val;
-        return 1;
+        switch (p->data_size) {
+        case sizeof(double):
+            *(double *)p->data = val;
+            return 1;
+        }
+    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER
+               && val == (uintmax_t)val) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(uint32_t):
+            if (val >= 0 && val <= UINT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(uint32_t));
+                *(uint32_t *)p->data = (uint32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(uint64_t):
+            if (val >= 0 && val <= UINT64_MAX) {
+                SET_RETURN_SIZE(p, sizeof(uint64_t));
+                *(uint64_t *)p->data = (uint64_t)val;
+                return 1;
+            }
+            break;            }
+    } else if (p->data_type == OSSL_PARAM_INTEGER && val == (intmax_t)val) {
+        SET_RETURN_SIZE(p, sizeof(double));
+        switch (p->data_size) {
+        case sizeof(int32_t):
+            if (val >= INT32_MIN && val <= INT32_MAX) {
+                SET_RETURN_SIZE(p, sizeof(int32_t));
+                *(int32_t *)p->data = (int32_t)val;
+                return 1;
+            }
+            break;
+        case sizeof(int64_t):
+            if (val >= INT64_MIN && val <= INT64_MAX) {
+                SET_RETURN_SIZE(p, sizeof(int64_t));
+                *(int64_t *)p->data = (int64_t)val;
+                return 1;
+            }
+            break;
+        }
     }
     return 0;
 }
index 5f3a49d..7fb55c7 100644 (file)
@@ -6,23 +6,37 @@
 # in the file LICENSE in the source distribution or at
 # https://www.openssl.org/source/license.html
 
-# Copyright IBM Corp. 2018
+# Copyright IBM Corp. 2018-2019
 # Author: Patrick Steuer <patrick.steuer@de.ibm.com>
 
 package perlasm::s390x;
 
 use strict;
 use warnings;
+use bigint;
 use Carp qw(confess);
 use Exporter qw(import);
 
 our @EXPORT=qw(PERLASM_BEGIN PERLASM_END);
 our @EXPORT_OK=qw(AUTOLOAD LABEL INCLUDE stfle);
 our %EXPORT_TAGS=(
+       # long-displacement facility
+       LD => [qw(clgfi)],
+       # general-instruction-extension facility
+       GE => [qw(risbg)],
+       # extended-immediate facility
+       EI => [qw(lt)],
+       # miscellaneous-instruction-extensions facility 1
+       MI1 => [qw(risbgn)],
+       # message-security assist
        MSA => [qw(kmac km kmc kimd klmd)],
+       # message-security-assist extension 4
        MSA4 => [qw(kmf kmo pcc kmctr)],
+       # message-security-assist extension 5
        MSA5 => [qw(ppno prno)],
+       # message-security-assist extension 8
        MSA8 => [qw(kma)],
+       # vector facility
        VX => [qw(vgef vgeg vgbm vzero vone vgm vgmb vgmh vgmf vgmg
            vl vlr vlrep vlrepb vlreph vlrepf vlrepg vleb vleh vlef vleg vleib
            vleih vleif vleig vlgv vlgvb vlgvh vlgvf vlgvg vllez vllezb vllezh
@@ -71,6 +85,7 @@ our %EXPORT_TAGS=(
            wfmadb vfms vfmsdb wfmsdb vfpso vfpsodb wfpsodb vflcdb wflcdb
            vflndb wflndb vflpdb wflpdb vfsq vfsqdb wfsqdb vfs vfsdb wfsdb
            vftci vftcidb wftcidb)],
+       # vector-enhancements facility 1
        VXE => [qw(vbperm vllezlf vmsl vmslg vnx vnn voc vpopctb vpopcth
            vpopctf vpopctg vfasb wfasb wfaxb wfcsb wfcxb wfksb wfkxb vfcesb
            vfcesbs wfcesb wfcesbs wfcexb wfcexbs vfchsb vfchsbs wfchsb wfchsbs
@@ -83,10 +98,11 @@ our %EXPORT_TAGS=(
            wfnmsxb vfpsosb wfpsosb vflcsb wflcsb vflnsb wflnsb vflpsb wflpsb
            vfpsoxb wfpsoxb vflcxb wflcxb vflnxb wflnxb vflpxb wflpxb vfsqsb
            wfsqsb wfsqxb vfssb wfssb wfsxb vftcisb wftcisb wftcixb)],
+       # vector-packed-decimal facility
        VXD => [qw(vlrlr vlrl vstrlr vstrl vap vcp vcvb vcvbg vcvd vcvdg vdp
            vlip vmp vmsp vpkz vpsop vrp vsdp vsrp vsp vtp vupkz)],
 );
-Exporter::export_ok_tags(qw(MSA MSA4 MSA5 MSA8 VX VXE VXD));
+Exporter::export_ok_tags(qw(LD GE EI MI1 MSA MSA4 MSA5 MSA8 VX VXE VXD));
 
 our $AUTOLOAD;
 
@@ -143,6 +159,28 @@ sub stfle {
        S(0xb2b0,@_);
 }
 
+# MISC
+
+sub clgfi {
+       confess(err("ARGNUM")) if ($#_!=1);
+       RILa(0xc2e,@_);
+}
+
+sub lt {
+       confess(err("ARGNUM")) if ($#_!=1);
+       RXYa(0xe312,@_);
+}
+
+sub risbg {
+       confess(err("ARGNUM")) if ($#_<3||$#_>4);
+       RIEf(0xec55,@_);
+}
+
+sub risbgn {
+       confess(err("ARGNUM")) if ($#_<3||$#_>4);
+       RIEf(0xec59,@_);
+}
+
 # MSA
 
 sub kmac {
@@ -250,7 +288,7 @@ sub vgmg {
 }
 
 sub vl {
-       confess(err("ARGNUM")) if ($#_!=1);
+       confess(err("ARGNUM")) if ($#_<1||$#_>2);
        VRX(0xe706,@_);
 }
 
@@ -345,7 +383,7 @@ sub vllezg {
 }
 
 sub vlm {
-       confess(err("ARGNUM")) if ($#_!=2);
+       confess(err("ARGNUM")) if ($#_<2||$#_>3);
        VRSa(0xe736,@_);
 }
 
@@ -548,7 +586,7 @@ sub vsegf {
 }
 
 sub vst {
-       confess(err("ARGNUM")) if ($#_!=1);
+       confess(err("ARGNUM")) if ($#_<1||$#_>2);
        VRX(0xe70e,@_);
 }
 
@@ -570,7 +608,7 @@ sub vsteg {
 }
 
 sub vstm {
-       confess(err("ARGNUM")) if ($#_!=2);
+       confess(err("ARGNUM")) if ($#_<2||$#_>3);
        VRSa(0xe73e,@_);
 }
 
@@ -2486,6 +2524,36 @@ sub vupkz {
 # Instruction Formats
 #
 
+sub RIEf {
+       confess(err("ARGNUM")) if ($#_<4||5<$#_);
+       my $ops=join(',',@_[1..$#_]);
+       my $memn=(caller(1))[3];
+       $memn=~s/^.*:://;
+       my ($opcode,$r1,$r2,$i3,$i4,$i5)=(shift,get_R(shift),get_R(shift),
+                                         get_I(shift,8),get_I(shift,8),
+                                         get_I(shift,8));
+
+       $out.="\t.word\t";
+       $out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$r2)).",";
+       $out.=sprintf("%#06x",($i3<<8)|$i4).",";
+       $out.=sprintf("%#06x",($i5<<8)|($opcode&0xff));
+       $out.="\t# $memn\t$ops\n"
+}
+
+sub RILa {
+       confess(err("ARGNUM")) if ($#_!=2);
+       my $ops=join(',',@_[1..$#_]);
+       my $memn=(caller(1))[3];
+       $memn=~s/^.*:://;
+       my ($opcode,$r1,$i2)=(shift,get_R(shift),get_I(shift,32));
+
+       $out.="\t.word\t";
+       $out.=sprintf("%#06x",(($opcode>>4)<<8|$r1<<4|($opcode&0xf))).",";
+       $out.=sprintf("%#06x",($i2>>16)).",";
+       $out.=sprintf("%#06x",($i2&0xffff));
+       $out.="\t# $memn\t$ops\n"
+}
+
 sub RRE {
        confess(err("ARGNUM")) if ($#_<0||2<$#_);
        my $ops=join(',',@_[1..$#_]);
@@ -2510,6 +2578,20 @@ sub RRFb {
        $out.="\t# $memn\t$ops\n"
 }
 
+sub RXYa {
+       confess(err("ARGNUM")) if ($#_!=2);
+       my $ops=join(',',@_[1..$#_]);
+       my $memn=(caller(1))[3];
+       $memn=~s/^.*:://;
+       my ($opcode,$r1,$d2,$x2,$b2)=(shift,get_R(shift),get_DXB(shift));
+
+       $out.="\t.word\t";
+       $out.=sprintf("%#06x",(($opcode>>8)<<8|$r1<<4|$x2)).",";
+       $out.=sprintf("%#06x",($b2<<12|($d2&0xfff))).",";
+       $out.=sprintf("%#06x",(($d2>>12)<<8|$opcode&0xff));
+       $out.="\t# $memn\t$ops\n"
+}
+
 sub S {
        confess(err("ARGNUM")) if ($#_<0||1<$#_);
        my $ops=join(',',@_[1..$#_]);
index ea1c2d8..73efdd9 100755 (executable)
@@ -45,7 +45,7 @@
 use strict;
 use FindBin qw($Bin);
 use lib "$Bin/../..";
-use perlasm::s390x qw(:DEFAULT :VX AUTOLOAD LABEL INCLUDE);
+use perlasm::s390x qw(:DEFAULT :LD :GE :EI :MI1 :VX AUTOLOAD LABEL INCLUDE);
 
 my $flavour = shift;
 
index 9601674..0d5ab79 100644 (file)
@@ -323,6 +323,7 @@ void OPENSSL_cpuid_setup(void)
 #ifdef OSSL_IMPLEMENT_GETAUXVAL
     {
         unsigned long hwcap = getauxval(HWCAP);
+        unsigned long hwcap2 = getauxval(HWCAP2);
 
         if (hwcap & HWCAP_FPU) {
             OPENSSL_ppccap_P |= PPC_FPU;
@@ -341,11 +342,11 @@ void OPENSSL_cpuid_setup(void)
         if (hwcap & HWCAP_ALTIVEC) {
             OPENSSL_ppccap_P |= PPC_ALTIVEC;
 
-            if ((hwcap & HWCAP_VSX) && (getauxval(HWCAP2) & HWCAP_VEC_CRYPTO))
+            if ((hwcap & HWCAP_VSX) && (hwcap2 & HWCAP_VEC_CRYPTO))
                 OPENSSL_ppccap_P |= PPC_CRYPTO207;
         }
 
-        if (hwcap & HWCAP_ARCH_3_00) {
+        if (hwcap2 & HWCAP_ARCH_3_00) {
             OPENSSL_ppccap_P |= PPC_MADD300;
         }
     }
index 3a86b6e..3bdf307 100644 (file)
@@ -1,3 +1,5 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=property_string.c property_parse.c property.c \
                         property_err.c defn_cache.c
+SOURCE[../../providers/fips]=\
+    property_string.c property_parse.c property.c defn_cache.c
index df87c19..aec05c1 100644 (file)
@@ -29,8 +29,6 @@ typedef struct {
 
 DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM);
 
-static LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = NULL;
-
 static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a)
 {
     return OPENSSL_LH_strhash(a->prop);
@@ -48,35 +46,52 @@ static void property_defn_free(PROPERTY_DEFN_ELEM *elem)
     OPENSSL_free(elem);
 }
 
-int ossl_prop_defn_init(void)
+static void property_defns_free(void *vproperty_defns)
 {
-    property_defns = lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash,
-                                               &property_defn_cmp);
-    return property_defns != NULL;
-}
+    LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns;
 
-void ossl_prop_defn_cleanup(void)
-{
     if (property_defns != NULL) {
-        lh_PROPERTY_DEFN_ELEM_doall(property_defns, &property_defn_free);
+        lh_PROPERTY_DEFN_ELEM_doall(property_defns,
+                                    &property_defn_free);
         lh_PROPERTY_DEFN_ELEM_free(property_defns);
-        property_defns = NULL;
     }
 }
 
-OSSL_PROPERTY_LIST *ossl_prop_defn_get(const char *prop)
+static void *property_defns_new(OPENSSL_CTX *ctx) {
+    return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp);
+}
+
+static const OPENSSL_CTX_METHOD property_defns_method = {
+    property_defns_new,
+    property_defns_free,
+};
+
+OSSL_PROPERTY_LIST *ossl_prop_defn_get(OPENSSL_CTX *ctx, const char *prop)
 {
     PROPERTY_DEFN_ELEM elem, *r;
+    LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
+
+    property_defns = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_DEFN_INDEX,
+                                          &property_defns_method);
+    if (property_defns == NULL)
+        return NULL;
 
     elem.prop = prop;
     r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem);
     return r != NULL ? r->defn : NULL;
 }
 
-int ossl_prop_defn_set(const char *prop, OSSL_PROPERTY_LIST *pl)
+int ossl_prop_defn_set(OPENSSL_CTX *ctx, const char *prop,
+                       OSSL_PROPERTY_LIST *pl)
 {
     PROPERTY_DEFN_ELEM elem, *old, *p = NULL;
     size_t len;
+    LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns;
+
+    property_defns = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_DEFN_INDEX,
+                                          &property_defns_method);
+    if (property_defns == NULL)
+        return 0;
 
     if (prop == NULL)
         return 1;
index 9a6857f..0051c7e 100644 (file)
@@ -2,16 +2,17 @@
 
 Definition
       ::= PropertyName ( '=' Value )? ( ',' PropertyName ( '=' Value )? )*
-Query ::= ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value )
-          ( ',' ( '-'? PropertyName | PropertyName ( '=' | '!=' ) Value ) )*
+Query ::= PropertyQuery ( ',' PropertyQuery )*
+PropertyQuery ::= '-'? PropertyName
+        | '?' ( PropertyName (( '=' | '!=' ) Value)?)
 Value    ::= NumberLiteral
         | StringLiteral
 StringLiteral ::= QuotedString | UnquotedString
 QuotedString     ::= '"' [^"]* '"'
-       | "'" [^']* "'"
+        | "'" [^']* "'"
 UnquotedString ::= [^{space},]+
 NumberLiteral
      ::= '0' ( [0-7]* | 'x' [0-9A-Fa-f]+ )
-       | '-'? [1-9] [0-9]+
+        | '-'? [1-9] [0-9]+
 PropertyName
          ::= [A-Z] [A-Z0-9_]* ( '.' [A-Z] [A-Z0-9_]* )*
old mode 100644 (file)
new mode 100755 (executable)
index 3382722..766d885
@@ -2,7 +2,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
       <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
-      <meta name="generator" content="Railroad Diagram Generator 1.56.1774" />
+      <meta name="generator" content="Railroad Diagram Generator 1.59.1797" />
       <style type="text/css">
     ::-moz-selection
     {
       display: block;
       padding: 10px;
       background: #FFF6D1;
-      width: 1000px;
+      width: 992px;
     }
     #divs div.grammar
     {
                <div><a href="#Definition" title="Definition">Definition</a></div>
                <div>         ::= <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? ( ',' <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' <a href="#Value" title="Value">Value</a> )? )*</div></xhtml:code></xhtml:div>
       </xhtml:p>
-      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Query">Query:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="419" height="201">
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Query">Query:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="211" height="81">
          <defs>
             <style type="text/css">
     @namespace "http://www.w3.org/2000/svg";
   </style>
          </defs>
          <polygon points="9 61 1 57 1 65"/>
-         <polygon points="17 61 9 57 9 65"/>
-         <rect x="91" y="79" width="26" height="32" rx="10"/>
-         <rect x="89" y="77" width="26" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="99" y="97">-</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
-            <rect x="157" y="47" width="110" height="32"/>
-            <rect x="155" y="45" width="110" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="165" y="65">PropertyName</text></a><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
-            <rect x="71" y="123" width="110" height="32"/>
-            <rect x="69" y="121" width="110" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="79" y="141">PropertyName</text></a><rect x="221" y="123" width="30" height="32" rx="10"/>
-         <rect x="219" y="121" width="30" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="229" y="141">=</text>
-         <rect x="221" y="167" width="34" height="32" rx="10"/>
-         <rect x="219" y="165" width="34" height="32" class="terminal" rx="10"/>
-         <text class="terminal" x="229" y="185">!=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
-            <rect x="295" y="123" width="56" height="32"/>
-            <rect x="293" y="121" width="56" height="32" class="nonterminal"/>
-            <text class="nonterminal" x="303" y="141">Value</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
+         <polygon points="17 61 9 57 9 65"/><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyQuery" xlink:title="PropertyQuery">
+            <rect x="51" y="47" width="112" height="32"/>
+            <rect x="49" y="45" width="112" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="59" y="65">PropertyQuery</text></a><rect x="51" y="3" width="24" height="32" rx="10"/>
          <rect x="49" y="1" width="24" height="32" class="terminal" rx="10"/>
          <text class="terminal" x="59" y="21">,</text>
-         <svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m60 0 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m110 0 h10 m0 0 h84 m-320 0 h20 m300 0 h20 m-340 0 q10 0 10 10 m320 0 q0 -10 10 -10 m-330 10 v56 m320 0 v-56 m-320 56 q0 10 10 10 m300 0 q10 0 10 -10 m-310 10 h10 m110 0 h10 m20 0 h10 m30 0 h10 m0 0 h4 m-74 0 h20 m54 0 h20 m-94 0 q10 0 10 10 m74 0 q0 -10 10 -10 m-84 10 v24 m74 0 v-24 m-74 24 q0 10 10 10 m54 0 q10 0 10 -10 m-64 10 h10 m34 0 h10 m20 -44 h10 m56 0 h10 m-340 -76 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m340 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-340 0 h10 m24 0 h10 m0 0 h296 m23 44 h-3"/>
-         <polygon points="409 61 417 57 417 65"/>
-         <polygon points="409 61 401 57 401 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
+         <svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 61 h2 m20 0 h10 m112 0 h10 m-152 0 l20 0 m-1 0 q-9 0 -9 -10 l0 -24 q0 -10 10 -10 m132 44 l20 0 m-20 0 q10 0 10 -10 l0 -24 q0 -10 -10 -10 m-132 0 h10 m24 0 h10 m0 0 h88 m23 44 h-3"/>
+         <polygon points="201 61 209 57 209 65"/>
+         <polygon points="201 61 193 57 193 65"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
          <xhtml:div class="ebnf"><xhtml:code>
-               <div><a href="#Query" title="Query">Query</a>    ::= ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) ( ',' ( '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a> | <a href="#PropertyName" title="PropertyName">PropertyName</a> ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> ) )*</div></xhtml:code></xhtml:div>
+               <div><a href="#Query" title="Query">Query</a>    ::= <a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a> ( ',' <a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a> )*</div></xhtml:code></xhtml:div>
       </xhtml:p>
-      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Value">Value:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="81">
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">no references</xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="PropertyQuery">PropertyQuery:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="465" height="189">
+         <defs>
+            <style type="text/css">
+    @namespace "http://www.w3.org/2000/svg";
+    .line                 {fill: none; stroke: #332900;}
+    .bold-line            {stroke: #141000; shape-rendering: crispEdges; stroke-width: 2; }
+    .thin-line            {stroke: #1F1800; shape-rendering: crispEdges}
+    .filled               {fill: #332900; stroke: none;}
+    text.terminal         {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #141000;
+                            font-weight: bold;
+                          }
+    text.nonterminal      {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #1A1400;
+                            font-weight: normal;
+                          }
+    text.regexp           {font-family: Verdana, Sans-serif;
+                            font-size: 12px;
+                            fill: #1F1800;
+                            font-weight: normal;
+                          }
+    rect, circle, polygon {fill: #332900; stroke: #332900;}
+    rect.terminal         {fill: #FFDB4D; stroke: #332900;}
+    rect.nonterminal      {fill: #FFEC9E; stroke: #332900;}
+    rect.text             {fill: none; stroke: none;}    
+    polygon.regexp        {fill: #FFF4C7; stroke: #332900;}
+  </style>
+         </defs>
+         <polygon points="9 17 1 13 1 21"/>
+         <polygon points="17 17 9 13 9 21"/>
+         <rect x="71" y="35" width="26" height="32" rx="10"/>
+         <rect x="69" y="33" width="26" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="79" y="53">-</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
+            <rect x="137" y="3" width="110" height="32"/>
+            <rect x="135" y="1" width="110" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="145" y="21">PropertyName</text></a><rect x="51" y="79" width="26" height="32" rx="10"/>
+         <rect x="49" y="77" width="26" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="59" y="97">?</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#PropertyName" xlink:title="PropertyName">
+            <rect x="97" y="79" width="110" height="32"/>
+            <rect x="95" y="77" width="110" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="105" y="97">PropertyName</text></a><rect x="267" y="111" width="30" height="32" rx="10"/>
+         <rect x="265" y="109" width="30" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="275" y="129">=</text>
+         <rect x="267" y="155" width="34" height="32" rx="10"/>
+         <rect x="265" y="153" width="34" height="32" class="terminal" rx="10"/>
+         <text class="terminal" x="275" y="173">!=</text><a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Value" xlink:title="Value">
+            <rect x="341" y="111" width="56" height="32"/>
+            <rect x="339" y="109" width="56" height="32" class="nonterminal"/>
+            <text class="nonterminal" x="349" y="129">Value</text></a><svg:path xmlns:svg="http://www.w3.org/2000/svg" class="line" d="m17 17 h2 m40 0 h10 m0 0 h36 m-66 0 h20 m46 0 h20 m-86 0 q10 0 10 10 m66 0 q0 -10 10 -10 m-76 10 v12 m66 0 v-12 m-66 12 q0 10 10 10 m46 0 q10 0 10 -10 m-56 10 h10 m26 0 h10 m20 -32 h10 m110 0 h10 m0 0 h170 m-406 0 h20 m386 0 h20 m-426 0 q10 0 10 10 m406 0 q0 -10 10 -10 m-416 10 v56 m406 0 v-56 m-406 56 q0 10 10 10 m386 0 q10 0 10 -10 m-396 10 h10 m26 0 h10 m0 0 h10 m110 0 h10 m20 0 h10 m0 0 h160 m-190 0 h20 m170 0 h20 m-210 0 q10 0 10 10 m190 0 q0 -10 10 -10 m-200 10 v12 m190 0 v-12 m-190 12 q0 10 10 10 m170 0 q10 0 10 -10 m-160 10 h10 m30 0 h10 m0 0 h4 m-74 0 h20 m54 0 h20 m-94 0 q10 0 10 10 m74 0 q0 -10 10 -10 m-84 10 v24 m74 0 v-24 m-74 24 q0 10 10 10 m54 0 q10 0 10 -10 m-64 10 h10 m34 0 h10 m20 -44 h10 m56 0 h10 m43 -108 h-3"/>
+         <polygon points="455 17 463 13 463 21"/>
+         <polygon points="455 17 447 13 447 21"/></svg><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
+         <xhtml:div class="ebnf"><xhtml:code>
+               <div><a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</a></div>
+               <div>         ::= '-'? <a href="#PropertyName" title="PropertyName">PropertyName</a></div>
+               <div>           | '?' <a href="#PropertyName" title="PropertyName">PropertyName</a> ( ( '=' | '!=' ) <a href="#Value" title="Value">Value</a> )?</div></xhtml:code></xhtml:div>
+      </xhtml:p>
+      <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
+         <xhtml:ul>
+            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+         </xhtml:ul>
+      </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="Value">Value:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="207" height="81">
          <defs>
             <style type="text/css">
     @namespace "http://www.w3.org/2000/svg";
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
          <xhtml:ul>
             <xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
-            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+            <xhtml:li><xhtml:a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</xhtml:a></xhtml:li>
          </xhtml:ul>
       </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml" style="font-size: 14px; font-weight:bold"><xhtml:a name="StringLiteral">StringLiteral:</xhtml:a></xhtml:p><svg xmlns="http://www.w3.org/2000/svg" width="219" height="81">
          <defs>
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">referenced by:
          <xhtml:ul>
             <xhtml:li><xhtml:a href="#Definition" title="Definition">Definition</xhtml:a></xhtml:li>
-            <xhtml:li><xhtml:a href="#Query" title="Query">Query</xhtml:a></xhtml:li>
+            <xhtml:li><xhtml:a href="#PropertyQuery" title="PropertyQuery">PropertyQuery</xhtml:a></xhtml:li>
          </xhtml:ul>
       </xhtml:p><xhtml:br xmlns:xhtml="http://www.w3.org/1999/xhtml" /><xhtml:hr xmlns:xhtml="http://www.w3.org/1999/xhtml" />
       <xhtml:p xmlns:xhtml="http://www.w3.org/1999/xhtml">
index a2122dc..4c328ff 100644 (file)
@@ -47,6 +47,7 @@ typedef struct {
 } ALGORITHM;
 
 struct ossl_method_store_st {
+    OPENSSL_CTX *ctx;
     size_t nelem;
     SPARSE_ARRAY_OF(ALGORITHM) *algs;
     OSSL_PROPERTY_LIST *global_properties;
@@ -82,29 +83,10 @@ int ossl_property_unlock(OSSL_METHOD_STORE *p)
     return p != 0 ? CRYPTO_THREAD_unlock(p->lock) : 0;
 }
 
-int ossl_method_store_init(void)
+static openssl_ctx_run_once_fn do_method_store_init;
+int do_method_store_init(OPENSSL_CTX *ctx)
 {
-    if (ossl_property_string_init()
-            && ossl_prop_defn_init()
-            && ossl_property_parse_init())
-        return 1;
-
-    ossl_method_store_cleanup();
-    return 0;
-}
-
-void ossl_method_store_cleanup(void)
-{
-    ossl_property_string_cleanup();
-    ossl_prop_defn_cleanup();
-}
-
-static CRYPTO_ONCE method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_method_store_init)
-{
-    return OPENSSL_init_crypto(0, NULL)
-        && ossl_method_store_init()
-        && OPENSSL_atexit(&ossl_method_store_cleanup);
+    return ossl_property_parse_init(ctx);
 }
 
 static unsigned long query_hash(const QUERY *a)
@@ -141,15 +123,22 @@ static void alg_cleanup(ossl_uintmax_t idx, ALGORITHM *a)
     }
 }
 
-OSSL_METHOD_STORE *ossl_method_store_new(void)
+/*
+ * The OPENSSL_CTX param here allows access to underlying property data needed
+ * for computation
+ */
+OSSL_METHOD_STORE *ossl_method_store_new(OPENSSL_CTX *ctx)
 {
     OSSL_METHOD_STORE *res;
 
-    if (!RUN_ONCE(&method_store_init_flag, do_method_store_init))
-        return 0;
+    if (!openssl_ctx_run_once(ctx,
+                              OPENSSL_CTX_METHOD_STORE_RUN_ONCE_INDEX,
+                              do_method_store_init))
+        return NULL;
 
     res = OPENSSL_zalloc(sizeof(*res));
     if (res != NULL) {
+        res->ctx = ctx;
         if ((res->algs = ossl_sa_ALGORITHM_new()) == NULL) {
             OPENSSL_free(res);
             return NULL;
@@ -212,10 +201,11 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store,
      */
     ossl_property_write_lock(store);
     ossl_method_cache_flush(store, nid);
-    if ((impl->properties = ossl_prop_defn_get(properties)) == NULL) {
-        if ((impl->properties = ossl_parse_property(properties)) == NULL)
+    if ((impl->properties = ossl_prop_defn_get(store->ctx, properties)) == NULL) {
+        impl->properties = ossl_parse_property(store->ctx, properties);
+        if (impl->properties == NULL)
             goto err;
-        ossl_prop_defn_set(properties, impl->properties);
+        ossl_prop_defn_set(store->ctx, properties, impl->properties);
     }
 
     alg = ossl_method_store_retrieve(store, nid);
@@ -287,7 +277,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
     IMPLEMENTATION *impl;
     OSSL_PROPERTY_LIST *pq = NULL, *p2;
     int ret = 0;
-    int j;
+    int j, best = -1, score, optional;
 
     if (nid <= 0 || method == NULL || store == NULL)
         return 0;
@@ -310,7 +300,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
         }
         goto fin;
     }
-    pq = ossl_parse_query(prop_query);
+    pq = ossl_parse_query(store->ctx, prop_query);
     if (pq == NULL)
         goto fin;
     if (store->global_properties != NULL) {
@@ -320,13 +310,16 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
         ossl_property_free(pq);
         pq = p2;
     }
+    optional = ossl_property_has_optional(pq);
     for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
         impl = sk_IMPLEMENTATION_value(alg->impls, j);
-
-        if (ossl_property_match(pq, impl->properties)) {
+        score = ossl_property_match_count(pq, impl->properties);
+        if (score > best) {
             *method = impl->method;
             ret = 1;
-            goto fin;
+            if (!optional)
+                goto fin;
+            best = score;
         }
     }
 fin:
@@ -350,7 +343,7 @@ int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
         ossl_property_unlock(store);
         return 1;
     }
-    store->global_properties = ossl_parse_query(prop_query);
+    store->global_properties = ossl_parse_query(store->ctx, prop_query);
     ret = store->global_properties != NULL;
     ossl_property_unlock(store);
     return ret;
@@ -398,6 +391,8 @@ IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
  */
 static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
 {
+#if !defined(FIPS_MODE)
+/* TODO(3.0): No RAND_bytes yet in FIPS module. Add this back when available */
     OSSL_METHOD_STORE *store = state->store;
     unsigned int n;
 
@@ -411,6 +406,7 @@ static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
         OPENSSL_free(lh_QUERY_delete(state->cache, c));
     else
         state->nelem++;
+#endif /* !defined(FIPS_MODE) */
 }
 
 static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg,
index faf3fe1..5fa34ce 100644 (file)
 typedef struct ossl_property_list_st OSSL_PROPERTY_LIST;
 typedef int OSSL_PROPERTY_IDX;
 
-/* Initialisation and finalisation for subsystem */
-int ossl_method_store_init(void);
-void ossl_method_store_cleanup(void);
-
 /* Property string functions */
-OSSL_PROPERTY_IDX ossl_property_name(const char *s, int create);
-OSSL_PROPERTY_IDX ossl_property_value(const char *s, int create);
-int ossl_property_string_init(void);
-void ossl_property_string_cleanup(void);
+OSSL_PROPERTY_IDX ossl_property_name(OPENSSL_CTX *ctx, const char *s,
+                                     int create);
+OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s,
+                                      int create);
 
 /* Property list functions */
-int ossl_property_parse_init(void);
+int ossl_property_parse_init(OPENSSL_CTX *ctx);
 void ossl_property_free(OSSL_PROPERTY_LIST *p);
-int ossl_property_match(const OSSL_PROPERTY_LIST *query,
-                        const OSSL_PROPERTY_LIST *defn);
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query);
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+                              const OSSL_PROPERTY_LIST *defn);
 OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
                                         const OSSL_PROPERTY_LIST *b);
 
 /* Property definition functions */
-OSSL_PROPERTY_LIST *ossl_parse_property(const char *s);
+OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *s);
 
 /* Property query functions */
-OSSL_PROPERTY_LIST *ossl_parse_query(const char *s);
+OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s);
 
 /* Property definition cache functions */
-int ossl_prop_defn_init(void);
-void ossl_prop_defn_cleanup(void);
-OSSL_PROPERTY_LIST *ossl_prop_defn_get(const char *prop);
-int ossl_prop_defn_set(const char *prop, OSSL_PROPERTY_LIST *pl);
+OSSL_PROPERTY_LIST *ossl_prop_defn_get(OPENSSL_CTX *ctx, const char *prop);
+int ossl_prop_defn_set(OPENSSL_CTX *ctx, const char *prop,
+                       OSSL_PROPERTY_LIST *pl);
 
 /* Property cache lock / unlock */
 int ossl_property_write_lock(OSSL_METHOD_STORE *);
index faaaee8..c63a433 100644 (file)
@@ -32,6 +32,7 @@ typedef struct {
     OSSL_PROPERTY_IDX name_idx;
     PROPERTY_TYPE type;
     PROPERTY_OPER oper;
+    unsigned int optional : 1;
     union {
         int64_t             int_val;     /* Signed integer */
         OSSL_PROPERTY_IDX   str_val;     /* String */
@@ -40,6 +41,7 @@ typedef struct {
 
 struct ossl_property_list_st {
     int n;
+    unsigned int has_optional : 1;
     PROPERTY_DEFINITION properties[1];
 };
 
@@ -78,7 +80,8 @@ static int match(const char *t[], const char m[], size_t m_len)
     return 0;
 }
 
-static int parse_name(const char *t[], int create, OSSL_PROPERTY_IDX *idx)
+static int parse_name(OPENSSL_CTX *ctx, const char *t[], int create,
+                      OSSL_PROPERTY_IDX *idx)
 {
     char name[100];
     int err = 0;
@@ -109,7 +112,7 @@ static int parse_name(const char *t[], int create, OSSL_PROPERTY_IDX *idx)
     name[i] = '\0';
     *t = skip_space(s);
     if (!err) {
-        *idx = ossl_property_name(name, user_name && create);
+        *idx = ossl_property_name(ctx, name, user_name && create);
         return 1;
     }
     PROPerr(PROP_F_PARSE_NAME, PROP_R_NAME_TOO_LONG);
@@ -180,8 +183,8 @@ static int parse_oct(const char *t[], PROPERTY_DEFINITION *res)
     return 1;
 }
 
-static int parse_string(const char *t[], char delim, PROPERTY_DEFINITION *res,
-                        const int create)
+static int parse_string(OPENSSL_CTX *ctx, const char *t[], char delim,
+                        PROPERTY_DEFINITION *res, const int create)
 {
     char v[1000];
     const char *s = *t;
@@ -205,13 +208,13 @@ static int parse_string(const char *t[], char delim, PROPERTY_DEFINITION *res,
     if (err)
         PROPerr(PROP_F_PARSE_STRING, PROP_R_STRING_TOO_LONG);
     else
-        res->v.str_val = ossl_property_value(v, create);
+        res->v.str_val = ossl_property_value(ctx, v, create);
     res->type = PROPERTY_TYPE_STRING;
     return !err;
 }
 
-static int parse_unquoted(const char *t[], PROPERTY_DEFINITION *res,
-                          const int create)
+static int parse_unquoted(OPENSSL_CTX *ctx, const char *t[],
+                          PROPERTY_DEFINITION *res, const int create)
 {
     char v[1000];
     const char *s = *t;
@@ -236,19 +239,20 @@ static int parse_unquoted(const char *t[], PROPERTY_DEFINITION *res,
     if (err)
         PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_STRING_TOO_LONG);
     else
-        res->v.str_val = ossl_property_value(v, create);
+        res->v.str_val = ossl_property_value(ctx, v, create);
     res->type = PROPERTY_TYPE_STRING;
     return !err;
 }
 
-static int parse_value(const char *t[], PROPERTY_DEFINITION *res, int create)
+static int parse_value(OPENSSL_CTX *ctx, const char *t[],
+                       PROPERTY_DEFINITION *res, int create)
 {
     const char *s = *t;
     int r = 0;
 
     if (*s == '"' || *s == '\'') {
         s++;
-        r = parse_string(&s, s[-1], res, create);
+        r = parse_string(ctx, &s, s[-1], res, create);
     } else if (*s == '+') {
         s++;
         r = parse_number(&s, res);
@@ -265,7 +269,7 @@ static int parse_value(const char *t[], PROPERTY_DEFINITION *res, int create)
     } else if (ossl_isdigit(*s)) {
         return parse_number(t, res);
     } else if (ossl_isalpha(*s))
-        return parse_unquoted(t, res, create);
+        return parse_unquoted(ctx, t, res, create);
     if (r)
         *t = s;
     return r;
@@ -305,14 +309,17 @@ static OSSL_PROPERTY_LIST *stack_to_property_list(STACK_OF(PROPERTY_DEFINITION)
     if (r != NULL) {
         sk_PROPERTY_DEFINITION_sort(sk);
 
-        for (i = 0; i < n; i++)
+        r->has_optional = 0;
+        for (i = 0; i < n; i++) {
             r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
+            r->has_optional |= r->properties[i].optional;
+        }
         r->n = n;
     }
     return r;
 }
 
-OSSL_PROPERTY_LIST *ossl_parse_property(const char *defn)
+OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
 {
     PROPERTY_DEFINITION *prop = NULL;
     OSSL_PROPERTY_LIST *res = NULL;
@@ -330,7 +337,8 @@ OSSL_PROPERTY_LIST *ossl_parse_property(const char *defn)
         if (prop == NULL)
             goto err;
         memset(&prop->v, 0, sizeof(prop->v));
-        if (!parse_name(&s, 1, &prop->name_idx))
+        prop->optional = 0;
+        if (!parse_name(ctx, &s, 1, &prop->name_idx))
             goto err;
         prop->oper = PROPERTY_OPER_EQ;
         if (prop->name_idx == 0) {
@@ -338,7 +346,7 @@ OSSL_PROPERTY_LIST *ossl_parse_property(const char *defn)
             goto err;
         }
         if (match_ch(&s, '=')) {
-            if (!parse_value(&s, prop, 1)) {
+            if (!parse_value(ctx, &s, prop, 1)) {
                 PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_NO_VALUE);
                 goto err;
             }
@@ -365,7 +373,7 @@ err:
     return res;
 }
 
-OSSL_PROPERTY_LIST *ossl_parse_query(const char *s)
+OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s)
 {
     STACK_OF(PROPERTY_DEFINITION) *sk;
     OSSL_PROPERTY_LIST *res = NULL;
@@ -385,11 +393,13 @@ OSSL_PROPERTY_LIST *ossl_parse_query(const char *s)
 
         if (match_ch(&s, '-')) {
             prop->oper = PROPERTY_OVERRIDE;
-            if (!parse_name(&s, 0, &prop->name_idx))
+            prop->optional = 0;
+            if (!parse_name(ctx, &s, 0, &prop->name_idx))
                 goto err;
             goto skip_value;
         }
-        if (!parse_name(&s, 0, &prop->name_idx))
+        prop->optional = match_ch(&s, '?');
+        if (!parse_name(ctx, &s, 0, &prop->name_idx))
             goto err;
 
         if (match_ch(&s, '=')) {
@@ -403,7 +413,7 @@ OSSL_PROPERTY_LIST *ossl_parse_query(const char *s)
             prop->v.str_val = ossl_property_true;
             goto skip_value;
         }
-        if (!parse_value(&s, prop, 0))
+        if (!parse_value(ctx, &s, prop, 0))
             prop->type = PROPERTY_TYPE_VALUE_UNDEFINED;
 
 skip_value:
@@ -424,12 +434,22 @@ err:
     return res;
 }
 
-int ossl_property_match(const OSSL_PROPERTY_LIST *query,
-                        const OSSL_PROPERTY_LIST *defn)
+/* Does a property query have any optional clauses */
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
+{
+    return query->has_optional ? 1 : 0;
+}
+
+/*
+ * Compare a query against a definition.
+ * Return the number of clauses matched or -1 if a mandatory clause is false.
+ */
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+                              const OSSL_PROPERTY_LIST *defn)
 {
     const PROPERTY_DEFINITION *const q = query->properties;
     const PROPERTY_DEFINITION *const d = defn->properties;
-    int i = 0, j = 0;
+    int i = 0, j = 0, matches = 0;
     PROPERTY_OPER oper;
 
     while (i < query->n) {
@@ -446,9 +466,11 @@ int ossl_property_match(const OSSL_PROPERTY_LIST *query,
                 const int eq = q[i].type == d[j].type
                                && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
 
-                if ((eq && oper != PROPERTY_OPER_EQ)
-                    || (!eq && oper != PROPERTY_OPER_NE))
-                    return 0;
+                if ((eq && oper == PROPERTY_OPER_EQ)
+                    || (!eq && oper == PROPERTY_OPER_NE))
+                    matches++;
+                else if (!q[i].optional)
+                    return -1;
                 i++;
                 j++;
                 continue;
@@ -461,18 +483,23 @@ int ossl_property_match(const OSSL_PROPERTY_LIST *query,
          * the latter is treated as a comparison against the Boolean false.
          */
         if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
-            if (oper != PROPERTY_OPER_NE)
-                return 0;
+            if (oper == PROPERTY_OPER_NE)
+                matches++;
+            else if (!q[i].optional)
+                return -1;
         } else if (q[i].type != PROPERTY_TYPE_STRING
                    || (oper == PROPERTY_OPER_EQ
                        && q[i].v.str_val != ossl_property_false)
                    || (oper == PROPERTY_OPER_NE
                        && q[i].v.str_val == ossl_property_false)) {
-            return 0;
+            if (!q[i].optional)
+                return -1;
+        } else {
+            matches++;
         }
         i++;
     }
-    return 1;
+    return matches;
 }
 
 void ossl_property_free(OSSL_PROPERTY_LIST *p)
@@ -519,7 +546,7 @@ OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
     return r;
 }
 
-int ossl_property_parse_init(void)
+int ossl_property_parse_init(OPENSSL_CTX *ctx)
 {
     static const char *const predefined_names[] = {
         "default",      /* Being provided by the default built-in provider */
@@ -532,12 +559,12 @@ int ossl_property_parse_init(void)
     size_t i;
 
     for (i = 0; i < OSSL_NELEM(predefined_names); i++)
-        if (ossl_property_name(predefined_names[i], 1) == 0)
+        if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
             goto err;
 
     /* Pre-populate the two Boolean values */
-    if ((ossl_property_true = ossl_property_value("yes", 1)) == 0
-        || (ossl_property_false = ossl_property_value("no", 1)) == 0)
+    if ((ossl_property_true = ossl_property_value(ctx, "yes", 1)) == 0
+        || (ossl_property_false = ossl_property_value(ctx, "no", 1)) == 0)
         goto err;
 
     return 1;
index 7f6e30e..dcf5dcc 100644 (file)
@@ -34,10 +34,12 @@ typedef struct {
 DEFINE_LHASH_OF(PROPERTY_STRING);
 typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
 
-static PROP_TABLE *prop_names;
-static PROP_TABLE *prop_values;
-static OSSL_PROPERTY_IDX prop_name_idx = 0;
-static OSSL_PROPERTY_IDX prop_value_idx = 0;
+typedef struct {
+    PROP_TABLE *prop_names;
+    PROP_TABLE *prop_values;
+    OSSL_PROPERTY_IDX prop_name_idx;
+    OSSL_PROPERTY_IDX prop_value_idx;
+} PROPERTY_STRING_DATA;
 
 static unsigned long property_hash(const PROPERTY_STRING *a)
 {
@@ -65,6 +67,48 @@ static void property_table_free(PROP_TABLE **pt)
     }
 }
 
+static void property_string_data_free(void *vpropdata)
+{
+    PROPERTY_STRING_DATA *propdata = vpropdata;
+
+    if (propdata == NULL)
+        return;
+
+    property_table_free(&propdata->prop_names);
+    property_table_free(&propdata->prop_values);
+    propdata->prop_name_idx = propdata->prop_value_idx = 0;
+
+    OPENSSL_free(propdata);
+}
+
+static void *property_string_data_new(OPENSSL_CTX *ctx) {
+    PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata));
+
+    if (propdata == NULL)
+        return NULL;
+
+    propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash,
+                                                  &property_cmp);
+    if (propdata->prop_names == NULL)
+        goto err;
+
+    propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash,
+                                                   &property_cmp);
+    if (propdata->prop_values == NULL)
+        goto err;
+
+    return propdata;
+
+err:
+    property_string_data_free(propdata);
+    return NULL;
+}
+
+static const OPENSSL_CTX_METHOD property_string_data_method = {
+    property_string_data_new,
+    property_string_data_free,
+};
+
 static PROPERTY_STRING *new_property_string(const char *s,
                                             OSSL_PROPERTY_IDX *pidx)
 {
@@ -103,35 +147,30 @@ static OSSL_PROPERTY_IDX ossl_property_string(PROP_TABLE *t,
     return ps != NULL ? ps->idx : 0;
 }
 
-OSSL_PROPERTY_IDX ossl_property_name(const char *s, int create)
+OSSL_PROPERTY_IDX ossl_property_name(OPENSSL_CTX *ctx, const char *s,
+                                     int create)
 {
-    return ossl_property_string(prop_names, create ? &prop_name_idx : NULL, s);
-}
-
-OSSL_PROPERTY_IDX ossl_property_value(const char *s, int create)
-{
-    return ossl_property_string(prop_values, create ? &prop_value_idx : NULL, s);
-}
+    PROPERTY_STRING_DATA *propdata
+        = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX,
+                               &property_string_data_method);
 
-int ossl_property_string_init(void)
-{
-    prop_names = lh_PROPERTY_STRING_new(&property_hash, &property_cmp);
-    if (prop_names == NULL)
+    if (propdata == NULL)
         return 0;
-
-    prop_values = lh_PROPERTY_STRING_new(&property_hash, &property_cmp);
-    if (prop_values == NULL)
-        goto err;
-    return 1;
-
-err:
-    ossl_property_string_cleanup();
-    return 0;
+    return ossl_property_string(propdata->prop_names,
+                                create ? &propdata->prop_name_idx : NULL,
+                                s);
 }
 
-void ossl_property_string_cleanup(void)
+OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s,
+                                      int create)
 {
-    property_table_free(&prop_names);
-    property_table_free(&prop_values);
-    prop_name_idx = prop_value_idx = 0;
+    PROPERTY_STRING_DATA *propdata
+        = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX,
+                               &property_string_data_method);
+
+    if (propdata == NULL)
+        return 0;
+    return ossl_property_string(propdata->prop_values,
+                                create ? &propdata->prop_value_idx : NULL,
+                                s);
 }
index 9f4c017..d17ff93 100644 (file)
@@ -54,6 +54,9 @@ struct ossl_provider_st {
     OSSL_provider_get_param_types_fn *get_param_types;
     OSSL_provider_get_params_fn *get_params;
     OSSL_provider_query_operation_fn *query_operation;
+
+    /* Provider side data */
+    void *provctx;
 };
 DEFINE_STACK_OF(OSSL_PROVIDER)
 
@@ -76,7 +79,6 @@ struct provider_store_st {
     CRYPTO_RWLOCK *lock;
     unsigned int use_fallbacks:1;
 };
-static int provider_store_index = -1;
 
 static void provider_store_free(void *vstore)
 {
@@ -89,7 +91,7 @@ static void provider_store_free(void *vstore)
     OPENSSL_free(store);
 }
 
-static void *provider_store_new(void)
+static void *provider_store_new(OPENSSL_CTX *ctx)
 {
     struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
     const struct predefined_providers_st *p = NULL;
@@ -131,23 +133,12 @@ static const OPENSSL_CTX_METHOD provider_store_method = {
     provider_store_free,
 };
 
-static CRYPTO_ONCE provider_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_provider_store_init)
-{
-    return OPENSSL_init_crypto(0, NULL)
-        && (provider_store_index =
-            openssl_ctx_new_index(&provider_store_method)) != -1;
-}
-
-
 static struct provider_store_st *get_provider_store(OPENSSL_CTX *libctx)
 {
     struct provider_store_st *store = NULL;
 
-    if (!RUN_ONCE(&provider_store_init_flag, do_provider_store_init))
-        return NULL;
-
-    store = openssl_ctx_get_data(libctx, provider_store_index);
+    store = openssl_ctx_get_data(libctx, OPENSSL_CTX_PROVIDER_STORE_INDEX,
+                                 &provider_store_method);
     if (store == NULL)
         CRYPTOerr(CRYPTO_F_GET_PROVIDER_STORE, ERR_R_INTERNAL_ERROR);
     return store;
@@ -275,7 +266,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          */
         if (ref < 2 && prov->flag_initialized) {
             if (prov->teardown != NULL)
-                prov->teardown();
+                prov->teardown(prov->provctx);
             prov->flag_initialized = 0;
         }
 
@@ -284,7 +275,9 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          * the store.  All we have to do here is clean it out.
          */
         if (ref == 0) {
+#ifndef FIPS_MODE
             DSO_free(prov->module);
+#endif
             OPENSSL_free(prov->name);
             OPENSSL_free(prov->path);
             sk_INFOPAIR_pop_free(prov->parameters, free_infopair);
@@ -347,9 +340,11 @@ static const OSSL_DISPATCH *core_dispatch; /* Define further down */
 /*
  * Internal version that doesn't affect the store flags, and thereby avoid
  * locking.  Direct callers must remember to set the store flags when
- * appropriate
+ * appropriate. The libctx parameter is only necessary when FIPS_MODE is set
+ * (i.e. we are being called from inside the FIPS module) - it is ignored for
+ * other uses.
  */
-static int provider_activate(OSSL_PROVIDER *prov)
+static int provider_activate(OSSL_PROVIDER *prov, OPENSSL_CTX *libctx)
 {
     const OSSL_DISPATCH *provider_dispatch = NULL;
 
@@ -361,6 +356,9 @@ static int provider_activate(OSSL_PROVIDER *prov)
      * a loadable module.
      */
     if (prov->init_function == NULL) {
+#ifdef FIPS_MODE
+        return 0;
+#else
         if (prov->module == NULL) {
             char *allocated_path = NULL;
             const char *module_path = NULL;
@@ -398,14 +396,38 @@ static int provider_activate(OSSL_PROVIDER *prov)
         if (prov->module != NULL)
             prov->init_function = (OSSL_provider_init_fn *)
                 DSO_bind_func(prov->module, "OSSL_provider_init");
+#endif
     }
 
+    /*
+     * We call the initialise function for the provider.
+     *
+     * If FIPS_MODE is defined then we are inside the FIPS module and are about
+     * to recursively initialise ourselves. We need to do this so that we can
+     * get all the provider callback functions set up in order for us to be able
+     * to make EVP calls from within the FIPS module itself. Only algorithms
+     * from the FIPS module itself are available via the FIPS module EVP
+     * interface, i.e. we only ever have one provider available inside the FIPS
+     * module - the FIPS provider itself.
+     *
+     * For modules in general we cannot know what value will be used for the
+     * provctx - it is a "black box". But for the FIPS module we know that the
+     * provctx is really a library context. We default the provctx value to the
+     * same library context as was used for the EVP call that caused this call
+     * to "provider_activate".
+     */
+#ifdef FIPS_MODE
+    prov->provctx = libctx;
+#endif
     if (prov->init_function == NULL
-        || !prov->init_function(prov, core_dispatch, &provider_dispatch)) {
+        || !prov->init_function(prov, core_dispatch, &provider_dispatch,
+                                &prov->provctx)) {
         CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
         ERR_add_error_data(2, "name=", prov->name);
+#ifndef FIPS_MODE
         DSO_free(prov->module);
         prov->module = NULL;
+#endif
         return 0;
     }
 
@@ -438,7 +460,7 @@ static int provider_activate(OSSL_PROVIDER *prov)
 
 int ossl_provider_activate(OSSL_PROVIDER *prov)
 {
-    if (provider_activate(prov)) {
+    if (provider_activate(prov, NULL)) {
         CRYPTO_THREAD_write_lock(prov->store->lock);
         prov->store->use_fallbacks = 0;
         CRYPTO_THREAD_unlock(prov->store->lock);
@@ -448,6 +470,11 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
     return 0;
 }
 
+void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
+{
+    return prov->provctx;
+}
+
 
 static int provider_forall_loaded(struct provider_store_st *store,
                                   int *found_activated,
@@ -510,7 +537,7 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
                  */
                 if (prov->flag_fallback) {
                     activated_fallback_count++;
-                    provider_activate(prov);
+                    provider_activate(prov, ctx);
                 }
             }
 
@@ -560,31 +587,41 @@ const DSO *ossl_provider_dso(OSSL_PROVIDER *prov)
 
 const char *ossl_provider_module_name(OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     return DSO_get_filename(prov->module);
+#endif
 }
 
 const char *ossl_provider_module_path(OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     /* FIXME: Ensure it's a full path */
     return DSO_get_filename(prov->module);
+#endif
 }
 
 /* Wrappers around calls to the provider */
 void ossl_provider_teardown(const OSSL_PROVIDER *prov)
 {
     if (prov->teardown != NULL)
-        prov->teardown();
+        prov->teardown(prov->provctx);
 }
 
 const OSSL_ITEM *ossl_provider_get_param_types(const OSSL_PROVIDER *prov)
 {
-    return prov->get_param_types == NULL ? NULL : prov->get_param_types(prov);
+    return prov->get_param_types == NULL
+        ? NULL : prov->get_param_types(prov->provctx);
 }
 
 int ossl_provider_get_params(const OSSL_PROVIDER *prov,
                              const OSSL_PARAM params[])
 {
-    return prov->get_params == NULL ? 0 : prov->get_params(prov, params);
+    return prov->get_params == NULL
+        ? 0 : prov->get_params(prov->provctx, params);
 }
 
 
@@ -592,7 +629,7 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                     int operation_id,
                                                     int *no_cache)
 {
-    return prov->query_operation(prov, operation_id, no_cache);
+    return prov->query_operation(prov->provctx, operation_id, no_cache);
 }
 
 /*-
@@ -644,6 +681,8 @@ static int core_get_params(const OSSL_PROVIDER *prov, const OSSL_PARAM params[])
 static const OSSL_DISPATCH core_dispatch_[] = {
     { OSSL_FUNC_CORE_GET_PARAM_TYPES, (void (*)(void))core_get_param_types },
     { OSSL_FUNC_CORE_GET_PARAMS, (void (*)(void))core_get_params },
+    { OSSL_FUNC_CORE_PUT_ERROR, (void (*)(void))ERR_put_error },
+    { OSSL_FUNC_CORE_ADD_ERROR_VDATA, (void (*)(void))ERR_add_error_vdata },
     { 0, NULL }
 };
 static const OSSL_DISPATCH *core_dispatch = core_dispatch_;
index d14cd5b..d1423b1 100644 (file)
 #include "provider_local.h"
 
 OSSL_provider_init_fn ossl_default_provider_init;
+OSSL_provider_init_fn fips_intern_provider_init;
 
 const struct predefined_providers_st predefined_providers[] = {
+#ifdef FIPS_MODE
+    { "fips", fips_intern_provider_init, 1 },
+#else
     { "default", ossl_default_provider_init, 1 },
+#endif
     { NULL, NULL, 0 }
 };
index d9c1fb7..70d2580 100644 (file)
@@ -1,6 +1,5 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
         randfile.c rand_lib.c rand_err.c rand_crng_test.c rand_egd.c \
-        rand_win.c rand_unix.c rand_vms.c drbg_lib.c drbg_ctr.c \
+        rand_win.c rand_unix.c rand_vms.c drbg_lib.c drbg_ctr.c rand_vxworks.c \
         drbg_hash.c drbg_hmac.c
-
index 4e1e2ea..fbe75e6 100644 (file)
@@ -1101,6 +1101,17 @@ static int drbg_add(const void *buf, int num, double randomness)
 
     buflen = (size_t)num;
 
+#ifdef FIPS_MODE
+    /*
+     * NIST SP-800-90A mandates that entropy *shall not* be provided
+     * by the consuming application. By setting the randomness to zero,
+     * we ensure that the buffer contents will be added to the internal
+     * state of the DRBG only as additional data.
+     *
+     * (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
+     */
+    randomness = 0.0;
+#endif
     if (buflen < seedlen || randomness < (double) seedlen) {
 #if defined(OPENSSL_RAND_SEED_NONE)
         /*
@@ -1117,7 +1128,7 @@ static int drbg_add(const void *buf, int num, double randomness)
         return ret;
 #else
         /*
-         * If an os entropy source is avaible then we declare the buffer content
+         * If an os entropy source is available then we declare the buffer content
          * as additional data by setting randomness to zero and trigger a regular
          * reseeding.
          */
@@ -1125,7 +1136,6 @@ static int drbg_add(const void *buf, int num, double randomness)
 #endif
     }
 
-
     if (randomness > (double)seedlen) {
         /*
          * The purpose of this check is to bound |randomness| by a
index 87f4ee1..1b4f167 100644 (file)
  */
 
 #include <string.h>
+#include <openssl/evp.h>
 #include "internal/rand_int.h"
 #include "internal/thread_once.h"
 #include "rand_lcl.h"
 
 static RAND_POOL *crngt_pool;
-static unsigned char *crngt_prev;
+static unsigned char crngt_prev[EVP_MAX_MD_SIZE];
 
-int (*crngt_get_entropy)(unsigned char *) = &rand_crngt_get_entropy_cb;
+int (*crngt_get_entropy)(unsigned char *, unsigned char *, unsigned int *)
+    = &rand_crngt_get_entropy_cb;
 
-int rand_crngt_get_entropy_cb(unsigned char *buf)
+int rand_crngt_get_entropy_cb(unsigned char *buf, unsigned char *md,
+                              unsigned int *md_size)
 {
+    int r;
     size_t n;
     unsigned char *p;
 
-    while ((n = rand_pool_acquire_entropy(crngt_pool)) != 0)
-        if (n >= CRNGT_BUFSIZ) {
-            p = rand_pool_detach(crngt_pool);
+    n = rand_pool_acquire_entropy(crngt_pool);
+    if (n >= CRNGT_BUFSIZ) {
+        p = rand_pool_detach(crngt_pool);
+        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL);
+        if (r != 0)
             memcpy(buf, p, CRNGT_BUFSIZ);
-            rand_pool_reattach(crngt_pool, p);
-            return 1;
-        }
+        rand_pool_reattach(crngt_pool, p);
+        return r;
+    }
     return 0;
-
 }
+
 void rand_crngt_cleanup(void)
 {
     rand_pool_free(crngt_pool);
-    OPENSSL_secure_free(crngt_prev);
     crngt_pool = NULL;
-    crngt_prev = NULL;
 }
 
 int rand_crngt_init(void)
 {
+    unsigned char buf[CRNGT_BUFSIZ];
+
     if ((crngt_pool = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL)
         return 0;
-    if ((crngt_prev = OPENSSL_secure_malloc(CRNGT_BUFSIZ)) != NULL
-        && crngt_get_entropy(crngt_prev))
+    if (crngt_get_entropy(buf, crngt_prev, NULL)) {
+        OPENSSL_cleanse(buf, sizeof(buf));
         return 1;
+    }
     rand_crngt_cleanup();
     return 0;
 }
@@ -74,7 +81,8 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
                               int entropy, size_t min_len, size_t max_len,
                               int prediction_resistance)
 {
-    unsigned char buf[CRNGT_BUFSIZ];
+    unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
+    unsigned int sz;
     RAND_POOL *pool;
     size_t q, r = 0, s, t = 0;
     int attempts = 3;
@@ -87,17 +95,18 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
 
     while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
         s = q > sizeof(buf) ? sizeof(buf) : q;
-        if (!crngt_get_entropy(buf)
-            || memcmp(crngt_prev, buf, CRNGT_BUFSIZ) == 0
+        if (!crngt_get_entropy(buf, md, &sz)
+            || memcmp(crngt_prev, md, sz) == 0
             || !rand_pool_add(pool, buf, s, s * 8))
             goto err;
-        memcpy(crngt_prev, buf, CRNGT_BUFSIZ);
+        memcpy(crngt_prev, md, sz);
         t += s;
         attempts++;
     }
     r = t;
     *pout = rand_pool_detach(pool);
 err:
+    OPENSSL_cleanse(buf, sizeof(buf));
     rand_pool_free(pool);
     return r;
 }
index d793d28..3ce5f7a 100644 (file)
@@ -334,8 +334,10 @@ int drbg_hmac_init(RAND_DRBG *drbg);
  * Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
  * These need to be exposed for the unit tests.
  */
-int rand_crngt_get_entropy_cb(unsigned char *buf);
-extern int (*crngt_get_entropy)(unsigned char *);
+int rand_crngt_get_entropy_cb(unsigned char *buf, unsigned char *md,
+                              unsigned int *md_size);
+extern int (*crngt_get_entropy)(unsigned char *buf, unsigned char *md,
+                                unsigned int *md_size);
 int rand_crngt_init(void);
 void rand_crngt_cleanup(void);
 
index 5d1e0d8..2b3e32d 100644 (file)
@@ -30,7 +30,8 @@
 # include <sys/param.h>
 #endif
 
-#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
+#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
+     || defined(__DJGPP__)
 # include <sys/types.h>
 # include <sys/stat.h>
 # include <fcntl.h>
@@ -88,30 +89,8 @@ static uint64_t get_timer_bits(void);
 # undef OPENSSL_RAND_SEED_EGD
 #endif
 
-#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
-        !defined(OPENSSL_RAND_SEED_NONE)
-# error "UEFI and VXWorks only support seeding NONE"
-#endif
-
-#if defined(OPENSSL_SYS_VXWORKS)
-/* empty implementation */
-int rand_pool_init(void)
-{
-    return 1;
-}
-
-void rand_pool_cleanup(void)
-{
-}
-
-void rand_pool_keep_random_devices_open(int keep)
-{
-}
-
-size_t rand_pool_acquire_entropy(RAND_POOL *pool)
-{
-    return rand_pool_entropy_available(pool);
-}
+#if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE)
+# error "UEFI only supports seeding NONE"
 #endif
 
 #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
@@ -608,7 +587,8 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 # endif
 #endif
 
-#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
+#if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \
+     || defined(__DJGPP__)
 int rand_pool_add_nonce_data(RAND_POOL *pool)
 {
     struct {
diff --git a/crypto/rand/rand_vxworks.c b/crypto/rand/rand_vxworks.c
new file mode 100644 (file)
index 0000000..81774e0
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_SYS_VXWORKS
+NON_EMPTY_TRANSLATION_UNIT
+#else
+# include <openssl/rand.h>
+# include "rand_lcl.h"
+# include "internal/rand_int.h"
+# include "internal/cryptlib.h"
+# include <version.h>
+# include <taskLib.h>
+
+# if defined(OPENSSL_RAND_SEED_NONE)
+/* none means none */
+#  undef OPENSSL_RAND_SEED_OS
+# endif
+
+# if defined(OPENSSL_RAND_SEED_OS)
+#  if _WRS_VXWORKS_MAJOR >= 7
+#    define RAND_SEED_VXRANDLIB
+#  else
+#    error "VxWorks <7 only support RAND_SEED_NONE"
+#  endif
+# endif
+
+# if defined(RAND_SEED_VXRANDLIB)
+#  include <randomNumGen.h>
+# endif
+
+/* Macro to convert two thirty two bit values into a sixty four bit one */
+# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
+
+static uint64_t get_time_stamp(void)
+{
+    struct timespec ts;
+
+    if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+        return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+    return time(NULL);
+}
+
+static uint64_t get_timer_bits(void)
+{
+    uint64_t res = OPENSSL_rdtsc();
+    struct timespec ts;
+
+    if (res != 0)
+        return res;
+
+    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+        return TWO32TO64(ts.tv_sec, ts.tv_nsec);
+    return time(NULL);
+}
+
+/*
+ * empty implementation
+ * vxworks does not need to init/cleanup or keep open the random lib
+ */
+int rand_pool_init(void)
+{
+    return 1;
+}
+
+void rand_pool_cleanup(void)
+{
+}
+
+void rand_pool_keep_random_devices_open(int keep)
+{
+}
+
+int rand_pool_add_additional_data(RAND_POOL *pool)
+{
+    struct {
+        CRYPTO_THREAD_ID tid;
+        uint64_t time;
+    } data;
+
+    memset(&data, 0, sizeof(data));
+
+    /*
+     * Add some noise from the thread id and a high resolution timer.
+     * The thread id adds a little randomness if the drbg is accessed
+     * concurrently (which is the case for the <master> drbg).
+     */
+    data.tid = CRYPTO_THREAD_get_current_id();
+    data.time = get_timer_bits();
+
+    return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+int rand_pool_add_nonce_data(RAND_POOL *pool)
+{
+    struct {
+        pid_t pid;
+        CRYPTO_THREAD_ID tid;
+        uint64_t time;
+    } data;
+
+    memset(&data, 0, sizeof(data));
+
+    /*
+     * Add process id, thread id, and a high resolution timestamp to
+     * ensure that the nonce is unique with high probability for
+     * different process instances.
+     */
+    data.pid = getpid();
+    data.tid = CRYPTO_THREAD_get_current_id();
+    data.time = get_time_stamp();
+
+    return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
+size_t rand_pool_acquire_entropy(RAND_POOL *pool)
+{
+# if defined(RAND_SEED_VXRANDLIB)
+    /* vxRandLib based entropy method */
+    size_t bytes_needed;
+
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+    if (bytes_needed > 0)
+    {
+        int retryCount = 0;
+        STATUS result = ERROR;
+        unsigned char *buffer;
+
+        buffer = rand_pool_add_begin(pool, bytes_needed);
+        while ((result != OK) && (retryCount < 10)) {
+            RANDOM_NUM_GEN_STATUS status = randStatus();
+
+            if ((status == RANDOM_NUM_GEN_ENOUGH_ENTROPY)
+                    || (status == RANDOM_NUM_GEN_MAX_ENTROPY) ) {
+                result = randBytes(buffer, bytes_needed);
+                if (result == OK)
+                    rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
+                /*
+                 * no else here: randStatus said ok, if randBytes failed
+                 * it will result in another loop or no entropy
+                 */
+            } else {
+                /*
+                 * give a minimum delay here to allow OS to collect more
+                 * entropy. taskDelay duration will depend on the system tick,
+                 * this is by design as the sw-random lib uses interrupts
+                 * which will at least happen during ticks
+                 */
+                taskDelay(5);
+            }
+            retryCount++;
+        }
+    }
+    return rand_pool_entropy_available(pool);
+# else
+    /*
+     * SEED_NONE means none, without randlib we dont have entropy and
+     * rely on it being added externally
+     */
+    return rand_pool_entropy_available(pool);
+# endif /* defined(RAND_SEED_VXRANDLIB) */
+}
+
+#endif /* OPENSSL_SYS_VXWORKS */
index 4f65dfa..96a13b3 100644 (file)
@@ -25,11 +25,9 @@ int RSA_check_key(const RSA *key)
 int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
 {
 #ifdef FIPS_MODE
-    if (!(rsa_sp800_56b_check_public(key)
-            && rsa_sp800_56b_check_private(key)
-            && rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key))
-        return 0;
-
+    return rsa_sp800_56b_check_public(key)
+               && rsa_sp800_56b_check_private(key)
+               && rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key));
 #else
     BIGNUM *i, *j, *k, *l, *m;
     BN_CTX *ctx;
index 8931d7e..bd0870b 100644 (file)
@@ -56,7 +56,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
 
     if (rctx == NULL)
         return 0;
-    rctx->nbits = 1024;
+    rctx->nbits = 2048;
     rctx->primes = RSA_DEFAULT_PRIME_NUM;
     if (pkey_ctx_is_pss(ctx))
         rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
@@ -89,6 +89,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
     dctx->pad_mode = sctx->pad_mode;
     dctx->md = sctx->md;
     dctx->mgf1md = sctx->mgf1md;
+    dctx->saltlen = sctx->saltlen;
     if (sctx->oaep_label) {
         OPENSSL_free(dctx->oaep_label);
         dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
index e587021..e4183e0 100644 (file)
@@ -1,2 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=stack.c
+SOURCE[../../providers/fips]=stack.c
index 2f0ed64..450a4e1 100644 (file)
@@ -11,7 +11,6 @@
 #include "internal/cryptlib.h"
 #include "internal/numbers.h"
 #include <openssl/stack.h>
-#include <openssl/objects.h>
 #include <errno.h>
 #include <openssl/e_os2.h>      /* For ossl_inline */
 
@@ -307,20 +306,20 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
     }
     if (data == NULL)
         return -1;
-    r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
-                        ret_val_options);
+    r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
+                     ret_val_options);
 
     return r == NULL ? -1 : (int)((const void **)r - st->data);
 }
 
 int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
 {
-    return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
+    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH);
 }
 
 int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
 {
-    return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
+    return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH);
 }
 
 int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
index 0a6c903..0d351ca 100644 (file)
@@ -175,7 +175,10 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
     return 1;
 }
 
-# ifdef OPENSSL_SYS_UNIX
+# ifndef FIPS_MODE
+/* TODO(3.0): No fork protection in FIPS module yet! */
+
+#  ifdef OPENSSL_SYS_UNIX
 static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
 
 static void fork_once_func(void)
@@ -183,14 +186,15 @@ static void fork_once_func(void)
     pthread_atfork(OPENSSL_fork_prepare,
                    OPENSSL_fork_parent, OPENSSL_fork_child);
 }
-# endif
+#  endif
 
 int openssl_init_fork_handlers(void)
 {
-# ifdef OPENSSL_SYS_UNIX
+#  ifdef OPENSSL_SYS_UNIX
     if (pthread_once(&fork_once_control, fork_once_func) == 0)
         return 1;
-# endif
+#  endif
     return 0;
 }
+# endif /* FIPS_MODE */
 #endif
index 25cf56e..f95d397 100644 (file)
@@ -15,10 +15,10 @@ ossl_method_store_cache_get, ossl_method_store_cache_set
 
  typedef struct ossl_method_store_st OSSL_METHOD_STORE;
 
- OSSL_METHOD_STORE *ossl_method_store_new(void);
+ OSSL_METHOD_STORE *ossl_method_store_new(OPENSSL_CTX *ctx);
  void ossl_method_store_free(OSSL_METHOD_STORE *store);
- int ossl_method_store_init(void);
- void ossl_method_store_cleanup(void);
+ int ossl_method_store_init(OPENSSL_CTX *ctx);
+ void ossl_method_store_cleanup(OPENSSL_CTX *ctx);
  int ossl_method_store_add(OSSL_METHOD_STORE *store,
                            int nid, const char *properties,
                            void *method, void (*method_destruct)(void *));
@@ -51,12 +51,14 @@ separately (see L</Cache Functions> below).
 
 =head2 Store Functions
 
-ossl_method_store_init() initialises the method store subsystem.
+ossl_method_store_init() initialises the method store subsystem in the scope of
+the library context B<ctx>.
 
 ossl_method_store_cleanup() cleans up and shuts down the implementation method
-store subsystem.
+store subsystem in the scope of the library context B<ctx>.
 
-ossl_method_store_new() create a new empty method store.
+ossl_method_store_new() create a new empty method store using the supplied
+B<ctx> to allow access to the required underlying property data.
 
 ossl_method_store_free() frees resources allocated to B<store>.
 
index 881aaf9..2679a7e 100644 (file)
@@ -10,17 +10,16 @@ evp_generic_fetch - generic algorithm fetcher and method creator for EVP
  #include "evp_locl.h"
 
  void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
-                         const char *algorithm, const char *properties,
-                         void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
+                         const char *name, const char *properties,
+                         void *(*new_method)(const OSSL_DISPATCH *fns,
                                              OSSL_PROVIDER *prov),
                          int (*upref_method)(void *),
-                         void (*free_method)(void *),
-                         int (*nid_method)(void *));
+                         void (*free_method)(void *));
 
 =head1 DESCRIPTION
 
 evp_generic_fetch() calls ossl_method_construct() with the given
-C<libctx>, C<operation_id>, C<algorithm>, and C<properties> and uses
+C<libctx>, C<operation_id>, C<name>, and C<properties> and uses
 it to create an EVP method with the help of the functions
 C<new_method>, C<upref_method>, and C<free_method>.
 
@@ -42,10 +41,6 @@ one.
 
 frees the given method.
 
-=item nid_method()
-
-returns the nid associated with the given method.
-
 =back
 
 =head1 RETURN VALUES
@@ -80,7 +75,6 @@ And here's the implementation of the FOO method fetcher:
     /* typedef struct evp_foo_st EVP_FOO */
     struct evp_foo_st {
         OSSL_PROVIDER *prov;
-        int nid;
        CRYPTO_REF_COUNT refcnt;
         OSSL_OP_foo_newctx_fn *newctx;
         OSSL_OP_foo_init_fn *init;
@@ -93,7 +87,7 @@ And here's the implementation of the FOO method fetcher:
      * In this example, we have a public method creator and destructor.
      * It's not absolutely necessary, but is in the spirit of OpenSSL.
      */
-    EVP_FOO *EVP_FOO_meth_from_dispatch(int foo_type, const OSSL_DISPATCH *fns,
+    EVP_FOO *EVP_FOO_meth_from_dispatch(const OSSL_DISPATCH *fns,
                                         OSSL_PROVIDER *prov)
     {
         EVP_FOO *foo = NULL;
@@ -120,7 +114,6 @@ And here's the implementation of the FOO method fetcher:
                 break;
             }
         }
-        foo->nid = foo_type;
         foo->prov = prov;
         if (prov)
             ossl_provider_upref(prov);
@@ -138,10 +131,10 @@ And here's the implementation of the FOO method fetcher:
         }
     }
 
-    static void *foo_from_dispatch(int nid, const OSSL_DISPATCH *fns,
+    static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
                                    OSSL_PROVIDER *prov)
     {
-        return EVP_FOO_meth_from_dispatch(nid, fns, prov);
+        return EVP_FOO_meth_from_dispatch(fns, prov);
     }
 
     static int foo_upref(void *vfoo)
@@ -159,11 +152,21 @@ And here's the implementation of the FOO method fetcher:
     }
 
     EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx,
-                           const char *algorithm,
+                           const char *name,
                            const char *properties)
     {
-        return evp_generic_fetch(ctx, OSSL_OP_FOO, algorithm, properties,
-                                 foo_from_dispatch, foo_upref, foo_free);
+        EVP_FOO *foo =
+            evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
+                              foo_from_dispatch, foo_upref, foo_free);
+
+        /*
+         * If this method exists in legacy form, with a constant NID for the
+         * given |name|, this is the spot to find that NID and set it in
+         * the newly constructed EVP_FOO instance.
+         */
+
+        return foo;
+
     }
 
 And finally, the library functions:
index db066ad..d9b3f5d 100644 (file)
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-openssl_ctx_new_index, openssl_ctx_get_data - internal OPENSSL_CTX routines
+openssl_ctx_get_data, openssl_ctx_run_once, openssl_ctx_onfree
+- internal OPENSSL_CTX routines
 
 =head1 SYNOPSIS
 
@@ -10,12 +11,16 @@ openssl_ctx_new_index, openssl_ctx_get_data - internal OPENSSL_CTX routines
  #include "internal/cryptlib.h"
 
  typedef struct openssl_ctx_method {
-     void *(*new_func)(void);
+     void *(*new_func)(OPENSSL_CTX *ctx);
      void (*free_func)(void *);
  } OPENSSL_CTX_METHOD;
 
- int openssl_ctx_new_index(const OPENSSL_CTX_METHOD *meth);
- void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index);
+ void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,
+                            const OPENSSL_CTX_METHOD *meth);
+
+ int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
+                          openssl_ctx_run_once_fn run_once_fn);
+ int openssl_ctx_onfree(OPENSSL_CTX *ctx, openssl_ctx_onfree_fn onfreefn);
 
 =head1 DESCRIPTION
 
@@ -23,26 +28,32 @@ Internally, the OpenSSL library context C<OPENSSL_CTX> is implemented
 as a C<CRYPTO_EX_DATA>, which allows data from diverse parts of the
 library to be added and removed dynamically.
 Each such data item must have a corresponding CRYPTO_EX_DATA index
-associated with it.
+associated with it. Unlike normal CRYPTO_EX_DATA objects we use static indexes
+to identify data items. These are mapped transparetnly to CRYPTO_EX_DATA dynamic
+indexes internally to the implementation.
 See the example further down to see how that's done.
 
-openssl_ctx_new_index() allocates a new library context index, and
-associates it with the functions given through C<meth>.
-The functions given through that method are used to create or free
-items that are stored at that index whenever a library context is
-created or freed, meaning that the code that use a data item of that
+openssl_ctx_get_data() is used to retrieve a pointer to the data in
+the library context C<ctx> associated with the given C<index>. An
+OPENSSL_CTX_METHOD must be defined and given in the C<meth> parameter. The index
+for it should be defined in cryptlib.h. The functions through the method are
+used to create or free items that are stored at that index whenever a library
+context is created or freed, meaning that the code that use a data item of that
 index doesn't have to worry about that, just use the data available.
 
 Deallocation of an index happens automatically when the library
 context is freed.
 
-openssl_ctx_get_data() is used to retrieve a pointer to the data in
-the library context C<ctx> associated with the given C<index>.
+openssl_ctx_run_once is used to run some initialisation routine C<run_once_fn>
+exactly once per library context C<ctx> object. Each initialisation routine
+should be allocate a unique run once index in cryptlib.h.
 
-=head1 RETURN VALUES
+Any resources allocated via a run once initialisation routine can be cleaned up
+using openssl_ctx_onfree. This associates an "on free" routine C<onfreefn> with
+the library context C<ctx>. When C<ctx> is freed all associated "on free"
+routines are called.
 
-openssl_ctx_new_index() returns -1 on error, otherwise the allocated
-index number.
+=head1 RETURN VALUES
 
 openssl_ctx_get_data() returns a pointer on success, or C<NULL> on
 failure.
@@ -53,17 +64,14 @@ failure.
 
 For a type C<FOO> that should end up in the OpenSSL library context, a
 small bit of initialization is needed, i.e. to associate a constructor
-and a destructor to a new index.
-
- /* The index will always be entirely global, and dynamically allocated */
- static int foo_index = -1;
+and a destructor to an index.
 
  typedef struct foo_st {
      int i;
      void *data;
  } FOO;
 
- static void *foo_new(void)
+ static void *foo_new(OPENSSL_CTX *ctx)
  {
      FOO *ptr = OPENSSL_zalloc(sizeof(*foo));
      if (ptr != NULL)
@@ -74,27 +82,49 @@ and a destructor to a new index.
  {
      OPENSSL_free(ptr);
  }
- static const OPENSSL_CTX_METHOD foo_method = {
+
+ /*
+  * Include a reference to this in the methods table in context.c 
+  * OPENSSL_CTX_FOO_INDEX should be added to internal/cryptlib.h
+  */
+ const OPENSSL_CTX_METHOD foo_method = {
      foo_new,
      foo_free
  };
 
- static int foo_init(void)
- {
-     foo_index = openssl_ctx_new_index(foo_method);
-
-     return foo_index != -1;
- }
-
 =head2 Usage
 
 To get and use the data stored in the library context, simply do this:
 
  /*
   * ctx is received from a caller,
-  * foo_index comes from the example above
   */
- FOO *data = openssl_ctx_get_data(ctx, foo_index);
+ FOO *data = openssl_ctx_get_data(ctx, OPENSSL_CTX_FOO_INDEX, &foo_method);
+
+=head2 Run Once
+
+ void foo_cleanup(OPENSSL_CTX *ctx)
+ {
+     /* Free foo resources associated with ctx */
+ }
+
+ static openssl_ctx_run_once_fn do_foo_init;
+ static int do_foo_init(OPENSSL_CTX *ctx)
+ {
+     /* Allocate and initialise some foo resources and associated with ctx */
+     return openssl_ctx_onfree(ctx, &foo_cleanup)
+ }
+
+ int foo_some_function(OPENSSL_CTX *ctx)
+ {
+    if (!openssl_ctx_run_once(ctx,
+                              OPENSSL_CTX_FOO_RUN_ONCE_INDEX,
+                              do_foo_init))
+        return 0;
+
+    /* Do some work using foo resources in ctx */
+ }
+
 
 =head1 SEE ALSO
 
index 7b682dd..60de260 100644 (file)
@@ -11,17 +11,17 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
 
  struct ossl_method_construct_method_st {
      /* Create store */
-     void *(*alloc_tmp_store)(void);
+     void *(*alloc_tmp_store)(OPENSSL_CTX *ctx);
      /* Remove a store */
      void (*dealloc_tmp_store)(void *store);
      /* Get an already existing method from a store */
-     void *(*get)(OPENSSL_CTX *libctx, void *store, const char *propquery,
-                  void *data);
+     void *(*get)(OPENSSL_CTX *libctx, void *store, const char *name,
+                  const char *propquery, void *data);
      /* Store a method in a store */
-     int (*put)(OPENSSL_CTX *libctx, void *store, const char *propdef,
-                void *method, void *data);
+     int (*put)(OPENSSL_CTX *libctx, void *store, void *method,
+                const char *name, const char *propdef, void *data);
      /* Construct a new method */
-     void *(*construct)(const char *algorithm_name, const OSSL_DISPATCH *fns,
+     void *(*construct)(const char *name, const OSSL_DISPATCH *fns,
                         OSSL_PROVIDER *prov, void *data);
      /* Destruct a method */
      void (*destruct)(void *method);
@@ -33,6 +33,7 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
                              int force_cache,
                              OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
 
+
 =head1 DESCRIPTION
 
 All libcrypto sub-systems that want to create their own methods based
@@ -65,7 +66,7 @@ function pointers:
 
 =item alloc_tmp_store()
 
-Create a temporary method store.
+Create a temporary method store in the scope of the library context C<ctx>.
 This store is used to temporarily store methods for easier lookup, for
 when the provider doesn't want its dispatch table stored in a longer
 term cache.
@@ -76,14 +77,15 @@ Remove a temporary store.
 
 =item get()
 
-Look up an already existing method from a store.
+Look up an already existing method from a store by name.
 
 The store may be given with C<store>.
 B<NULL> is a valid value and means that a sub-system default store
 must be used.
 This default store should be stored in the library context C<libctx>.
 
-The method to be looked up should be identified with data from C<data>
+The method to be looked up should be identified with the given C<name> and
+data from C<data>
 (which is the C<mcm_data> that was passed to ossl_construct_method())
 and the provided property query C<propquery>.
 
@@ -99,15 +101,15 @@ B<NULL> is a valid value and means that a sub-system default store
 must be used.
 This default store should be stored in the library context C<libctx>.
 
-The method should be associated with the given property definition
-C<propdef> and any identification data given through C<data> (which is
+The method should be associated with the given C<name> and property definition
+C<propdef> as well as any identification data given through C<data> (which is
 the C<mcm_data> that was passed to ossl_construct_method()).
 
 This function is expected to increment the C<method>'s reference count.
 
 =item construct()
 
-Constructs a sub-system method for the given C<algorithm_name> and the given
+Constructs a sub-system method for the given C<name> and the given
 dispatch table C<fns>.
 
 The associated I<provider object> C<prov> is passed as well, to make
@@ -132,7 +134,7 @@ B<NULL> on error.
 
 =head1 HISTORY
 
-This functionality was added to OpenSSL 3.0.0.
+This functionality was added to OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod
new file mode 100644 (file)
index 0000000..07dc914
--- /dev/null
@@ -0,0 +1,74 @@
+=pod
+
+=head1 NAME
+
+ossl_namemap_new, ossl_namemap_free, ossl_namemap_stored,
+ossl_namemap_add, ossl_namemap_name, ossl_namemap_number
+- internal number E<lt>-E<gt> name map
+
+=head1 SYNOPSIS
+
+ #include "internal/cryptlib.h"
+
+ OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx);
+
+ OSSL_NAMEMAP *ossl_namemap_new(void);
+ void ossl_namemap_free(OSSL_NAMEMAP *namemap);
+
+ int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name);
+ const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number);
+ int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name);
+
+=head1 DESCRIPTION
+
+A B<OSSL_NAMEMAP> is a simple number E<lt>-E<gt> name map, which can
+be used to give any arbitrary name (any string) a unique dynamic
+identity that is valid throughout the lifetime of the associated
+library context.
+
+ossl_namemap_new() and ossl_namemap_free() construct and destruct a
+new B<OSSL_NAMEMAP>.
+This is suitable to use when the B<OSSL_NAMEMAP> is embedded in other
+structures, or should be independent for any reason.
+
+ossl_namemap_stored() finds or auto-creat