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