Browse Source

Add --fips-key configuration parameter to fipsinstall application.

Change default FIPS HMAC KEY from all-zero's
Use default FIPSKEY if not given on command line.
Make all -macopt in fipsinstall optional
Make all tests, except fipsinstall, use the default -macopt and
-mac_name flags.
Define and use FIPSDIR variable on VMS/MMS.
Also use SRCDIR/BLDDIR in SRCTOP/BLDTOP.

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12235)
Rich Salz 3 years ago
parent
commit
3121425830

+ 1 - 0
.gitignore

@@ -24,6 +24,7 @@
 /include/crypto/*_conf.h
 /include/openssl/configuration.h
 /include/openssl/opensslv.h
+/include/openssl/fipskey.h
 
 # Auto generated doc files
 doc/man1/openssl-*.pod

+ 6 - 3
Configurations/descrip.mms.tmpl

@@ -106,6 +106,7 @@ OPTIONS={- $config{options} -}
 CONFIGURE_ARGS=({- join(", ",quotify_l(@{$config{perlargv}})) -})
 SRCDIR={- $config{sourcedir} -}
 BLDDIR={- $config{builddir} -}
+FIPSKEY={- $config{FIPSKEY} -}
 
 # Allow both V and VERBOSE to indicate verbosity.  This only applies
 # to testing.
@@ -439,19 +440,21 @@ all : build_sw build_docs
 test : tests
 {- dependmagic('tests'); -} : build_programs_nodep, build_modules_nodep copy-utils
         @ ! {- output_off() if $disabled{tests}; "" -}
-        DEFINE SRCTOP {- sourcedir() -}
-        DEFINE BLDTOP {- builddir() -}
+        DEFINE SRCTOP "$(SRCDIR)"
+        DEFINE BLDTOP "$(BLDDIR)"
+        DEFINE FIPSKEY "$(FIPSKEY)"
         IF "$(VERBOSE)" .NES. "" THEN DEFINE VERBOSE "$(VERBOSE)"
         $(PERL) {- sourcefile("test", "run_tests.pl") -} $(TESTS)
         DEASSIGN BLDTOP
         DEASSIGN SRCTOP
+        DEASSIGN FIPSKEY
         @ ! {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
         @ WRITE SYS$OUTPUT "Tests are not supported with your chosen Configure options"
         @ ! {- output_on() if !$disabled{tests}; "" -}
 
 list-tests :
         @ ! {- output_off() if $disabled{tests}; "" -}
-        @ DEFINE SRCTOP {- sourcedir() -}
+        @ DEFINE SRCTOP "$(SRCDIR)"
         @ $(PERL) {- sourcefile("test", "run_tests.pl") -} list
         @ DEASSIGN SRCTOP
         @ ! {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}

+ 2 - 0
Configurations/unix-Makefile.tmpl

@@ -61,6 +61,7 @@ OPTIONS={- $config{options} -}
 CONFIGURE_ARGS=({- join(", ",quotify_l(@{$config{perlargv}})) -})
 SRCDIR={- $config{sourcedir} -}
 BLDDIR={- $config{builddir} -}
+FIPSKEY={- $config{FIPSKEY} -}
 
 VERSION={- "$config{full_version}" -}
 MAJOR={- $config{major} -}
@@ -475,6 +476,7 @@ test: tests
 	( SRCTOP=$(SRCDIR) \
 	  BLDTOP=$(BLDDIR) \
 	  PERL="$(PERL)" \
+	  FIPSKEY="$(FIPSKEY)" \
 	  EXE_EXT={- platform->binext() -} \
 	  $(PERL) $(SRCDIR)/test/run_tests.pl $(TESTS) )
 	@ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}

+ 2 - 0
Configurations/windows-makefile.tmpl

@@ -37,6 +37,7 @@
 PLATFORM={- $config{target} -}
 SRCDIR={- $config{sourcedir} -}
 BLDDIR={- $config{builddir} -}
+FIPSKEY={- $config{FIPSKEY} -}
 
 VERSION={- "$config{full_version}" -}
 MAJOR={- $config{major} -}
@@ -405,6 +406,7 @@ test: tests
 	set SRCTOP=$(SRCDIR)
 	set BLDTOP=$(BLDDIR)
 	set PERL=$(PERL)
+	set FIPSKEY=$(FIPSKEY) \
 	"$(PERL)" "$(SRCDIR)\test\run_tests.pl" $(TESTS)
 	@{- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -}
 	@$(ECHO) "Tests are not supported with your chosen Configure options"

+ 13 - 0
Configure

@@ -244,6 +244,9 @@ my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
 
 $config{sourcedir} = abs2rel($srcdir);
 $config{builddir} = abs2rel($blddir);
+# echo -n 'holy hand grenade of antioch' | openssl sha256
+$config{FIPSKEY} =
+    'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813';
 
 # Collect reconfiguration information if needed
 my @argvcopy=@ARGV;
@@ -934,6 +937,16 @@ while (@argvcopy)
                             push @seed_sources, $x;
                             }
                         }
+                elsif (/^--fips-key=(.*)$/)
+                        {
+                        $user{FIPSKEY}=lc($1);
+                        die "Non-hex character in FIPS key\n"
+                           if $user{FIPSKEY} =~ /[^a-f0-9]/;
+                        die "FIPS key must have even number of characters\n"
+                           if length $1 & 1;
+                        die "FIPS key too long (64 bytes max)\n"
+                           if length $1 > 64;
+                        }
                 elsif (/^--cross-compile-prefix=(.*)$/)
                         {
                         $user{CROSS_COMPILE}=$1;

+ 14 - 0
INSTALL.md

@@ -21,6 +21,7 @@ Table of Contents
    - [Compiler Warnings](#compiler-warnings)
    - [ZLib Flags](#zlib-flags)
    - [Seeding the Random Generator](#seeding-the-random-generator)
+   - [Setting the FIPS HMAC key](#setting-the-FIPS-HMAC-key)
    - [Enable and Disable Features](#enable-and-disable-features)
    - [Displaying configuration data](#displaying-configuration-data)
  - [Installation Steps in Detail](#installation-steps-in-detail)
@@ -465,6 +466,19 @@ at the end of this document.
 
 [rng]: #notes-on-random-number-generation
 
+Setting the FIPS HMAC key
+-------------------------
+
+    --fips-key=value
+
+As part of its self-test validation, the FIPS module must verify itself
+by performing a SHA-256 HMAC computation on itself. The default key is
+the SHA256 value of "the holy handgrenade of antioch" and is sufficient
+for meeting the FIPS requirements.
+
+To change the key to a different value, use this flag. The value should
+be a hex string no more than 64 characters.
+
 Enable and Disable Features
 ---------------------------
 

+ 15 - 5
apps/fipsinstall.c

@@ -15,6 +15,7 @@
 #include <openssl/fips_names.h>
 #include <openssl/core_names.h>
 #include <openssl/self_test.h>
+#include <openssl/fipskey.h>
 #include "apps.h"
 #include "progs.h"
 
@@ -266,7 +267,7 @@ end:
 
 int fipsinstall_main(int argc, char **argv)
 {
-    int ret = 1, verify = 0;
+    int ret = 1, verify = 0, gotkey = 0, gotdigest = 0;
     BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;
     char *in_fname = NULL, *out_fname = NULL, *prog, *section_name = NULL;
     char *prov_name = NULL, *module_fname = NULL;
@@ -283,6 +284,8 @@ int fipsinstall_main(int argc, char **argv)
     CONF *conf = NULL;
 
     section_name = DEFAULT_FIPS_SECTION;
+    if ((opts = sk_OPENSSL_STRING_new_null()) == NULL)
+        goto end;
 
     prog = opt_init(argc, argv, fipsinstall_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -327,10 +330,12 @@ opthelp:
             mac_name = opt_arg();
             break;
         case OPT_MACOPT:
-            if (opts == NULL)
-                opts = sk_OPENSSL_STRING_new_null();
-            if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
+            if (!sk_OPENSSL_STRING_push(opts, opt_arg()))
                 goto opthelp;
+            if (strncmp(opt_arg(), "hexkey:", 7) == 0)
+                gotkey = 1;
+            else if (strncmp(opt_arg(), "digest:", 7) == 0)
+                gotdigest = 1;
             break;
         case OPT_VERIFY:
             verify = 1;
@@ -341,7 +346,6 @@ opthelp:
     if (module_fname == NULL
         || (verify && in_fname == NULL)
         || (!verify && (out_fname == NULL || prov_name == NULL))
-        || opts == NULL
         || argc != 0)
         goto opthelp;
 
@@ -350,6 +354,12 @@ opthelp:
             || self_test_corrupt_type != NULL)
         OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);
 
+    /* Use the default FIPS HMAC digest and key if not specified. */
+    if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256"))
+        goto end;
+    if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING))
+        goto end;
+
     module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
     if (module_bio == NULL) {
         BIO_printf(bio_err, "Failed to open module file\n");

+ 2 - 0
build.info

@@ -10,11 +10,13 @@ DEPEND[libssl]=libcrypto
 # Empty DEPEND "indices" means the dependencies are expected to be built
 # unconditionally before anything else.
 DEPEND[]=include/openssl/configuration.h include/openssl/opensslv.h \
+         include/openssl/fipskey.h \
          include/crypto/bn_conf.h include/crypto/dso_conf.h \
          doc/man7/openssl_user_macros.pod
 
 GENERATE[include/openssl/configuration.h]=include/openssl/configuration.h.in
 GENERATE[include/openssl/opensslv.h]=include/openssl/opensslv.h.in
+GENERATE[include/openssl/fipskey.h]=include/openssl/fipskey.h.in
 GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in
 GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in
 GENERATE[doc/man7/openssl_user_macros.pod]=doc/man7/openssl_user_macros.pod.in

+ 6 - 1
doc/man1/openssl-fipsinstall.pod.in

@@ -94,7 +94,7 @@ C<openssl list -mac-algorithms>.  The default is B<HMAC>.
 Passes options to the MAC algorithm.
 A comprehensive list of controls can be found in the EVP_MAC implementation
 documentation.
-Common control strings used for fipsinstall are:
+Common control strings used for this command are:
 
 =over 4
 
@@ -104,12 +104,16 @@ Specifies the MAC key as an alphanumeric string (use if the key contains
 printable characters only).
 The string length must conform to any restrictions of the MAC algorithm.
 A key must be specified for every MAC algorithm.
+If no key is provided, the default that was specified when OpenSSL was
+configured is used.
 
 =item B<hexkey>:I<string>
 
 Specifies the MAC key in hexadecimal form (two hex digits per byte).
 The key length must conform to any restrictions of the MAC algorithm.
 A key must be specified for every MAC algorithm.
+If no key is provided, the default that was specified when OpenSSL was
+configured is used.
 
 =item B<digest>:I<string>
 
@@ -118,6 +122,7 @@ characters only).
 The string length must conform to any restrictions of the MAC algorithm.
 To see the list of supported digests, use the command
 C<openssl list -digest-commands>.
+The default digest is SHA-256.
 
 =back
 

+ 30 - 0
include/openssl/fipskey.h.in

@@ -0,0 +1,30 @@
+/*
+ * {- join("\n * ", @autowarntext) -}
+ *
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_FIPSKEY_H
+# define OPENSSL_FIPSKEY_H
+
+# ifdef  __cplusplus
+extern "C" {
+# endif
+
+/*
+ * The FIPS validation HMAC key, usable as an array initializer.
+ */
+#define FIPS_KEY_ELEMENTS \
+    {- join(', ', map { "0x$_" } unpack("(A2)*", $config{FIPSKEY})) -}
+
+/*
+ * The FIPS validation key, as a string.
+ */
+#define FIPS_KEY_STRING "{- $config{FIPSKEY} -}"
+
+#endif

+ 2 - 1
providers/fips/self_test.c

@@ -11,6 +11,7 @@
 #include <openssl/evp.h>
 #include <openssl/params.h>
 #include <openssl/crypto.h>
+#include <openssl/fipskey.h>
 #include "e_os.h"
 /*
  * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
@@ -35,7 +36,7 @@
 
 static int FIPS_state = FIPS_STATE_INIT;
 static CRYPTO_RWLOCK *self_test_lock = NULL;
-static unsigned char fixed_key[32] = { 0 };
+static unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS };
 
 static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
 DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)

+ 13 - 12
test/recipes/03-test_fipsinstall.t

@@ -27,18 +27,19 @@ plan skip_all => "Test only supported in a fips build" if disabled("fips");
 plan tests => 12;
 
 my $infile = bldtop_file('providers', platform->dso('fips'));
+my $fipskey = $ENV{FIPSKEY} // '00';
 
 # fail if no module name
 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module',
              '-provider_name', 'fips',
-             '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
              '-section_name', 'fips_install'])),
    "fipsinstall fail");
 
 # fail to verify if the configuration file is missing
 ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
              '-provider_name', 'fips', '-mac_name', 'HMAC',
-             '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
              '-section_name', 'fips_install', '-verify'])),
    "fipsinstall verify fail");
 
@@ -46,56 +47,56 @@ ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
 # output a fips.cnf file containing mac data
 ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install'])),
    "fipsinstall");
 
 # verify the fips.cnf file
 ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install', '-verify'])),
    "fipsinstall verify");
 
 # fail to verify the fips.cnf file if a different key is used
 ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
              '-provider_name', 'fips', '-mac_name', 'HMAC',
-             '-macopt', 'digest:SHA256', '-macopt', 'hexkey:01',
+             '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
              '-section_name', 'fips_install', '-verify'])),
    "fipsinstall verify fail bad key");
 
 # fail to verify the fips.cnf file if a different mac digest is used
 ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
              '-provider_name', 'fips', '-mac_name', 'HMAC',
-             '-macopt', 'digest:SHA512', '-macopt', 'hexkey:00',
+             '-macopt', 'digest:SHA512', '-macopt', "hexkey:$fipskey",
              '-section_name', 'fips_install', '-verify'])),
    "fipsinstall verify fail incorrect digest");
 
 # corrupt the module hmac
 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install', '-corrupt_desc', 'HMAC'])),
    "fipsinstall fails when the module integrity is corrupted");
 
 # corrupt the first digest
 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install', '-corrupt_desc', 'SHA1'])),
    "fipsinstall fails when the digest result is corrupted");
 
 # corrupt another digest
 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install', '-corrupt_desc', 'SHA3'])),
    "fipsinstall fails when the digest result is corrupted");
 
 # corrupt DRBG
 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
             '-provider_name', 'fips', '-mac_name', 'HMAC',
-            '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+            '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
             '-section_name', 'fips_install', '-corrupt_desc', 'CTR'])),
    "fipsinstall fails when the DRBG CTR result is corrupted");
 
@@ -106,7 +107,7 @@ SKIP: {
 
     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
                 '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
                 '-section_name', 'fips_install',
                 '-corrupt_desc', 'DH',
                 '-corrupt_type', 'KAT_KA'])),
@@ -119,7 +120,7 @@ SKIP: {
         if disabled("dsa");
     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
                 '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
                 '-section_name', 'fips_install',
                 '-corrupt_desc', 'DSA',
                 '-corrupt_type', 'KAT_Signature'])),

+ 1 - 2
test/recipes/30-test_acvp.t

@@ -32,8 +32,7 @@ plan tests => 2;
 ok(run(app(['openssl', 'fipsinstall',
            '-out', bldtop_file('providers', 'fipsmodule.cnf'),
            '-module', $infile,
-           '-provider_name', 'fips', '-mac_name', 'HMAC',
-           '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+           '-provider_name', 'fips',
            '-section_name', 'fips_sect'])),
    "fipsinstall");
 

+ 1 - 2
test/recipes/30-test_evp.t

@@ -85,8 +85,7 @@ unless ($no_fips) {
     ok(run(app(['openssl', 'fipsinstall',
                 '-out', bldtop_file('providers', 'fipsmodule.cnf'),
                 '-module', $infile,
-                '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-provider_name', 'fips',
                 '-section_name', 'fips_sect'])),
        "fipsinstall");
 }

+ 1 - 2
test/recipes/30-test_evp_fetch_prov.t

@@ -47,8 +47,7 @@ unless ($no_fips) {
         cmd     => app(['openssl', 'fipsinstall',
                         '-out', bldtop_file('providers', 'fipsmodule.cnf'),
                         '-module', bldtop_file('providers', platform->dso('fips')),
-                        '-provider_name', 'fips', '-mac_name', 'HMAC',
-                        '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                        '-provider_name', 'fips',
                         '-section_name', 'fips_sect']),
         message => "fipsinstall"
     };

+ 1 - 2
test/recipes/80-test_ssl_new.t

@@ -118,8 +118,7 @@ unless ($no_fips) {
     ok(run(app(['openssl', 'fipsinstall',
                 '-out', bldtop_file('providers', 'fipsmodule.cnf'),
                 '-module', bldtop_file('providers', platform->dso('fips')),
-                '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-provider_name', 'fips',
                 '-section_name', 'fips_sect'])),
        "fipsinstall");
 }

+ 1 - 2
test/recipes/80-test_ssl_old.t

@@ -86,8 +86,7 @@ unless ($no_fips) {
     ok(run(app(['openssl', 'fipsinstall',
                 '-out', bldtop_file('providers', 'fipsmodule.cnf'),
                 '-module', bldtop_file('providers', platform->dso('fips')),
-                '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-provider_name', 'fips',
                 '-section_name', 'fips_sect'])),
        "fipsinstall");
 }

+ 1 - 2
test/recipes/90-test_sslapi.t

@@ -40,8 +40,7 @@ unless ($no_fips) {
     ok(run(app(['openssl', 'fipsinstall',
                 '-out', bldtop_file('providers', 'fipsmodule.cnf'),
                 '-module', bldtop_file('providers', platform->dso('fips')),
-                '-provider_name', 'fips', '-mac_name', 'HMAC',
-                '-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
+                '-provider_name', 'fips',
                 '-section_name', 'fips_sect'])),
        "fipsinstall");