03-test_fipsinstall.t revision 1.3 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 run(test(["fips_version_test", "-config", $provconf, "<3.5.0"]),
257 capture => 1, statusvar => \my $exit);
258 skip "FIPS provider version is too new for Asymmetric RSA corruption test", 1
259 if !$exit;
260 ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
261 '-corrupt_desc', 'RSA_Encrypt',
262 '-corrupt_type', 'KAT_AsymmetricCipher'])),
263 "fipsinstall fails when the asymmetric cipher result is corrupted");
264 }
265
266 # 'local' ensures that this change is only done in this file.
267 local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir());
268
269 ok(replace_parent_line_file('fips.cnf', 'fips_parent.cnf')
270 && run(app(['openssl', 'fipsinstall', '-config', 'fips_parent.cnf'])),
271 "verify fips provider loads from a configuration file");
272
273 ok(replace_parent_line_file('fips_no_module_mac.cnf',
274 'fips_parent_no_module_mac.cnf')
275 && !run(app(['openssl', 'fipsinstall',
276 '-config', 'fips_parent_no_module_mac.cnf'])),
277 "verify load config fail no module mac");
278
279
280 SKIP: {
281 skip "Newer FIPS provider version does not support this feature", 3
282 if !$indicatorpost;
283
284 ok(replace_parent_line_file('fips_no_install_mac.cnf',
285 'fips_parent_no_install_mac.cnf')
286 && !run(app(['openssl', 'fipsinstall',
287 '-config', 'fips_parent_no_install_mac.cnf'])),
288 "verify load config fail no install mac");
289 ok(replace_parent_line_file('fips_bad_indicator.cnf',
290 'fips_parent_bad_indicator.cnf')
291 && !run(app(['openssl', 'fipsinstall',
292 '-config', 'fips_parent_bad_indicator.cnf'])),
293 "verify load config fail bad indicator");
294 ok(replace_parent_line_file('fips_bad_install_mac.cnf',
295 'fips_parent_bad_install_mac.cnf')
296 && !run(app(['openssl', 'fipsinstall',
297 '-config', 'fips_parent_bad_install_mac.cnf'])),
298 "verify load config fail bad install mac");
299 }
300
301 ok(replace_parent_line_file('fips_bad_module_mac.cnf',
302 'fips_parent_bad_module_mac.cnf')
303 && !run(app(['openssl', 'fipsinstall',
304 '-config', 'fips_parent_bad_module_mac.cnf'])),
305 "verify load config fail bad module mac");
306
307
308 my $stconf = "fipsmodule_selftest.cnf";
309
310 ok(run(app(['openssl', 'fipsinstall', '-out', $stconf,
311 '-module', $infile, '-self_test_onload'])),
312 "fipsinstall config saved without self test indicator");
313
314 ok(!run(app(['openssl', 'fipsinstall', '-in', $stconf,
315 '-module', $infile, '-verify'])),
316 "fipsinstall config verify fails without self test indicator");
317
318 ok(run(app(['openssl', 'fipsinstall', '-in', $stconf,
319 '-module', $infile, '-self_test_onload', '-verify'])),
320 "fipsinstall config verify passes when self test indicator is not present");
321