1#! /usr/bin/env perl 2# Copyright 2019-2021 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} // '00'; 31 32# Read in a text $infile and replace the regular expression in $srch with the 33# value in $repl and output to a new file $outfile. 34sub replace_line_file_internal { 35 36 my ($infile, $srch, $repl, $outfile) = @_; 37 my $msg; 38 39 open(my $in, "<", $infile) or return 0; 40 read($in, $msg, 1024); 41 close $in; 42 43 $msg =~ s/$srch/$repl/; 44 45 open(my $fh, ">", $outfile) or return 0; 46 print $fh $msg; 47 close $fh; 48 return 1; 49} 50 51# Read in the text input file 'fips.cnf' 52# and replace a single Key = Value line with a new value in $value. 53# OR remove the Key = Value line if the passed in $value is empty. 54# and then output a new file $outfile. 55# $key is the Key to find 56sub replace_line_file { 57 my ($key, $value, $outfile) = @_; 58 59 my $srch = qr/$key\s*=\s*\S*\n/; 60 my $rep; 61 if ($value eq "") { 62 $rep = ""; 63 } else { 64 $rep = "$key = $value\n"; 65 } 66 return replace_line_file_internal('fips.cnf', $srch, $rep, $outfile); 67} 68 69# Read in the text input file 'test/fips.cnf' 70# and replace the .cnf file used in 71# .include fipsmodule.cnf with a new value in $value. 72# and then output a new file $outfile. 73# $key is the Key to find 74sub replace_parent_line_file { 75 my ($value, $outfile) = @_; 76 my $srch = qr/fipsmodule.cnf/; 77 my $rep = "$value"; 78 return replace_line_file_internal(srctop_file("test", 'fips.cnf'), 79 $srch, $rep, $outfile); 80} 81 82# fail if no module name 83ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', 84 '-provider_name', 'fips', 85 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 86 '-section_name', 'fips_sect'])), 87 "fipsinstall fail"); 88 89# fail to verify if the configuration file is missing 90ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile, 91 '-provider_name', 'fips', '-mac_name', 'HMAC', 92 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 93 '-section_name', 'fips_sect', '-verify'])), 94 "fipsinstall verify fail"); 95 96 97# output a fips.cnf file containing mac data 98ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, 99 '-provider_name', 'fips', '-mac_name', 'HMAC', 100 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 101 '-section_name', 'fips_sect'])), 102 "fipsinstall"); 103 104# verify the fips.cnf file 105ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile, 106 '-provider_name', 'fips', '-mac_name', 'HMAC', 107 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 108 '-section_name', 'fips_sect', '-verify'])), 109 "fipsinstall verify"); 110 111ok(replace_line_file('module-mac', '', 'fips_no_module_mac.cnf') 112 && !run(app(['openssl', 'fipsinstall', 113 '-in', 'fips_no_module_mac.cnf', 114 '-module', $infile, 115 '-provider_name', 'fips', '-mac_name', 'HMAC', 116 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 117 '-section_name', 'fips_sect', '-verify'])), 118 "fipsinstall verify fail no module mac"); 119 120ok(replace_line_file('install-mac', '', 'fips_no_install_mac.cnf') 121 && !run(app(['openssl', 'fipsinstall', 122 '-in', 'fips_no_install_mac.cnf', 123 '-module', $infile, 124 '-provider_name', 'fips', '-mac_name', 'HMAC', 125 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 126 '-section_name', 'fips_sect', '-verify'])), 127 "fipsinstall verify fail no install indicator mac"); 128 129ok(replace_line_file('module-mac', '00:00:00:00:00:00', 130 'fips_bad_module_mac.cnf') 131 && !run(app(['openssl', 'fipsinstall', 132 '-in', 'fips_bad_module_mac.cnf', 133 '-module', $infile, 134 '-provider_name', 'fips', '-mac_name', 'HMAC', 135 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 136 '-section_name', 'fips_sect', '-verify'])), 137 "fipsinstall verify fail if invalid module integrity value"); 138 139ok(replace_line_file('install-mac', '00:00:00:00:00:00', 140 'fips_bad_install_mac.cnf') 141 && !run(app(['openssl', 'fipsinstall', 142 '-in', 'fips_bad_install_mac.cnf', 143 '-module', $infile, 144 '-provider_name', 'fips', '-mac_name', 'HMAC', 145 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 146 '-section_name', 'fips_sect', '-verify'])), 147 "fipsinstall verify fail if invalid install indicator integrity value"); 148 149ok(replace_line_file('install-status', 'INCORRECT_STATUS_STRING', 150 'fips_bad_indicator.cnf') 151 && !run(app(['openssl', 'fipsinstall', 152 '-in', 'fips_bad_indicator.cnf', 153 '-module', $infile, 154 '-provider_name', 'fips', '-mac_name', 'HMAC', 155 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 156 '-section_name', 'fips_sect', '-verify'])), 157 "fipsinstall verify fail if invalid install indicator status"); 158 159# fail to verify the fips.cnf file if a different key is used 160ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile, 161 '-provider_name', 'fips', '-mac_name', 'HMAC', 162 '-macopt', 'digest:SHA256', '-macopt', "hexkey:01", 163 '-section_name', 'fips_sect', '-verify'])), 164 "fipsinstall verify fail bad key"); 165 166# fail to verify the fips.cnf file if a different mac digest is used 167ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile, 168 '-provider_name', 'fips', '-mac_name', 'HMAC', 169 '-macopt', 'digest:SHA512', '-macopt', "hexkey:$fipskey", 170 '-section_name', 'fips_sect', '-verify'])), 171 "fipsinstall verify fail incorrect digest"); 172 173# corrupt the module hmac 174ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, 175 '-provider_name', 'fips', '-mac_name', 'HMAC', 176 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 177 '-section_name', 'fips_sect', '-corrupt_desc', 'HMAC'])), 178 "fipsinstall fails when the module integrity is corrupted"); 179 180# corrupt the first digest 181ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile, 182 '-provider_name', 'fips', '-mac_name', 'HMAC', 183 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 184 '-section_name', 'fips_sect', '-corrupt_desc', 'SHA1'])), 185 "fipsinstall fails when the digest result is corrupted"); 186 187# corrupt another digest 188ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile, 189 '-provider_name', 'fips', '-mac_name', 'HMAC', 190 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 191 '-section_name', 'fips_sect', '-corrupt_desc', 'SHA3'])), 192 "fipsinstall fails when the digest result is corrupted"); 193 194# corrupt cipher encrypt test 195ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile, 196 '-provider_name', 'fips', '-mac_name', 'HMAC', 197 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 198 '-section_name', 'fips_sect', '-corrupt_desc', 'AES_GCM'])), 199 "fipsinstall fails when the AES_GCM result is corrupted"); 200 201# corrupt cipher decrypt test 202ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile, 203 '-provider_name', 'fips', '-mac_name', 'HMAC', 204 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 205 '-section_name', 'fips_sect', '-corrupt_desc', 'AES_ECB_Decrypt'])), 206 "fipsinstall fails when the AES_ECB result is corrupted"); 207 208# corrupt DRBG 209ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips_fail.cnf', '-module', $infile, 210 '-provider_name', 'fips', '-mac_name', 'HMAC', 211 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 212 '-section_name', 'fips_sect', '-corrupt_desc', 'CTR'])), 213 "fipsinstall fails when the DRBG CTR result is corrupted"); 214 215# corrupt a KAS test 216SKIP: { 217 skip "Skipping KAS DH corruption test because of no dh in this build", 1 218 if disabled("dh"); 219 220 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, 221 '-provider_name', 'fips', '-mac_name', 'HMAC', 222 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 223 '-section_name', 'fips_sect', 224 '-corrupt_desc', 'DH', 225 '-corrupt_type', 'KAT_KA'])), 226 "fipsinstall fails when the kas result is corrupted"); 227} 228 229# corrupt a Signature test 230SKIP: { 231 skip "Skipping Signature DSA corruption test because of no dsa in this build", 1 232 if disabled("dsa"); 233 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, 234 '-provider_name', 'fips', '-mac_name', 'HMAC', 235 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey", 236 '-section_name', 'fips_sect', 237 '-corrupt_desc', 'DSA', 238 '-corrupt_type', 'PCT_Signature'])), 239 "fipsinstall fails when the signature result is corrupted"); 240} 241 242# corrupt an Asymmetric cipher test 243SKIP: { 244 skip "Skipping Asymmetric RSA corruption test because of no rsa in this build", 1 245 if disabled("rsa"); 246 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, 247 '-corrupt_desc', 'RSA_Encrypt', 248 '-corrupt_type', 'KAT_AsymmetricCipher'])), 249 "fipsinstall fails when the asymmetric cipher result is corrupted"); 250} 251 252# 'local' ensures that this change is only done in this file. 253local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir()); 254 255ok(replace_parent_line_file('fips.cnf', 'fips_parent.cnf') 256 && run(app(['openssl', 'fipsinstall', '-config', 'fips_parent.cnf'])), 257 "verify fips provider loads from a configuration file"); 258 259ok(replace_parent_line_file('fips_no_module_mac.cnf', 260 'fips_parent_no_module_mac.cnf') 261 && !run(app(['openssl', 'fipsinstall', 262 '-config', 'fips_parent_no_module_mac.cnf'])), 263 "verify load config fail no module mac"); 264 265ok(replace_parent_line_file('fips_no_install_mac.cnf', 266 'fips_parent_no_install_mac.cnf') 267 && !run(app(['openssl', 'fipsinstall', 268 '-config', 'fips_parent_no_install_mac.cnf'])), 269 "verify load config fail no install mac"); 270 271ok(replace_parent_line_file('fips_bad_indicator.cnf', 272 'fips_parent_bad_indicator.cnf') 273 && !run(app(['openssl', 'fipsinstall', 274 '-config', 'fips_parent_bad_indicator.cnf'])), 275 "verify load config fail bad indicator"); 276 277 278ok(replace_parent_line_file('fips_bad_install_mac.cnf', 279 'fips_parent_bad_install_mac.cnf') 280 && !run(app(['openssl', 'fipsinstall', 281 '-config', 'fips_parent_bad_install_mac.cnf'])), 282 "verify load config fail bad install mac"); 283 284ok(replace_parent_line_file('fips_bad_module_mac.cnf', 285 'fips_parent_bad_module_mac.cnf') 286 && !run(app(['openssl', 'fipsinstall', 287 '-config', 'fips_parent_bad_module_mac.cnf'])), 288 "verify load config fail bad module mac"); 289 290 291my $stconf = "fipsmodule_selftest.cnf"; 292 293ok(run(app(['openssl', 'fipsinstall', '-out', $stconf, 294 '-module', $infile, '-self_test_onload'])), 295 "fipsinstall config saved without self test indicator"); 296 297ok(!run(app(['openssl', 'fipsinstall', '-in', $stconf, 298 '-module', $infile, '-verify'])), 299 "fipsinstall config verify fails without self test indicator"); 300 301ok(run(app(['openssl', 'fipsinstall', '-in', $stconf, 302 '-module', $infile, '-self_test_onload', '-verify'])), 303 "fipsinstall config verify passes when self test indicator is not present"); 304