Remove PSS salt length detection hack from fipslagtest.pl by allowing a regexp
[openssl.git] / fips / fipsalgtest.pl
1 #!/usr/bin/perl -w
2 # Perl utility to run or verify FIPS 140-2 CMVP algorithm tests based on the
3 # pathnames of input algorithm test files actually present (the unqualified
4 # file names are consistent but the pathnames are not).
5 #
6
7 # FIPS test definitions
8 # List of all the unqualified file names we expect and command lines to run
9
10 # DSA tests
11 my @fips_dsa_test_list = (
12
13     "DSA",
14
15     [ "PQGGen",  "fips_dssvs pqg" ],
16     [ "KeyPair", "fips_dssvs keypair" ],
17     [ "SigGen",  "fips_dssvs siggen" ],
18     [ "SigVer",  "fips_dssvs sigver" ]
19
20 );
21
22 my @fips_dsa_pqgver_test_list = (
23
24     [ "PQGVer",  "fips_dssvs pqgver" ]
25
26 );
27
28 # RSA tests
29
30 my @fips_rsa_test_list = (
31
32     "RSA",
33
34     [ "SigGen15",  "fips_rsastest" ],
35     [ "SigVer15",  "fips_rsavtest" ],
36     [ "SigVerRSA", "fips_rsavtest -x931" ],
37     [ "KeyGenRSA", "fips_rsagtest" ],
38     [ "SigGenRSA", "fips_rsastest -x931" ]
39
40 );
41
42 # Special cases for PSS. The filename itself is
43 # not sufficient to determine the test. Addditionally we
44 # need to examine the file contents to determine the salt length
45 # In these cases the test filename has (saltlen) appended.
46
47 # RSA PSS salt length 0 tests
48
49 my @fips_rsa_pss0_test_list = (
50
51     [ "SigGenPSS(0)", "fips_rsastest -saltlen 0",
52                                         '^\s*#\s*salt\s+len:\s+0\s*$' ],
53     [ "SigVerPSS(0)", "fips_rsavtest -saltlen 0",
54                                         '^\s*#\s*salt\s+len:\s+0\s*$' ],
55
56 );
57
58 # RSA PSS salt length 62 tests
59
60 my @fips_rsa_pss62_test_list = (
61     [ "SigGenPSS(62)", "fips_rsastest -saltlen 62",
62                                         '^\s*#\s*salt\s+len:\s+62\s*$' ],
63     [ "SigVerPSS(62)", "fips_rsavtest -saltlen 62",
64                                         '^\s*#\s*salt\s+len:\s+62\s*$' ],
65 );
66
67 # SHA tests
68
69 my @fips_sha_test_list = (
70
71     "SHA",
72
73     [ "SHA1LongMsg",    "fips_shatest" ],
74     [ "SHA1Monte",      "fips_shatest" ],
75     [ "SHA1ShortMsg",   "fips_shatest" ],
76     [ "SHA224LongMsg",  "fips_shatest" ],
77     [ "SHA224Monte",    "fips_shatest" ],
78     [ "SHA224ShortMsg", "fips_shatest" ],
79     [ "SHA256LongMsg",  "fips_shatest" ],
80     [ "SHA256Monte",    "fips_shatest" ],
81     [ "SHA256ShortMsg", "fips_shatest" ],
82     [ "SHA384LongMsg",  "fips_shatest" ],
83     [ "SHA384Monte",    "fips_shatest" ],
84     [ "SHA384ShortMsg", "fips_shatest" ],
85     [ "SHA512LongMsg",  "fips_shatest" ],
86     [ "SHA512Monte",    "fips_shatest" ],
87     [ "SHA512ShortMsg", "fips_shatest" ]
88
89 );
90
91 # HMAC
92
93 my @fips_hmac_test_list = (
94
95     "HMAC",
96
97     [ "HMAC", "fips_hmactest" ]
98
99 );
100
101 # CMAC
102
103 my @fips_cmac_test_list = (
104
105     "CMAC",
106
107     [ "CMACGenAES128", "fips_cmactest -a aes128 -g" ],
108     [ "CMACVerAES128", "fips_cmactest -a aes128 -v" ],
109     [ "CMACGenAES192", "fips_cmactest -a aes192 -g" ],
110     [ "CMACVerAES192", "fips_cmactest -a aes192 -v" ],
111     [ "CMACGenAES256", "fips_cmactest -a aes256 -g" ],
112     [ "CMACVerAES256", "fips_cmactest -a aes256 -v" ],
113     [ "CMACGenTDES3", "fips_cmactest -a tdes3 -g" ],
114     [ "CMACVerTDES3", "fips_cmactest -a tdes3 -v" ],
115
116 );
117
118 # RAND tests, AES version
119
120 my @fips_rand_aes_test_list = (
121
122     "RAND (AES)",
123
124     [ "ANSI931_AES128MCT", "fips_rngvs mct" ],
125     [ "ANSI931_AES192MCT", "fips_rngvs mct" ],
126     [ "ANSI931_AES256MCT", "fips_rngvs mct" ],
127     [ "ANSI931_AES128VST", "fips_rngvs vst" ],
128     [ "ANSI931_AES192VST", "fips_rngvs vst" ],
129     [ "ANSI931_AES256VST", "fips_rngvs vst" ]
130
131 );
132
133 # RAND tests, DES2 version
134
135 my @fips_rand_des2_test_list = (
136
137     "RAND (DES2)",
138
139     [ "ANSI931_TDES2MCT", "fips_rngvs mct" ],
140     [ "ANSI931_TDES2VST", "fips_rngvs vst" ]
141
142 );
143
144 # AES tests
145
146 my @fips_aes_test_list = (
147
148     "AES",
149
150     [ "CBCGFSbox128",     "fips_aesavs -f" ],
151     [ "CBCGFSbox192",     "fips_aesavs -f" ],
152     [ "CBCGFSbox256",     "fips_aesavs -f" ],
153     [ "CBCKeySbox128",    "fips_aesavs -f" ],
154     [ "CBCKeySbox192",    "fips_aesavs -f" ],
155     [ "CBCKeySbox256",    "fips_aesavs -f" ],
156     [ "CBCMCT128",        "fips_aesavs -f" ],
157     [ "CBCMCT192",        "fips_aesavs -f" ],
158     [ "CBCMCT256",        "fips_aesavs -f" ],
159     [ "CBCMMT128",        "fips_aesavs -f" ],
160     [ "CBCMMT192",        "fips_aesavs -f" ],
161     [ "CBCMMT256",        "fips_aesavs -f" ],
162     [ "CBCVarKey128",     "fips_aesavs -f" ],
163     [ "CBCVarKey192",     "fips_aesavs -f" ],
164     [ "CBCVarKey256",     "fips_aesavs -f" ],
165     [ "CBCVarTxt128",     "fips_aesavs -f" ],
166     [ "CBCVarTxt192",     "fips_aesavs -f" ],
167     [ "CBCVarTxt256",     "fips_aesavs -f" ],
168     [ "CFB128GFSbox128",  "fips_aesavs -f" ],
169     [ "CFB128GFSbox192",  "fips_aesavs -f" ],
170     [ "CFB128GFSbox256",  "fips_aesavs -f" ],
171     [ "CFB128KeySbox128", "fips_aesavs -f" ],
172     [ "CFB128KeySbox192", "fips_aesavs -f" ],
173     [ "CFB128KeySbox256", "fips_aesavs -f" ],
174     [ "CFB128MCT128",     "fips_aesavs -f" ],
175     [ "CFB128MCT192",     "fips_aesavs -f" ],
176     [ "CFB128MCT256",     "fips_aesavs -f" ],
177     [ "CFB128MMT128",     "fips_aesavs -f" ],
178     [ "CFB128MMT192",     "fips_aesavs -f" ],
179     [ "CFB128MMT256",     "fips_aesavs -f" ],
180     [ "CFB128VarKey128",  "fips_aesavs -f" ],
181     [ "CFB128VarKey192",  "fips_aesavs -f" ],
182     [ "CFB128VarKey256",  "fips_aesavs -f" ],
183     [ "CFB128VarTxt128",  "fips_aesavs -f" ],
184     [ "CFB128VarTxt192",  "fips_aesavs -f" ],
185     [ "CFB128VarTxt256",  "fips_aesavs -f" ],
186     [ "CFB8GFSbox128",    "fips_aesavs -f" ],
187     [ "CFB8GFSbox192",    "fips_aesavs -f" ],
188     [ "CFB8GFSbox256",    "fips_aesavs -f" ],
189     [ "CFB8KeySbox128",   "fips_aesavs -f" ],
190     [ "CFB8KeySbox192",   "fips_aesavs -f" ],
191     [ "CFB8KeySbox256",   "fips_aesavs -f" ],
192     [ "CFB8MCT128",       "fips_aesavs -f" ],
193     [ "CFB8MCT192",       "fips_aesavs -f" ],
194     [ "CFB8MCT256",       "fips_aesavs -f" ],
195     [ "CFB8MMT128",       "fips_aesavs -f" ],
196     [ "CFB8MMT192",       "fips_aesavs -f" ],
197     [ "CFB8MMT256",       "fips_aesavs -f" ],
198     [ "CFB8VarKey128",    "fips_aesavs -f" ],
199     [ "CFB8VarKey192",    "fips_aesavs -f" ],
200     [ "CFB8VarKey256",    "fips_aesavs -f" ],
201     [ "CFB8VarTxt128",    "fips_aesavs -f" ],
202     [ "CFB8VarTxt192",    "fips_aesavs -f" ],
203     [ "CFB8VarTxt256",    "fips_aesavs -f" ],
204
205     [ "ECBGFSbox128",  "fips_aesavs -f" ],
206     [ "ECBGFSbox192",  "fips_aesavs -f" ],
207     [ "ECBGFSbox256",  "fips_aesavs -f" ],
208     [ "ECBKeySbox128", "fips_aesavs -f" ],
209     [ "ECBKeySbox192", "fips_aesavs -f" ],
210     [ "ECBKeySbox256", "fips_aesavs -f" ],
211     [ "ECBMCT128",     "fips_aesavs -f" ],
212     [ "ECBMCT192",     "fips_aesavs -f" ],
213     [ "ECBMCT256",     "fips_aesavs -f" ],
214     [ "ECBMMT128",     "fips_aesavs -f" ],
215     [ "ECBMMT192",     "fips_aesavs -f" ],
216     [ "ECBMMT256",     "fips_aesavs -f" ],
217     [ "ECBVarKey128",  "fips_aesavs -f" ],
218     [ "ECBVarKey192",  "fips_aesavs -f" ],
219     [ "ECBVarKey256",  "fips_aesavs -f" ],
220     [ "ECBVarTxt128",  "fips_aesavs -f" ],
221     [ "ECBVarTxt192",  "fips_aesavs -f" ],
222     [ "ECBVarTxt256",  "fips_aesavs -f" ],
223     [ "OFBGFSbox128",  "fips_aesavs -f" ],
224     [ "OFBGFSbox192",  "fips_aesavs -f" ],
225     [ "OFBGFSbox256",  "fips_aesavs -f" ],
226     [ "OFBKeySbox128", "fips_aesavs -f" ],
227     [ "OFBKeySbox192", "fips_aesavs -f" ],
228     [ "OFBKeySbox256", "fips_aesavs -f" ],
229     [ "OFBMCT128",     "fips_aesavs -f" ],
230     [ "OFBMCT192",     "fips_aesavs -f" ],
231     [ "OFBMCT256",     "fips_aesavs -f" ],
232     [ "OFBMMT128",     "fips_aesavs -f" ],
233     [ "OFBMMT192",     "fips_aesavs -f" ],
234     [ "OFBMMT256",     "fips_aesavs -f" ],
235     [ "OFBVarKey128",  "fips_aesavs -f" ],
236     [ "OFBVarKey192",  "fips_aesavs -f" ],
237     [ "OFBVarKey256",  "fips_aesavs -f" ],
238     [ "OFBVarTxt128",  "fips_aesavs -f" ],
239     [ "OFBVarTxt192",  "fips_aesavs -f" ],
240     [ "OFBVarTxt256",  "fips_aesavs -f" ]
241
242 );
243
244 my @fips_aes_cfb1_test_list = (
245
246     # AES CFB1 tests
247
248     [ "CFB1GFSbox128",  "fips_aesavs -f" ],
249     [ "CFB1GFSbox192",  "fips_aesavs -f" ],
250     [ "CFB1GFSbox256",  "fips_aesavs -f" ],
251     [ "CFB1KeySbox128", "fips_aesavs -f" ],
252     [ "CFB1KeySbox192", "fips_aesavs -f" ],
253     [ "CFB1KeySbox256", "fips_aesavs -f" ],
254     [ "CFB1MCT128",     "fips_aesavs -f" ],
255     [ "CFB1MCT192",     "fips_aesavs -f" ],
256     [ "CFB1MCT256",     "fips_aesavs -f" ],
257     [ "CFB1MMT128",     "fips_aesavs -f" ],
258     [ "CFB1MMT192",     "fips_aesavs -f" ],
259     [ "CFB1MMT256",     "fips_aesavs -f" ],
260     [ "CFB1VarKey128",  "fips_aesavs -f" ],
261     [ "CFB1VarKey192",  "fips_aesavs -f" ],
262     [ "CFB1VarKey256",  "fips_aesavs -f" ],
263     [ "CFB1VarTxt128",  "fips_aesavs -f" ],
264     [ "CFB1VarTxt192",  "fips_aesavs -f" ],
265     [ "CFB1VarTxt256",  "fips_aesavs -f" ]
266
267 );
268
269 # Triple DES tests
270
271 my @fips_des3_test_list = (
272
273     "Triple DES",
274
275     [ "TCBCinvperm",   "fips_desmovs -f" ],
276     [ "TCBCMMT1",      "fips_desmovs -f" ],
277     [ "TCBCMMT2",      "fips_desmovs -f" ],
278     [ "TCBCMMT3",      "fips_desmovs -f" ],
279     [ "TCBCMonte1",    "fips_desmovs -f" ],
280     [ "TCBCMonte2",    "fips_desmovs -f" ],
281     [ "TCBCMonte3",    "fips_desmovs -f" ],
282     [ "TCBCpermop",    "fips_desmovs -f" ],
283     [ "TCBCsubtab",    "fips_desmovs -f" ],
284     [ "TCBCvarkey",    "fips_desmovs -f" ],
285     [ "TCBCvartext",   "fips_desmovs -f" ],
286     [ "TCFB64invperm", "fips_desmovs -f" ],
287     [ "TCFB64MMT1",    "fips_desmovs -f" ],
288     [ "TCFB64MMT2",    "fips_desmovs -f" ],
289     [ "TCFB64MMT3",    "fips_desmovs -f" ],
290     [ "TCFB64Monte1",  "fips_desmovs -f" ],
291     [ "TCFB64Monte2",  "fips_desmovs -f" ],
292     [ "TCFB64Monte3",  "fips_desmovs -f" ],
293     [ "TCFB64permop",  "fips_desmovs -f" ],
294     [ "TCFB64subtab",  "fips_desmovs -f" ],
295     [ "TCFB64varkey",  "fips_desmovs -f" ],
296     [ "TCFB64vartext", "fips_desmovs -f" ],
297     [ "TCFB8invperm",  "fips_desmovs -f" ],
298     [ "TCFB8MMT1",     "fips_desmovs -f" ],
299     [ "TCFB8MMT2",     "fips_desmovs -f" ],
300     [ "TCFB8MMT3",     "fips_desmovs -f" ],
301     [ "TCFB8Monte1",   "fips_desmovs -f" ],
302     [ "TCFB8Monte2",   "fips_desmovs -f" ],
303     [ "TCFB8Monte3",   "fips_desmovs -f" ],
304     [ "TCFB8permop",   "fips_desmovs -f" ],
305     [ "TCFB8subtab",   "fips_desmovs -f" ],
306     [ "TCFB8varkey",   "fips_desmovs -f" ],
307     [ "TCFB8vartext",  "fips_desmovs -f" ],
308     [ "TECBinvperm",   "fips_desmovs -f" ],
309     [ "TECBMMT1",      "fips_desmovs -f" ],
310     [ "TECBMMT2",      "fips_desmovs -f" ],
311     [ "TECBMMT3",      "fips_desmovs -f" ],
312     [ "TECBMonte1",    "fips_desmovs -f" ],
313     [ "TECBMonte2",    "fips_desmovs -f" ],
314     [ "TECBMonte3",    "fips_desmovs -f" ],
315     [ "TECBpermop",    "fips_desmovs -f" ],
316     [ "TECBsubtab",    "fips_desmovs -f" ],
317     [ "TECBvarkey",    "fips_desmovs -f" ],
318     [ "TECBvartext",   "fips_desmovs -f" ],
319     [ "TOFBinvperm",   "fips_desmovs -f" ],
320     [ "TOFBMMT1",      "fips_desmovs -f" ],
321     [ "TOFBMMT2",      "fips_desmovs -f" ],
322     [ "TOFBMMT3",      "fips_desmovs -f" ],
323     [ "TOFBMonte1",    "fips_desmovs -f" ],
324     [ "TOFBMonte2",    "fips_desmovs -f" ],
325     [ "TOFBMonte3",    "fips_desmovs -f" ],
326     [ "TOFBpermop",    "fips_desmovs -f" ],
327     [ "TOFBsubtab",    "fips_desmovs -f" ],
328     [ "TOFBvarkey",    "fips_desmovs -f" ],
329     [ "TOFBvartext",   "fips_desmovs -f" ]
330
331 );
332
333 my @fips_des3_cfb1_test_list = (
334
335     # DES3 CFB1 tests
336
337     [ "TCFB1invperm",  "fips_desmovs -f" ],
338     [ "TCFB1MMT1",     "fips_desmovs -f" ],
339     [ "TCFB1MMT2",     "fips_desmovs -f" ],
340     [ "TCFB1MMT3",     "fips_desmovs -f" ],
341     [ "TCFB1Monte1",   "fips_desmovs -f" ],
342     [ "TCFB1Monte2",   "fips_desmovs -f" ],
343     [ "TCFB1Monte3",   "fips_desmovs -f" ],
344     [ "TCFB1permop",   "fips_desmovs -f" ],
345     [ "TCFB1subtab",   "fips_desmovs -f" ],
346     [ "TCFB1varkey",   "fips_desmovs -f" ],
347     [ "TCFB1vartext",  "fips_desmovs -f" ],
348
349 );
350
351 # Verification special cases.
352 # In most cases the output of a test is deterministic and
353 # it can be compared to a known good result. A few involve
354 # the genration and use of random keys and the output will
355 # be different each time. In thoses cases we perform special tests
356 # to simply check their consistency. For example signature generation
357 # output will be run through signature verification to see if all outputs
358 # show as valid.
359 #
360
361 my %verify_special = (
362     "PQGGen"        => "fips_dssvs pqgver",
363     "KeyPair"       => "fips_dssvs keyver",
364     "SigGen"        => "fips_dssvs sigver",
365     "SigGen15"      => "fips_rsavtest",
366     "SigGenRSA"     => "fips_rsavtest -x931",
367     "SigGenPSS(0)"  => "fips_rsavtest -saltlen 0",
368     "SigGenPSS(62)" => "fips_rsavtest -saltlen 62",
369 );
370
371 my $win32  = $^O =~ m/mswin/i;
372 my $onedir = 0;
373 my $filter = "";
374 my $tvdir;
375 my $tprefix;
376 my $shwrap_prefix;
377 my $debug          = 0;
378 my $quiet          = 0;
379 my $notest         = 0;
380 my $verify         = 1;
381 my $rspdir         = "rsp";
382 my $ignore_missing = 0;
383 my $ignore_bogus   = 0;
384 my $bufout         = '';
385 my $list_tests     = 0;
386
387 my %fips_enabled = (
388     dsa         => 1,
389     "dsa-pqgver"  => 0,
390     rsa         => 1,
391     "rsa-pss0"  => 0,
392     "rsa-pss62" => 1,
393     sha         => 1,
394     hmac        => 1,
395     cmac        => 0,
396     "rand-aes"  => 1,
397     "rand-des2" => 0,
398     aes         => 1,
399     "aes-cfb1"  => 0,
400     des3        => 1,
401     "des3-cfb1" => 0
402 );
403
404 foreach (@ARGV) {
405     if ( $_ eq "--win32" ) {
406         $win32 = 1;
407     }
408     elsif ( $_ eq "--onedir" ) {
409         $onedir = 1;
410     }
411     elsif ( $_ eq "--debug" ) {
412         $debug = 1;
413     }
414     elsif ( $_ eq "--ignore-missing" ) {
415         $ignore_missing = 1;
416     }
417     elsif ( $_ eq "--ignore-bogus" ) {
418         $ignore_bogus = 1;
419     }
420     elsif ( $_ eq "--generate" ) {
421         $verify = 0;
422     }
423     elsif ( $_ eq "--notest" ) {
424         $notest = 1;
425     }
426     elsif ( $_ eq "--quiet" ) {
427         $quiet = 1;
428     }
429     elsif (/--dir=(.*)$/) {
430         $tvdir = $1;
431     }
432     elsif (/--rspdir=(.*)$/) {
433         $rspdir = $1;
434     }
435     elsif (/--tprefix=(.*)$/) {
436         $tprefix = $1;
437     }
438     elsif (/--shwrap_prefix=(.*)$/) {
439         $shwrap_prefix = $1;
440     }
441     elsif (/^--(enable|disable)-(.*)$/) {
442         if ( !exists $fips_enabled{$2} ) {
443             print STDERR "Unknown test $2\n";
444         }
445         if ( $1 eq "enable" ) {
446             $fips_enabled{$2} = 1;
447         }
448         else {
449             $fips_enabled{$2} = 0;
450         }
451     }
452     elsif (/--filter=(.*)$/) {
453         $filter = $1;
454     }
455     elsif (/^--list-tests$/) {
456         $list_tests = 1;
457     }
458     else {
459         Help();
460         exit(1);
461     }
462 }
463
464 my @fips_test_list;
465
466 push @fips_test_list, @fips_dsa_test_list       if $fips_enabled{"dsa"};
467 push @fips_test_list, @fips_dsa_pqgver_test_list if $fips_enabled{"dsa-pqgver"};
468 push @fips_test_list, @fips_rsa_test_list       if $fips_enabled{"rsa"};
469 push @fips_test_list, @fips_rsa_pss0_test_list  if $fips_enabled{"rsa-pss0"};
470 push @fips_test_list, @fips_rsa_pss62_test_list if $fips_enabled{"rsa-pss62"};
471 push @fips_test_list, @fips_sha_test_list       if $fips_enabled{"sha"};
472 push @fips_test_list, @fips_hmac_test_list      if $fips_enabled{"hmac"};
473 push @fips_test_list, @fips_cmac_test_list      if $fips_enabled{"cmac"};
474 push @fips_test_list, @fips_rand_aes_test_list  if $fips_enabled{"rand-aes"};
475 push @fips_test_list, @fips_rand_des2_test_list if $fips_enabled{"rand-des2"};
476 push @fips_test_list, @fips_aes_test_list       if $fips_enabled{"aes"};
477 push @fips_test_list, @fips_aes_cfb1_test_list  if $fips_enabled{"aes-cfb1"};
478 push @fips_test_list, @fips_des3_test_list      if $fips_enabled{"des3"};
479 push @fips_test_list, @fips_des3_cfb1_test_list if $fips_enabled{"des3-cfb1"};
480
481 if ($list_tests) {
482     my ( $test, $en );
483     print "=====TEST LIST=====\n";
484     foreach $test ( sort keys %fips_enabled ) {
485         $en = $fips_enabled{$test};
486         $test =~ tr/[a-z]/[A-Z]/;
487         printf "%-10s %s\n", $test, $en ? "enabled" : "disabled";
488     }
489     exit(0);
490 }
491
492 foreach (@fips_test_list) {
493     next unless ref($_);
494     my $nm = $_->[0];
495     $_->[3] = "";
496     $_->[4] = "";
497     print STDERR "Duplicate test $nm\n" if exists $fips_tests{$nm};
498     $fips_tests{$nm} = $_;
499 }
500
501 $tvdir = "." unless defined $tvdir;
502
503 if ($win32) {
504     if ( !defined $tprefix ) {
505         if ($onedir) {
506             $tprefix = ".\\";
507         }
508         else {
509             $tprefix = "..\\out32dll\\";
510         }
511     }
512 }
513 else {
514     if ($onedir) {
515         $tprefix       = "./" unless defined $tprefix;
516         $shwrap_prefix = "./" unless defined $shwrap_prefix;
517     }
518     else {
519         $tprefix       = "../test/" unless defined $tprefix;
520         $shwrap_prefix = "../util/" unless defined $shwrap_prefix;
521     }
522 }
523
524 sanity_check_exe( $win32, $tprefix, $shwrap_prefix );
525
526 my $cmd_prefix = $win32 ? "" : "${shwrap_prefix}shlib_wrap.sh ";
527
528 find_files( $filter, $tvdir );
529
530 sanity_check_files();
531
532 my ( $runerr, $cmperr, $cmpok, $scheckrunerr, $scheckerr, $scheckok, $skipcnt )
533   = ( 0, 0, 0, 0, 0, 0, 0 );
534
535 exit(0) if $notest;
536
537 run_tests( $verify, $win32, $tprefix, $filter, $tvdir );
538
539 if ($verify) {
540     print "ALGORITHM TEST VERIFY SUMMARY REPORT:\n";
541     print "Tests skipped due to missing files:        $skipcnt\n";
542     print "Algorithm test program execution failures: $runerr\n";
543     print "Test comparisons successful:               $cmpok\n";
544     print "Test comparisons failed:                   $cmperr\n";
545     print "Test sanity checks successful:             $scheckok\n";
546     print "Test sanity checks failed:                 $scheckerr\n";
547     print "Sanity check program execution failures:   $scheckrunerr\n";
548
549     if ( $runerr || $cmperr || $scheckrunerr || $scheckerr ) {
550         print "***TEST FAILURE***\n";
551     }
552     else {
553         print "***ALL TESTS SUCCESSFUL***\n";
554     }
555 }
556 else {
557     print "ALGORITHM TEST SUMMARY REPORT:\n";
558     print "Tests skipped due to missing files:        $skipcnt\n";
559     print "Algorithm test program execution failures: $runerr\n";
560
561     if ($runerr) {
562         print "***TEST FAILURE***\n";
563     }
564     else {
565         print "***ALL TESTS SUCCESSFUL***\n";
566     }
567 }
568
569 #--------------------------------
570 sub Help {
571     ( my $cmd ) = ( $0 =~ m#([^/]+)$# );
572     print <<EOF;
573 $cmd: generate run CMVP algorithm tests
574         --debug                     Enable debug output
575         --dir=<dirname>             Optional root for *.req file search
576         --filter=<regexp>
577         --onedir <dirname>          Assume all components in current directory
578         --rspdir=<dirname>          Name of subdirectories containing *.rsp files, default "rsp"
579         --shwrap_prefix=<prefix>
580         --tprefix=<prefix>
581         --ignore-bogus              Ignore duplicate or bogus files
582         --ignore-missing            Ignore missing test files
583         --quiet                     Shhh....
584         --generate                  Generate algorithm test output
585         --win32                     Win32 environment
586         --enable-<alg>              Enable algorithm set <alg>.
587         --disable-<alg>             Disable algorithm set <alg>.
588         Where <alg> can be one of:
589 EOF
590
591 while (my ($key, $value) = each %fips_enabled)
592         {
593         printf "\t\t%-20s(%s by default)\n", $key ,
594                         $value ? "enabled" : "disabled";
595         }
596 }
597
598 # Sanity check to see if all necessary executables exist
599
600 sub sanity_check_exe {
601     my ( $win32, $tprefix, $shwrap_prefix ) = @_;
602     my %exe_list;
603     my $bad = 0;
604     $exe_list{ $shwrap_prefix . "shlib_wrap.sh" } = 1 unless $win32;
605     foreach (@fips_test_list) {
606         next unless ref($_);
607         my $cmd = $_->[1];
608         $cmd =~ s/ .*$//;
609         $cmd = $tprefix . $cmd;
610         $cmd .= ".exe" if $win32;
611         $exe_list{$cmd} = 1;
612     }
613
614     foreach ( sort keys %exe_list ) {
615         if ( !-f $_ ) {
616             print STDERR "ERROR: can't find executable $_\n";
617             $bad = 1;
618         }
619     }
620     if ($bad) {
621         print STDERR "FATAL ERROR: executables missing\n";
622         exit(1);
623     }
624     elsif ($debug) {
625         print STDERR "Executable sanity check passed OK\n";
626     }
627 }
628
629 # Search for all request and response files
630
631 sub find_files {
632     my ( $filter, $dir ) = @_;
633     my ( $dirh, $testname, $tref );
634     opendir( $dirh, $dir );
635     while ( $_ = readdir($dirh) ) {
636         next if ( $_ eq "." || $_ eq ".." );
637         $_ = "$dir/$_";
638         if ( -f "$_" ) {
639             if (/\/([^\/]*)\.rsp$/) {
640                 $tref = find_test($1, $_);
641                 $testname = $$tref[0];
642                 if ( defined $tref ) {
643                     if ( $$tref[4] eq "" ) {
644                         $$tref[4] = $_;
645                     }
646                     else {
647                         print STDERR
648 "WARNING: duplicate response file $_ for test $testname\n";
649                         $nbogus++;
650                     }
651                 }
652                 else {
653                     print STDERR "WARNING: bogus file $_\n";
654                     $nbogus++;
655                 }
656             }
657             next unless /$filter.*\.req$/i;
658             if (/\/([^\/]*)\.req$/) {
659                 $tref = find_test($1, $_);
660                 $testname = $$tref[0];
661                 if ( defined $tref ) {
662                     if ( $$tref[3] eq "" ) {
663                         $$tref[3] = $_;
664                     }
665                     else {
666                         print STDERR
667 "WARNING: duplicate request file $_ for test $testname\n";
668                         $nbogus++;
669                     }
670
671                 }
672                 elsif ( !/SHAmix\.req$/ ) {
673                     print STDERR "WARNING: unrecognized filename $_\n";
674                     $nbogus++;
675                 }
676             }
677         }
678         elsif ( -d "$_" ) {
679             find_files( $filter, $_ );
680         }
681     }
682     closedir($dirh);
683 }
684 #
685 # Find test based on filename.
686 # In ambiguous cases search file contents for a match
687 #
688
689 sub find_test {
690     my ( $test, $path ) = @_;
691     foreach $tref (@fips_test_list) {
692         next unless ref($tref);
693         my ( $tst, $cmd, $regexp, $req, $resp ) = @$tref;
694         $tst =~ s/\(.*$//;
695         if ($tst eq $test) {
696                 return $tref if (!defined $regexp);
697                 my $found = 0;
698                 my $line;
699                 open( IN, $path ) || die "Can't Open File $path";
700                 while ($line = <IN>) {
701                     if ($line =~ /$regexp/i) {
702                         $found = 1;
703                         last;
704                     }
705                 }
706                 close IN;
707                 return $tref if $found == 1;
708         }
709     }
710     return undef;
711 }
712
713 sub sanity_check_files {
714     my $bad = 0;
715     foreach (@fips_test_list) {
716         next unless ref($_);
717         my ( $tst, $cmd, $regexp, $req, $resp ) = @$_;
718
719         #print STDERR "FILES $tst, $cmd, $req, $resp\n";
720         if ( $req eq "" ) {
721             print STDERR "WARNING: missing request file for $tst\n";
722             $bad = 1;
723             next;
724         }
725         if ( $verify && $resp eq "" ) {
726             print STDERR "WARNING: no response file for test $tst\n";
727             $bad = 1;
728         }
729         elsif ( !$verify && $resp ne "" ) {
730             print STDERR "WARNING: response file $resp will be overwritten\n";
731         }
732     }
733     if ($bad) {
734         print STDERR "ERROR: test vector file set not complete\n";
735         exit(1) unless $ignore_missing;
736     }
737     if ($nbogus) {
738         print STDERR
739           "ERROR: $nbogus bogus or duplicate request and response files\n";
740         exit(1) unless $ignore_bogus;
741     }
742     if ( $debug && !$nbogus && !$bad ) {
743         print STDERR "test vector file set complete\n";
744     }
745 }
746
747 sub run_tests {
748     my ( $verify, $win32, $tprefix, $filter, $tvdir ) = @_;
749     my ( $tname, $tref );
750     my $bad = 0;
751     foreach (@fips_test_list) {
752         if ( !ref($_) ) {
753             print "Running $_ tests\n" unless $quiet;
754             next;
755         }
756         my ( $tname, $tcmd, $regexp, $req, $rsp ) = @$_;
757         my $out = $rsp;
758         if ($verify) {
759             $out =~ s/\.rsp$/.tst/;
760         }
761         if ( $req eq "" ) {
762             print STDERR
763               "WARNING: Request file for $tname missing: test skipped\n";
764             $skipcnt++;
765             next;
766         }
767         if ( $verify && $rsp eq "" ) {
768             print STDERR
769               "WARNING: Response file for $tname missing: test skipped\n";
770             $skipcnt++;
771             next;
772         }
773         elsif ( !$verify ) {
774             if ( $rsp ne "" ) {
775                 print STDERR "WARNING: Response file for $tname deleted\n";
776                 unlink $rsp;
777             }
778             $out = $req;
779             $out =~ s|/req/(\S+)\.req|/$rspdir/$1.rsp|;
780             my $outdir = $out;
781             $outdir =~ s|/[^/]*$||;
782             if ( !-d $outdir ) {
783                 print STDERR "DEBUG: Creating directory $outdir\n" if $debug;
784                 mkdir($outdir) || die "Can't create directory $outdir";
785             }
786         }
787         my $cmd = "$cmd_prefix$tprefix$tcmd ";
788         if ( $tcmd =~ /-f$/ ) {
789             $cmd .= "\"$req\" \"$out\"";
790         }
791         else {
792             $cmd .= "\"$req\" \"$out\"";
793         }
794         print STDERR "DEBUG: running test $tname\n" if ( $debug && !$verify );
795         system($cmd);
796         if ( $? != 0 ) {
797             print STDERR
798               "WARNING: error executing test $tname for command: $cmd\n";
799             $runerr++;
800             next;
801         }
802         if ($verify) {
803             if ( exists $verify_special{$tname} ) {
804                 my $vout = $rsp;
805                 $vout =~ s/\.rsp$/.ver/;
806                 $tcmd = $verify_special{$tname};
807                 $cmd  = "$cmd_prefix$tprefix$tcmd ";
808                 $cmd .= "\"$out\" \"$vout\"";
809                 system($cmd);
810                 if ( $? != 0 ) {
811                     print STDERR
812                       "WARNING: error executing verify test $tname $cmd\n";
813                     $scheckrunerr++;
814                     next;
815                 }
816                 my ( $fcount, $pcount ) = ( 0, 0 );
817                 open VER, "$vout";
818                 while (<VER>) {
819                     if (/^Result\s*=\s*(\S*)\s*$/i)
820
821                     {
822                         if ( $1 eq "F" ) {
823                             $fcount++;
824                         }
825                         else {
826                             $pcount++;
827                         }
828                     }
829                 }
830                 close VER;
831
832                 unlink $vout;
833                 if ( $fcount || $debug ) {
834                     print STDERR "DEBUG: $tname, Pass=$pcount, Fail=$fcount\n";
835                 }
836                 if ( $fcount || !$pcount ) {
837                     $scheckerr++;
838                 }
839                 else {
840                     $scheckok++;
841                 }
842
843             }
844             elsif ( !cmp_file( $tname, $rsp, $out ) ) {
845                 $cmperr++;
846             }
847             else {
848                 $cmpok++;
849             }
850             unlink $out;
851         }
852     }
853 }
854
855 sub cmp_file {
856     my ( $tname, $rsp, $tst ) = @_;
857     my ( $rspf,    $tstf );
858     my ( $rspline, $tstline );
859     if ( !open( $rspf, $rsp ) ) {
860         print STDERR "ERROR: can't open request file $rsp\n";
861         return 0;
862     }
863     if ( !open( $tstf, $tst ) ) {
864         print STDERR "ERROR: can't open output file $tst\n";
865         return 0;
866     }
867     for ( ; ; ) {
868         $rspline = next_line($rspf);
869         $tstline = next_line($tstf);
870         if ( !defined($rspline) && !defined($tstline) ) {
871             print STDERR "DEBUG: $tname file comparison OK\n" if $debug;
872             return 1;
873         }
874         if ( !defined($rspline) ) {
875             print STDERR "ERROR: $tname EOF on $rsp\n";
876             return 0;
877         }
878         if ( !defined($tstline) ) {
879             print STDERR "ERROR: $tname EOF on $tst\n";
880             return 0;
881         }
882
883         # Workaround for bug in RAND des2 test output */
884         if ( $tstline =~ /^Key2 =/ && $rspline =~ /^Key1 =/ ) {
885             $rspline =~ s/^Key1/Key2/;
886         }
887
888         if ( $tstline ne $rspline ) {
889             print STDERR "ERROR: $tname mismatch:\n";
890             print STDERR "\t \"$tstline\" != \"$rspline\"\n";
891             return 0;
892         }
893     }
894     return 1;
895 }
896
897 sub next_line {
898     my ($in) = @_;
899
900     while (<$in>) {
901         chomp;
902
903         # Delete comments
904         s/#.*$//;
905
906         # Ignore blank lines
907         next if (/^\s*$/);
908
909         # Translate multiple space into one
910         s/\s+/ /g;
911         # Delete trailing whitespace
912         s/\s+$//;
913         # Remove leading zeroes
914         s/= 00/= /;
915         # Translate to upper case
916         return uc $_;
917     }
918     return undef;
919 }