Home | History | Annotate | Line # | Download | only in recipes
03-test_fipsinstall.t revision 1.2
      1 #! /usr/bin/env perl
      2 # Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
      3 #
      4 # Licensed under the Apache License 2.0 (the "License").  You may not use
      5 # this file except in compliance with the License.  You can obtain a copy
      6 # in the file LICENSE in the source distribution or at
      7 # https://www.openssl.org/source/license.html
      8 
      9 use strict;
     10 use warnings;
     11 
     12 use File::Spec::Functions qw(:DEFAULT abs2rel);
     13 use File::Copy;
     14 use OpenSSL::Glob;
     15 use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
     16 use OpenSSL::Test::Utils;
     17 
     18 BEGIN {
     19     setup("test_fipsinstall");
     20 }
     21 use lib srctop_dir('Configurations');
     22 use lib bldtop_dir('.');
     23 use platform;
     24 
     25 plan skip_all => "Test only supported in a fips build" if disabled("fips");
     26 
     27 plan tests => 29;
     28 
     29 my $infile = bldtop_file('providers', platform->dso('fips'));
     30 my $fipskey = $ENV{FIPSKEY} // config('FIPSKEY') // '00';
     31 my $provconf = srctop_file("test", "fips-and-base.cnf");
     32 
     33 run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]),
     34           capture => 1, statusvar => \my $indicatorpost);
     35 
     36 # Read in a text $infile and replace the regular expression in $srch with the
     37 # value in $repl and output to a new file $outfile.
     38 sub replace_line_file_internal {
     39 
     40     my ($infile, $srch, $repl, $outfile) = @_;
     41     my $msg;
     42 
     43     open(my $in, "<", $infile) or return 0;
     44     read($in, $msg, 1024);
     45     close $in;
     46 
     47     $msg =~ s/$srch/$repl/;
     48 
     49     open(my $fh, ">", $outfile) or return 0;
     50     print $fh $msg;
     51     close $fh;
     52     return 1;
     53 }
     54 
     55 # Read in the text input file 'fips.cnf'
     56 # and replace a single Key = Value line with a new value in $value.
     57 # OR remove the Key = Value line if the passed in $value is empty.
     58 # and then output a new file $outfile.
     59 # $key is the Key to find
     60 sub replace_line_file {
     61     my ($key, $value, $outfile) = @_;
     62 
     63     my $srch = qr/$key\s*=\s*\S*\n/;
     64     my $rep;
     65     if ($value eq "") {
     66         $rep = "";
     67     } else {
     68        $rep = "$key = $value\n";
     69     }
     70     return replace_line_file_internal('fips.cnf', $srch, $rep, $outfile);
     71 }
     72 
     73 # Read in the text input file 'test/fips.cnf'
     74 # and replace the .cnf file used in
     75 # .include fipsmodule.cnf with a new value in $value.
     76 # and then output a new file $outfile.
     77 # $key is the Key to find
     78 sub replace_parent_line_file {
     79     my ($value, $outfile) = @_;
     80     my $srch = qr/fipsmodule.cnf/;
     81     my $rep = "$value";
     82     return replace_line_file_internal(srctop_file("test", 'fips.cnf'),
     83                                       $srch, $rep, $outfile);
     84 }
     85 
     86 # fail if no module name
     87 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module',
     88              '-provider_name', 'fips',
     89              '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
     90              '-section_name', 'fips_sect'])),
     91    "fipsinstall fail");
     92 
     93 # fail to verify if the configuration file is missing
     94 ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
     95              '-provider_name', 'fips', '-mac_name', 'HMAC',
     96              '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
     97              '-section_name', 'fips_sect', '-verify'])),
     98    "fipsinstall verify fail");
     99 
    100 
    101 # output a fips.cnf file containing mac data
    102 ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
    103             '-provider_name', 'fips', '-mac_name', 'HMAC',
    104             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    105             '-section_name', 'fips_sect'])),
    106    "fipsinstall");
    107 
    108 # verify the fips.cnf file
    109 ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
    110             '-provider_name', 'fips', '-mac_name', 'HMAC',
    111             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    112             '-section_name', 'fips_sect', '-verify'])),
    113    "fipsinstall verify");
    114 
    115 ok(replace_line_file('module-mac', '', 'fips_no_module_mac.cnf')
    116    && !run(app(['openssl', 'fipsinstall',
    117                 '-in', 'fips_no_module_mac.cnf',
    118                 '-module', $infile,
    119                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    120                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    121                 '-section_name', 'fips_sect', '-verify'])),
    122    "fipsinstall verify fail no module mac");
    123 
    124 ok(replace_line_file('install-mac', '', 'fips_no_install_mac.cnf')
    125    && !run(app(['openssl', 'fipsinstall',
    126                 '-in', 'fips_no_install_mac.cnf',
    127                 '-module', $infile,
    128                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    129                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    130                 '-section_name', 'fips_sect', '-verify'])),
    131    "fipsinstall verify fail no install indicator mac");
    132 
    133 ok(replace_line_file('module-mac', '00:00:00:00:00:00',
    134                      'fips_bad_module_mac.cnf')
    135    && !run(app(['openssl', 'fipsinstall',
    136                 '-in', 'fips_bad_module_mac.cnf',
    137                 '-module', $infile,
    138                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    139                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    140                 '-section_name', 'fips_sect', '-verify'])),
    141    "fipsinstall verify fail if invalid module integrity value");
    142 
    143 ok(replace_line_file('install-mac', '00:00:00:00:00:00',
    144                      'fips_bad_install_mac.cnf')
    145    && !run(app(['openssl', 'fipsinstall',
    146                 '-in', 'fips_bad_install_mac.cnf',
    147                 '-module', $infile,
    148                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    149                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    150                 '-section_name', 'fips_sect', '-verify'])),
    151    "fipsinstall verify fail if invalid install indicator integrity value");
    152 
    153 ok(replace_line_file('install-status', 'INCORRECT_STATUS_STRING',
    154                      'fips_bad_indicator.cnf')
    155    && !run(app(['openssl', 'fipsinstall',
    156                 '-in', 'fips_bad_indicator.cnf',
    157                 '-module', $infile,
    158                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    159                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    160                 '-section_name', 'fips_sect', '-verify'])),
    161    "fipsinstall verify fail if invalid install indicator status");
    162 
    163 # fail to verify the fips.cnf file if a different key is used
    164 ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
    165              '-provider_name', 'fips', '-mac_name', 'HMAC',
    166              '-macopt', 'digest:SHA256', '-macopt', "hexkey:01",
    167              '-section_name', 'fips_sect', '-verify'])),
    168    "fipsinstall verify fail bad key");
    169 
    170 # fail to verify the fips.cnf file if a different mac digest is used
    171 ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
    172              '-provider_name', 'fips', '-mac_name', 'HMAC',
    173              '-macopt', 'digest:SHA512', '-macopt', "hexkey:$fipskey",
    174              '-section_name', 'fips_sect', '-verify'])),
    175    "fipsinstall verify fail incorrect digest");
    176 
    177 # corrupt the module hmac
    178 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
    179             '-provider_name', 'fips', '-mac_name', 'HMAC',
    180             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    181             '-section_name', 'fips_sect', '-corrupt_desc', 'HMAC'])),
    182    "fipsinstall fails when the module integrity is corrupted");
    183 
    184 # corrupt the first digest
    185 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
    186             '-provider_name', 'fips', '-mac_name', 'HMAC',
    187             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    188             '-section_name', 'fips_sect', '-corrupt_desc', 'SHA2'])),
    189    "fipsinstall fails when the digest result is corrupted");
    190 
    191 # corrupt another digest
    192 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
    193             '-provider_name', 'fips', '-mac_name', 'HMAC',
    194             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    195             '-section_name', 'fips_sect', '-corrupt_desc', 'SHA3'])),
    196    "fipsinstall fails when the digest result is corrupted");
    197 
    198 # corrupt cipher encrypt test
    199 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
    200             '-provider_name', 'fips', '-mac_name', 'HMAC',
    201             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    202             '-section_name', 'fips_sect', '-corrupt_desc', 'AES_GCM'])),
    203    "fipsinstall fails when the AES_GCM result is corrupted");
    204 
    205 # corrupt cipher decrypt test
    206 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
    207             '-provider_name', 'fips', '-mac_name', 'HMAC',
    208             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    209             '-section_name', 'fips_sect', '-corrupt_desc', 'AES_ECB_Decrypt'])),
    210    "fipsinstall fails when the AES_ECB result is corrupted");
    211 
    212 # corrupt DRBG
    213 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile,
    214             '-provider_name', 'fips', '-mac_name', 'HMAC',
    215             '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    216             '-section_name', 'fips_sect', '-corrupt_desc', 'CTR'])),
    217    "fipsinstall fails when the DRBG CTR result is corrupted");
    218 
    219 # corrupt a KAS test
    220 SKIP: {
    221     skip "Skipping KAS DH corruption test because of no dh in this build", 1
    222         if disabled("dh");
    223 
    224     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
    225                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    226                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    227                 '-section_name', 'fips_sect',
    228                 '-corrupt_desc', 'DH',
    229                 '-corrupt_type', 'KAT_KA'])),
    230        "fipsinstall fails when the kas result is corrupted");
    231 }
    232 
    233 # corrupt a Signature test
    234 SKIP: {
    235     skip "Skipping Signature DSA corruption test because of no dsa in this build", 1
    236         if disabled("dsa");
    237 
    238     run(test(["fips_version_test", "-config", $provconf, "<3.1.0"]),
    239              capture => 1, statusvar => \my $exit);
    240     skip "FIPS provider version is too new for PCT DSA signature test", 1
    241         if !$exit;
    242 
    243     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
    244                 '-provider_name', 'fips', '-mac_name', 'HMAC',
    245                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
    246                 '-section_name', 'fips_sect',
    247                 '-corrupt_desc', 'DSA',
    248                 '-corrupt_type', 'PCT_Signature'])),
    249        "fipsinstall fails when the signature result is corrupted");
    250 }
    251 
    252 # corrupt an Asymmetric cipher test
    253 SKIP: {
    254     skip "Skipping Asymmetric RSA corruption test because of no rsa in this build", 1
    255         if disabled("rsa");
    256     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
    257                 '-corrupt_desc', 'RSA_Encrypt',
    258                 '-corrupt_type', 'KAT_AsymmetricCipher'])),
    259        "fipsinstall fails when the asymmetric cipher result is corrupted");
    260 }
    261 
    262 # 'local' ensures that this change is only done in this file.
    263 local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir());
    264 
    265 ok(replace_parent_line_file('fips.cnf', 'fips_parent.cnf')
    266    && run(app(['openssl', 'fipsinstall', '-config', 'fips_parent.cnf'])),
    267    "verify fips provider loads from a configuration file");
    268 
    269 ok(replace_parent_line_file('fips_no_module_mac.cnf',
    270                             'fips_parent_no_module_mac.cnf')
    271    && !run(app(['openssl', 'fipsinstall',
    272                 '-config', 'fips_parent_no_module_mac.cnf'])),
    273    "verify load config fail no module mac");
    274 
    275 
    276 SKIP: {
    277     skip "Newer FIPS provider version does not support this feature", 3
    278         if !$indicatorpost;
    279 
    280     ok(replace_parent_line_file('fips_no_install_mac.cnf',
    281                                 'fips_parent_no_install_mac.cnf')
    282        && !run(app(['openssl', 'fipsinstall',
    283                     '-config', 'fips_parent_no_install_mac.cnf'])),
    284        "verify load config fail no install mac");
    285     ok(replace_parent_line_file('fips_bad_indicator.cnf',
    286                                 'fips_parent_bad_indicator.cnf')
    287        && !run(app(['openssl', 'fipsinstall',
    288                     '-config', 'fips_parent_bad_indicator.cnf'])),
    289        "verify load config fail bad indicator");
    290     ok(replace_parent_line_file('fips_bad_install_mac.cnf',
    291                                 'fips_parent_bad_install_mac.cnf')
    292        && !run(app(['openssl', 'fipsinstall',
    293                     '-config', 'fips_parent_bad_install_mac.cnf'])),
    294        "verify load config fail bad install mac");
    295 }
    296 
    297 ok(replace_parent_line_file('fips_bad_module_mac.cnf',
    298                             'fips_parent_bad_module_mac.cnf')
    299    && !run(app(['openssl', 'fipsinstall',
    300                 '-config', 'fips_parent_bad_module_mac.cnf'])),
    301    "verify load config fail bad module mac");
    302 
    303 
    304 my $stconf = "fipsmodule_selftest.cnf";
    305 
    306 ok(run(app(['openssl', 'fipsinstall', '-out', $stconf,
    307             '-module', $infile, '-self_test_onload'])),
    308        "fipsinstall config saved without self test indicator");
    309 
    310 ok(!run(app(['openssl', 'fipsinstall', '-in', $stconf,
    311              '-module', $infile, '-verify'])),
    312         "fipsinstall config verify fails without self test indicator");
    313 
    314 ok(run(app(['openssl', 'fipsinstall', '-in', $stconf,
    315             '-module', $infile, '-self_test_onload', '-verify'])),
    316        "fipsinstall config verify passes when self test indicator is not present");
    317