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