xref: /openssl/test/recipes/20-test_cli_fips.t (revision 7ed6de99)
1#! /usr/bin/env perl
2# Copyright 2020-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;
13use File::Spec::Functions qw/curdir abs2rel/;
14use File::Copy;
15use OpenSSL::Glob;
16use OpenSSL::Test qw/:DEFAULT srctop_dir bldtop_dir bldtop_file srctop_file data_file/;
17use OpenSSL::Test::Utils;
18
19BEGIN {
20    setup("test_cli_fips");
21}
22use lib srctop_dir('Configurations');
23use lib bldtop_dir('.');
24use platform;
25
26my $no_check = disabled("fips") || disabled('fips-securitychecks');
27plan skip_all => "Test only supported in a fips build with security checks"
28    if $no_check;
29plan tests => 12;
30
31my $fipsmodule = bldtop_file('providers', platform->dso('fips'));
32my $fipsconf = srctop_file("test", "fips-and-base.cnf");
33my $defaultconf = srctop_file("test", "default.cnf");
34my $tbs_data = $fipsmodule;
35my $bogus_data = $fipsconf;
36
37$ENV{OPENSSL_CONF} = $fipsconf;
38
39run(test(["fips_version_test", "-config", $fipsconf, "<3.4.0"]),
40          capture => 1, statusvar => \my $dsasignpass);
41
42ok(run(app(['openssl', 'list', '-public-key-methods', '-verbose'])),
43   "provider listing of public key methods");
44ok(run(app(['openssl', 'list', '-public-key-algorithms', '-verbose'])),
45   "provider listing of public key algorithms");
46ok(run(app(['openssl', 'list', '-key-managers', '-verbose'])),
47   "provider listing of keymanagers");
48ok(run(app(['openssl', 'list', '-key-exchange-algorithms', '-verbose'])),
49   "provider listing of key exchange algorithms");
50ok(run(app(['openssl', 'list', '-kem-algorithms', '-verbose'])),
51   "provider listing of key encapsulation algorithms");
52ok(run(app(['openssl', 'list', '-signature-algorithms', '-verbose'])),
53   "provider listing of signature algorithms");
54ok(run(app(['openssl', 'list', '-tls-signature-algorithms', '-verbose'])),
55   "provider listing of TLS signature algorithms");
56ok(run(app(['openssl', 'list', '-asymcipher-algorithms', '-verbose'])),
57   "provider listing of encryption algorithms");
58ok(run(app(['openssl', 'list', '-key-managers', '-verbose', '-select', 'DSA' ])),
59   "provider listing of one item in the keymanager");
60
61sub pubfrompriv {
62    my $prefix = shift;
63    my $key = shift;
64    my $pub_key = shift;
65    my $type = shift;
66
67    ok(run(app(['openssl', 'pkey',
68                '-in', $key,
69                '-pubout',
70                '-out', $pub_key])),
71        $prefix.': '."Create the public key with $type parameters");
72
73}
74
75my $tsignverify_count = 9;
76sub tsignverify {
77    my $prefix = shift;
78    my $fips_key = shift;
79    my $fips_pub_key = shift;
80    my $nonfips_key = shift;
81    my $nonfips_pub_key = shift;
82    my $fips_sigfile = $prefix.'.fips.sig';
83    my $nonfips_sigfile = $prefix.'.nonfips.sig';
84    my $sigfile = '';
85    my $testtext = '';
86
87    $ENV{OPENSSL_CONF} = $fipsconf;
88
89    $sigfile = $fips_sigfile;
90    $testtext = $prefix.': '.
91        'Sign something with a FIPS key';
92    ok(run(app(['openssl', 'dgst', '-sha256',
93                '-sign', $fips_key,
94                '-out', $sigfile,
95                $tbs_data])),
96       $testtext);
97
98    $testtext = $prefix.': '.
99        'Verify something with a FIPS key';
100    ok(run(app(['openssl', 'dgst', '-sha256',
101                '-verify', $fips_pub_key,
102                '-signature', $sigfile,
103                $tbs_data])),
104       $testtext);
105
106    $testtext = $prefix.': '.
107        'Verify a valid signature against the wrong data with a FIPS key'.
108        ' (should fail)';
109    ok(!run(app(['openssl', 'dgst', '-sha256',
110                 '-verify', $fips_pub_key,
111                 '-signature', $sigfile,
112                 $bogus_data])),
113       $testtext);
114
115    $ENV{OPENSSL_CONF} = $defaultconf;
116
117    SKIP : {
118        skip "FIPS failure testing", 6
119            if ($nonfips_key eq '');
120
121        $sigfile = $nonfips_sigfile;
122        $testtext = $prefix.': '.
123            'Sign something with a non-FIPS key'.
124            ' with the default provider';
125        ok(run(app(['openssl', 'dgst', '-sha256',
126                    '-sign', $nonfips_key,
127                    '-out', $sigfile,
128                    $tbs_data])),
129           $testtext);
130
131        $testtext = $prefix.': '.
132            'Verify something with a non-FIPS key'.
133            ' with the default provider';
134        ok(run(app(['openssl', 'dgst', '-sha256',
135                    '-verify', $nonfips_pub_key,
136                    '-signature', $sigfile,
137                    $tbs_data])),
138           $testtext);
139
140        $ENV{OPENSSL_CONF} = $fipsconf;
141
142        $testtext = $prefix.': '.
143            'Sign something with a non-FIPS key'.
144            ' (should fail)';
145        ok(!run(app(['openssl', 'dgst', '-sha256',
146                     '-sign', $nonfips_key,
147                     '-out', $prefix.'.nonfips.fail.sig',
148                     $tbs_data])),
149           $testtext);
150
151        $testtext = $prefix.': '.
152            'Verify something with a non-FIPS key'.
153            ' (should fail)';
154        ok(!run(app(['openssl', 'dgst', '-sha256',
155                     '-verify', $nonfips_pub_key,
156                     '-signature', $sigfile,
157                     $tbs_data])),
158           $testtext);
159
160        $testtext = $prefix.': '.
161            'Verify something with a non-FIPS key'.
162		    ' in FIPS mode but with a non-FIPS property query';
163        ok(run(app(['openssl', 'dgst',
164				    '-provider', 'default',
165				    '-propquery', '?fips!=yes',
166				    '-sha256',
167                    '-verify', $nonfips_pub_key,
168                    '-signature', $sigfile,
169                    $tbs_data])),
170           $testtext);
171
172        $testtext = $prefix.': '.
173            'Verify a valid signature against the wrong data with a non-FIPS key'.
174            ' (should fail)';
175        ok(!run(app(['openssl', 'dgst', '-sha256',
176                     '-verify', $nonfips_pub_key,
177                     '-signature', $sigfile,
178                     $bogus_data])),
179           $testtext);
180   }
181}
182
183SKIP : {
184    skip "FIPS EC tests because of no ec in this build", 1
185        if disabled("ec");
186
187    subtest EC => sub {
188        my $testtext_prefix = 'EC';
189        my $a_fips_curve = 'prime256v1';
190        my $fips_key = $testtext_prefix.'.fips.priv.pem';
191        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
192        my $a_nonfips_curve = 'brainpoolP256r1';
193        my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
194        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
195        my $testtext = '';
196        my $curvename = '';
197
198        plan tests => 5 + $tsignverify_count;
199
200        $ENV{OPENSSL_CONF} = $defaultconf;
201        $curvename = $a_nonfips_curve;
202        $testtext = $testtext_prefix.': '.
203            'Generate a key with a non-FIPS algorithm with the default provider';
204        ok(run(app(['openssl', 'genpkey', '-algorithm', 'EC',
205                    '-pkeyopt', 'ec_paramgen_curve:'.$curvename,
206                    '-out', $nonfips_key])),
207           $testtext);
208
209        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
210
211        $ENV{OPENSSL_CONF} = $fipsconf;
212
213        $curvename = $a_fips_curve;
214        $testtext = $testtext_prefix.': '.
215            'Generate a key with a FIPS algorithm';
216        ok(run(app(['openssl', 'genpkey', '-algorithm', 'EC',
217                    '-pkeyopt', 'ec_paramgen_curve:'.$curvename,
218                    '-out', $fips_key])),
219           $testtext);
220
221        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
222
223        $curvename = $a_nonfips_curve;
224        $testtext = $testtext_prefix.': '.
225            'Generate a key with a non-FIPS algorithm'.
226            ' (should fail)';
227        ok(!run(app(['openssl', 'genpkey', '-algorithm', 'EC',
228                     '-pkeyopt', 'ec_paramgen_curve:'.$curvename,
229                     '-out', $testtext_prefix.'.'.$curvename.'.priv.pem'])),
230           $testtext);
231
232        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, $nonfips_key,
233                    $nonfips_pub_key);
234    };
235}
236
237SKIP: {
238    skip "FIPS RSA tests because of no rsa in this build", 1
239        if disabled("rsa");
240
241    subtest RSA => sub {
242        my $testtext_prefix = 'RSA';
243        my $fips_key = $testtext_prefix.'.fips.priv.pem';
244        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
245        my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
246        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
247        my $testtext = '';
248
249        plan tests => 5 + $tsignverify_count;
250
251        $ENV{OPENSSL_CONF} = $defaultconf;
252        $testtext = $testtext_prefix.': '.
253            'Generate a key with a non-FIPS algorithm with the default provider';
254        ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA',
255                    '-pkeyopt', 'rsa_keygen_bits:512',
256                    '-out', $nonfips_key])),
257           $testtext);
258
259        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
260
261        $ENV{OPENSSL_CONF} = $fipsconf;
262
263        $testtext = $testtext_prefix.': '.
264            'Generate a key with a FIPS algorithm';
265        ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA',
266                    '-pkeyopt', 'rsa_keygen_bits:2048',
267                    '-out', $fips_key])),
268           $testtext);
269
270        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
271
272        $testtext = $testtext_prefix.': '.
273            'Generate a key with a non-FIPS algorithm'.
274            ' (should fail)';
275        ok(!run(app(['openssl', 'genpkey', '-algorithm', 'RSA',
276                    '-pkeyopt', 'rsa_keygen_bits:512',
277                     '-out', $testtext_prefix.'.fail.priv.pem'])),
278           $testtext);
279
280        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, $nonfips_key,
281                    $nonfips_pub_key);
282    };
283}
284
285SKIP : {
286    skip "FIPS DSA tests because of no dsa in this build", 1
287        if disabled("dsa") || $dsasignpass == '0';
288
289    subtest DSA => sub {
290        my $testtext_prefix = 'DSA';
291        my $fips_key = $testtext_prefix.'.fips.priv.pem';
292        my $fips_pub_key = $testtext_prefix.'.fips.pub.pem';
293        my $nonfips_key = $testtext_prefix.'.nonfips.priv.pem';
294        my $nonfips_pub_key = $testtext_prefix.'.nonfips.pub.pem';
295        my $testtext = '';
296        my $fips_param = $testtext_prefix.'.fips.param.pem';
297        my $nonfips_param = $testtext_prefix.'.nonfips.param.pem';
298        my $shortnonfips_param = $testtext_prefix.'.shortnonfips.param.pem';
299
300        plan tests => 13 + $tsignverify_count;
301
302        $ENV{OPENSSL_CONF} = $defaultconf;
303
304        $testtext = $testtext_prefix.': '.
305            'Generate non-FIPS params with the default provider';
306        ok(run(app(['openssl', 'genpkey', '-genparam',
307                    '-algorithm', 'DSA',
308                    '-pkeyopt', 'type:fips186_2',
309                    '-pkeyopt', 'dsa_paramgen_bits:512',
310                    '-out', $nonfips_param])),
311           $testtext);
312
313        $ENV{OPENSSL_CONF} = $fipsconf;
314
315        $testtext = $testtext_prefix.': '.
316            'Generate FIPS params';
317        ok(run(app(['openssl', 'genpkey', '-genparam',
318                    '-algorithm', 'DSA',
319                    '-pkeyopt', 'dsa_paramgen_bits:2048',
320                    '-out', $fips_param])),
321           $testtext);
322
323        $testtext = $testtext_prefix.': '.
324            'Generate non-FIPS params'.
325            ' (should fail)';
326        ok(!run(app(['openssl', 'genpkey', '-genparam',
327                     '-algorithm', 'DSA',
328                    '-pkeyopt', 'dsa_paramgen_bits:512',
329                     '-out', $testtext_prefix.'.fail.param.pem'])),
330           $testtext);
331
332        $testtext = $testtext_prefix.': '.
333            'Generate non-FIPS params using non-FIPS property query'.
334            ' (dsaparam)';
335        ok(run(app(['openssl', 'dsaparam', '-provider', 'default',
336                    '-propquery', '?fips!=yes',
337                    '-out', $shortnonfips_param, '1024'])),
338            $testtext);
339
340        $testtext = $testtext_prefix.': '.
341            'Generate non-FIPS params using non-FIPS property query'.
342            ' (genpkey)';
343        ok(run(app(['openssl', 'genpkey', '-provider', 'default',
344                    '-propquery', '?fips!=yes',
345                    '-genparam', '-algorithm', 'DSA',
346                    '-pkeyopt', 'dsa_paramgen_bits:512'])),
347            $testtext);
348
349        $ENV{OPENSSL_CONF} = $defaultconf;
350
351        $testtext = $testtext_prefix.': '.
352            'Generate a key with non-FIPS params with the default provider';
353        ok(run(app(['openssl', 'genpkey',
354                    '-paramfile', $nonfips_param,
355                    '-pkeyopt', 'type:fips186_2',
356                    '-out', $nonfips_key])),
357           $testtext);
358
359        pubfrompriv($testtext_prefix, $nonfips_key, $nonfips_pub_key, "non-FIPS");
360
361        $ENV{OPENSSL_CONF} = $fipsconf;
362
363        $testtext = $testtext_prefix.': '.
364            'Generate a key with FIPS parameters';
365        ok(run(app(['openssl', 'genpkey',
366                    '-paramfile', $fips_param,
367                    '-pkeyopt', 'type:fips186_4',
368                    '-out', $fips_key])),
369           $testtext);
370
371        pubfrompriv($testtext_prefix, $fips_key, $fips_pub_key, "FIPS");
372
373        $testtext = $testtext_prefix.': '.
374            'Generate a key with non-FIPS parameters'.
375            ' (should fail)';
376        ok(!run(app(['openssl', 'genpkey',
377                     '-paramfile', $nonfips_param,
378                     '-pkeyopt', 'type:fips186_2',
379                     '-out', $testtext_prefix.'.fail.priv.pem'])),
380           $testtext);
381
382        $testtext = $testtext_prefix.': '.
383            'Generate a key with non-FIPS parameters using non-FIPS property'.
384            ' query (dsaparam)';
385        ok(run(app(['openssl', 'dsaparam', '-provider', 'default',
386                    '-propquery', '?fips!=yes',
387                    '-noout', '-genkey', '1024'])),
388            $testtext);
389
390        $testtext = $testtext_prefix.': '.
391            'Generate a key with non-FIPS parameters using non-FIPS property'.
392            ' query (gendsa)';
393        ok(run(app(['openssl', 'gendsa', '-provider', 'default',
394                    '-propquery', '?fips!=yes',
395                    $shortnonfips_param])),
396            $testtext);
397
398        $testtext = $testtext_prefix.': '.
399            'Generate a key with non-FIPS parameters using non-FIPS property'.
400            ' query (genpkey)';
401        ok(run(app(['openssl', 'genpkey', '-provider', 'default',
402                    '-propquery', '?fips!=yes',
403                    '-paramfile', $nonfips_param,
404                    '-pkeyopt', 'type:fips186_2',
405                    '-out', $testtext_prefix.'.fail.priv.pem'])),
406            $testtext);
407
408        tsignverify($testtext_prefix, $fips_key, $fips_pub_key, '', '');
409    };
410}
411