xref: /freebsd/crypto/openssl/test/recipes/03-test_fipsinstall.t (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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