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 9use strict; 10use warnings; 11 12use File::Spec::Functions qw(:DEFAULT abs2rel); 13use File::Copy; 14use OpenSSL::Glob; 15use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/; 16use OpenSSL::Test::Utils; 17 18BEGIN { 19 setup("test_fipsinstall"); 20} 21use lib srctop_dir('Configurations'); 22use lib bldtop_dir('.'); 23use platform; 24 25plan skip_all => "Test only supported in a fips build" if disabled("fips"); 26 27plan tests => 29; 28 29my $infile = bldtop_file('providers', platform->dso('fips')); 30my $fipskey = $ENV{FIPSKEY} // config('FIPSKEY') // '00'; 31my $provconf = srctop_file("test", "fips-and-base.cnf"); 32 33run(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. 38sub 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 60sub 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 78sub 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 87ok(!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 94ok(!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 102ok(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 109ok(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 115ok(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 124ok(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 133ok(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 143ok(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 153ok(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 164ok(!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 171ok(!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 178ok(!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 185ok(!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 192ok(!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 199ok(!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 206ok(!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 213ok(!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 220SKIP: { 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 234SKIP: { 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 253SKIP: { 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. 263local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir()); 264 265ok(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 269ok(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 276SKIP: { 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 297ok(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 304my $stconf = "fipsmodule_selftest.cnf"; 305 306ok(run(app(['openssl', 'fipsinstall', '-out', $stconf, 307 '-module', $infile, '-self_test_onload'])), 308 "fipsinstall config saved without self test indicator"); 309 310ok(!run(app(['openssl', 'fipsinstall', '-in', $stconf, 311 '-module', $infile, '-verify'])), 312 "fipsinstall config verify fails without self test indicator"); 313 314ok(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