Prototypes for more FIPS functions for use in FIPS capable OpenSSL.
[openssl.git] / fips / fipsalgtest.pl
1 #!/usr/bin/perl -w
2 # Perl utility to run or verify FIPS 140-2 CAVP 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 my @fips_aes_ccm_test_list = (
270
271     # AES CCM tests
272
273     "AES CCM",
274
275     [ "DVPT128",  "fips_gcmtest -ccm" ],
276     [ "DVPT192",  "fips_gcmtest -ccm" ],
277     [ "DVPT256",  "fips_gcmtest -ccm" ],
278     [ "VADT128",  "fips_gcmtest -ccm" ],
279     [ "VADT192",  "fips_gcmtest -ccm" ],
280     [ "VADT256",  "fips_gcmtest -ccm" ],
281     [ "VNT128",  "fips_gcmtest -ccm" ],
282     [ "VNT192",  "fips_gcmtest -ccm" ],
283     [ "VNT256",  "fips_gcmtest -ccm" ],
284     [ "VPT128",  "fips_gcmtest -ccm" ],
285     [ "VPT192",  "fips_gcmtest -ccm" ],
286     [ "VPT256",  "fips_gcmtest -ccm" ],
287     [ "VTT128",  "fips_gcmtest -ccm" ],
288     [ "VTT192",  "fips_gcmtest -ccm" ],
289     [ "VTT256",  "fips_gcmtest -ccm" ]
290
291 );
292
293 my @fips_aes_gcm_test_list = (
294
295     # AES GCM tests
296
297     "AES GCM",
298
299     [ "gcmDecrypt128",  "fips_gcmtest -decrypt" ],
300     [ "gcmDecrypt192",  "fips_gcmtest -decrypt" ],
301     [ "gcmDecrypt256",  "fips_gcmtest -decrypt" ],
302
303 );
304
305 my @fips_aes_xts_test_list = (
306     # AES XTS tests
307
308     "AES XTS",
309
310     [ "XTSGenAES128",  "fips_gcmtest -xts" ],
311     [ "XTSGenAES256",  "fips_gcmtest -xts" ],
312
313 );
314
315 # Triple DES tests
316
317 my @fips_des3_test_list = (
318
319     "Triple DES",
320
321     [ "TCBCinvperm",   "fips_desmovs -f" ],
322     [ "TCBCMMT1",      "fips_desmovs -f" ],
323     [ "TCBCMMT2",      "fips_desmovs -f" ],
324     [ "TCBCMMT3",      "fips_desmovs -f" ],
325     [ "TCBCMonte1",    "fips_desmovs -f" ],
326     [ "TCBCMonte2",    "fips_desmovs -f" ],
327     [ "TCBCMonte3",    "fips_desmovs -f" ],
328     [ "TCBCpermop",    "fips_desmovs -f" ],
329     [ "TCBCsubtab",    "fips_desmovs -f" ],
330     [ "TCBCvarkey",    "fips_desmovs -f" ],
331     [ "TCBCvartext",   "fips_desmovs -f" ],
332     [ "TCFB64invperm", "fips_desmovs -f" ],
333     [ "TCFB64MMT1",    "fips_desmovs -f" ],
334     [ "TCFB64MMT2",    "fips_desmovs -f" ],
335     [ "TCFB64MMT3",    "fips_desmovs -f" ],
336     [ "TCFB64Monte1",  "fips_desmovs -f" ],
337     [ "TCFB64Monte2",  "fips_desmovs -f" ],
338     [ "TCFB64Monte3",  "fips_desmovs -f" ],
339     [ "TCFB64permop",  "fips_desmovs -f" ],
340     [ "TCFB64subtab",  "fips_desmovs -f" ],
341     [ "TCFB64varkey",  "fips_desmovs -f" ],
342     [ "TCFB64vartext", "fips_desmovs -f" ],
343     [ "TCFB8invperm",  "fips_desmovs -f" ],
344     [ "TCFB8MMT1",     "fips_desmovs -f" ],
345     [ "TCFB8MMT2",     "fips_desmovs -f" ],
346     [ "TCFB8MMT3",     "fips_desmovs -f" ],
347     [ "TCFB8Monte1",   "fips_desmovs -f" ],
348     [ "TCFB8Monte2",   "fips_desmovs -f" ],
349     [ "TCFB8Monte3",   "fips_desmovs -f" ],
350     [ "TCFB8permop",   "fips_desmovs -f" ],
351     [ "TCFB8subtab",   "fips_desmovs -f" ],
352     [ "TCFB8varkey",   "fips_desmovs -f" ],
353     [ "TCFB8vartext",  "fips_desmovs -f" ],
354     [ "TECBinvperm",   "fips_desmovs -f" ],
355     [ "TECBMMT1",      "fips_desmovs -f" ],
356     [ "TECBMMT2",      "fips_desmovs -f" ],
357     [ "TECBMMT3",      "fips_desmovs -f" ],
358     [ "TECBMonte1",    "fips_desmovs -f" ],
359     [ "TECBMonte2",    "fips_desmovs -f" ],
360     [ "TECBMonte3",    "fips_desmovs -f" ],
361     [ "TECBpermop",    "fips_desmovs -f" ],
362     [ "TECBsubtab",    "fips_desmovs -f" ],
363     [ "TECBvarkey",    "fips_desmovs -f" ],
364     [ "TECBvartext",   "fips_desmovs -f" ],
365     [ "TOFBinvperm",   "fips_desmovs -f" ],
366     [ "TOFBMMT1",      "fips_desmovs -f" ],
367     [ "TOFBMMT2",      "fips_desmovs -f" ],
368     [ "TOFBMMT3",      "fips_desmovs -f" ],
369     [ "TOFBMonte1",    "fips_desmovs -f" ],
370     [ "TOFBMonte2",    "fips_desmovs -f" ],
371     [ "TOFBMonte3",    "fips_desmovs -f" ],
372     [ "TOFBpermop",    "fips_desmovs -f" ],
373     [ "TOFBsubtab",    "fips_desmovs -f" ],
374     [ "TOFBvarkey",    "fips_desmovs -f" ],
375     [ "TOFBvartext",   "fips_desmovs -f" ]
376
377 );
378
379 my @fips_des3_cfb1_test_list = (
380
381     # DES3 CFB1 tests
382
383     [ "TCFB1invperm",  "fips_desmovs -f" ],
384     [ "TCFB1MMT1",     "fips_desmovs -f" ],
385     [ "TCFB1MMT2",     "fips_desmovs -f" ],
386     [ "TCFB1MMT3",     "fips_desmovs -f" ],
387     [ "TCFB1Monte1",   "fips_desmovs -f" ],
388     [ "TCFB1Monte2",   "fips_desmovs -f" ],
389     [ "TCFB1Monte3",   "fips_desmovs -f" ],
390     [ "TCFB1permop",   "fips_desmovs -f" ],
391     [ "TCFB1subtab",   "fips_desmovs -f" ],
392     [ "TCFB1varkey",   "fips_desmovs -f" ],
393     [ "TCFB1vartext",  "fips_desmovs -f" ],
394
395 );
396
397 my @fips_drbg_test_list = (
398
399     # SP800-90 DRBG tests
400     "SP800-90 DRBG",
401     [ "CTR_DRBG",   "fips_drbgvs" ],
402     [ "Hash_DRBG",  "fips_drbgvs" ]
403
404 );
405
406 my @fips_dh_test_list = (
407
408     # DH
409     "DH Ephemeral Primitives Only",
410     [ "KASValidityTest_FFCEphem_NOKC_ZZOnly_init",   "fips_dhvs dhver" ],
411     [ "KASValidityTest_FFCEphem_NOKC_ZZOnly_resp",   "fips_dhvs dhver" ],
412
413 );
414
415 my @fips_ecdh_test_list = (
416
417     # ECDH
418     "ECDH Ephemeral Primitives Only",
419     [ "KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init",
420                                                         "fips_ecdhvs ecdhver" ],
421     [ "KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp",
422                                                         "fips_ecdhvs ecdhver" ],
423
424 );
425
426
427 # Verification special cases.
428 # In most cases the output of a test is deterministic and
429 # it can be compared to a known good result. A few involve
430 # the genration and use of random keys and the output will
431 # be different each time. In thoses cases we perform special tests
432 # to simply check their consistency. For example signature generation
433 # output will be run through signature verification to see if all outputs
434 # show as valid.
435 #
436
437 my %verify_special = (
438     "PQGGen"        => "fips_dssvs pqgver",
439     "KeyPair"       => "fips_dssvs keyver",
440     "SigGen"        => "fips_dssvs sigver",
441     "SigGen15"      => "fips_rsavtest",
442     "SigGenRSA"     => "fips_rsavtest -x931",
443     "SigGenPSS(0)"  => "fips_rsavtest -saltlen 0",
444     "SigGenPSS(62)" => "fips_rsavtest -saltlen 62",
445 );
446
447 my $win32  = $^O =~ m/mswin/i;
448 my $onedir = 0;
449 my $filter = "";
450 my $tvdir;
451 my $tprefix;
452 my $debug          = 0;
453 my $quiet          = 0;
454 my $notest         = 0;
455 my $verify         = 1;
456 my $rspdir         = "rsp";
457 my $ignore_missing = 0;
458 my $ignore_bogus   = 0;
459 my $bufout         = '';
460 my $list_tests     = 0;
461 my $minimal_script = 0;
462 my $outfile        = '';
463 my $no_warn_missing = 0;
464 my $no_warn_bogus = 0;
465 my $rmcmd = "rm -rf";
466 my $mkcmd = "mkdir";
467
468 my %fips_enabled = (
469     dsa         => 1,
470     "dsa-pqgver"  => 0,
471     rsa         => 1,
472     "rsa-pss0"  => 0,
473     "rsa-pss62" => 1,
474     sha         => 1,
475     hmac        => 1,
476     cmac        => 0,
477     "rand-aes"  => 1,
478     "rand-des2" => 0,
479     aes         => 1,
480     "aes-cfb1"  => 0,
481     des3        => 1,
482     "des3-cfb1" => 0,
483     drbg        => 0,
484     ccm         => 0,
485     "aes-xts"   => 0,
486     gcm         => 0,
487     dh          => 0,
488     ecdh        => 0,
489 );
490
491 foreach (@ARGV) {
492     if ( $_ eq "--win32" ) {
493         $win32 = 1;
494     }
495     elsif ( $_ eq "--onedir" ) {
496         $onedir = 1;
497     }
498     elsif ( $_ eq "--debug" ) {
499         $debug = 1;
500     }
501     elsif ( $_ eq "--quiet-missing" ) {
502         $ignore_missing = 1;
503         $no_warn_missing = 1;
504     }
505     elsif ( $_ eq "--ignore-missing" ) {
506         $ignore_missing = 1;
507     }
508     elsif ( $_ eq "--quiet-bogus" ) {
509         $ignore_bogus = 1;
510         $no_warn_bogus = 1;
511     }
512     elsif ( $_ eq "--ignore-bogus" ) {
513         $ignore_bogus = 1;
514     }
515     elsif ( $_ eq "--minimal-script" ) {
516         $minimal_script = 1;
517     }
518     elsif (/--generate-script=(.*)$/) {
519         $outfile = $1;
520         $verify = 0;
521     } elsif ( $_ eq "--generate" ) {
522         $verify = 0;
523     }
524     elsif ( $_ eq "--notest" ) {
525         $notest = 1;
526     }
527     elsif ( $_ eq "--quiet" ) {
528         $quiet = 1;
529     }
530     elsif (/--dir=(.*)$/) {
531         $tvdir = $1;
532     }
533     elsif (/--rspdir=(.*)$/) {
534         $rspdir = $1;
535     }
536     elsif (/--tprefix=(.*)$/) {
537         $tprefix = $1;
538     }
539     elsif (/^--(enable|disable)-(.*)$/) {
540         if ( !exists $fips_enabled{$2} ) {
541             print STDERR "Unknown test $2\n";
542             exit(1);
543         }
544         if ( $1 eq "enable" ) {
545             $fips_enabled{$2} = 1;
546         }
547         else {
548             $fips_enabled{$2} = 0;
549         }
550     }
551     elsif (/--filter=(.*)$/) {
552         $filter = $1;
553     }
554     elsif (/--rm=(.*)$/) {
555         $rmcmd = $1;
556     }
557     elsif (/--script-tprefix=(.*)$/) {
558         $stprefix = $1;
559     }
560     elsif (/--mkdir=(.*)$/) {
561         $mkcmd = $1;
562     }
563     elsif (/^--list-tests$/) {
564         $list_tests = 1;
565     }
566     else {
567         Help();
568         exit(1);
569     }
570 }
571
572 my @fips_test_list;
573
574 push @fips_test_list, @fips_dsa_test_list       if $fips_enabled{"dsa"};
575 push @fips_test_list, @fips_dsa_pqgver_test_list if $fips_enabled{"dsa-pqgver"};
576 push @fips_test_list, @fips_rsa_test_list       if $fips_enabled{"rsa"};
577 push @fips_test_list, @fips_rsa_pss0_test_list  if $fips_enabled{"rsa-pss0"};
578 push @fips_test_list, @fips_rsa_pss62_test_list if $fips_enabled{"rsa-pss62"};
579 push @fips_test_list, @fips_sha_test_list       if $fips_enabled{"sha"};
580 push @fips_test_list, @fips_hmac_test_list      if $fips_enabled{"hmac"};
581 push @fips_test_list, @fips_cmac_test_list      if $fips_enabled{"cmac"};
582 push @fips_test_list, @fips_rand_aes_test_list  if $fips_enabled{"rand-aes"};
583 push @fips_test_list, @fips_rand_des2_test_list if $fips_enabled{"rand-des2"};
584 push @fips_test_list, @fips_aes_test_list       if $fips_enabled{"aes"};
585 push @fips_test_list, @fips_aes_cfb1_test_list  if $fips_enabled{"aes-cfb1"};
586 push @fips_test_list, @fips_des3_test_list      if $fips_enabled{"des3"};
587 push @fips_test_list, @fips_des3_cfb1_test_list if $fips_enabled{"des3-cfb1"};
588 push @fips_test_list, @fips_drbg_test_list      if $fips_enabled{"drbg"};
589 push @fips_test_list, @fips_aes_ccm_test_list   if $fips_enabled{"aes-ccm"};
590 push @fips_test_list, @fips_aes_gcm_test_list   if $fips_enabled{"aes-gcm"};
591 push @fips_test_list, @fips_aes_xts_test_list   if $fips_enabled{"aes-xts"};
592 push @fips_test_list, @fips_dh_test_list        if $fips_enabled{"dh"};
593 push @fips_test_list, @fips_ecdh_test_list      if $fips_enabled{"ecdh"};
594
595 if ($list_tests) {
596     my ( $test, $en );
597     print "=====TEST LIST=====\n";
598     foreach $test ( sort keys %fips_enabled ) {
599         $en = $fips_enabled{$test};
600         $test =~ tr/[a-z]/[A-Z]/;
601         printf "%-10s %s\n", $test, $en ? "enabled" : "disabled";
602     }
603     exit(0);
604 }
605
606 foreach (@fips_test_list) {
607     next unless ref($_);
608     my $nm = $$_[0];
609     $$_[3] = "";
610     $$_[4] = "";
611     print STDERR "Duplicate test $nm\n" if exists $fips_tests{$nm};
612     $fips_tests{$nm} = $_;
613 }
614
615 $tvdir = "." unless defined $tvdir;
616
617 if ($win32) {
618     if ( !defined $tprefix ) {
619         if ($onedir) {
620             $tprefix = ".\\";
621         }
622         else {
623             $tprefix = "..\\out32dll\\";
624         }
625     }
626 }
627 else {
628     if ($onedir) {
629         $tprefix       = "./" unless defined $tprefix;
630     }
631     else {
632         $tprefix       = "../test/" unless defined $tprefix;
633     }
634 }
635
636 sanity_check_exe( $win32, $tprefix) if $outfile eq "";
637
638 find_files( $filter, $tvdir );
639
640 sanity_check_files();
641
642 my ( $runerr, $cmperr, $cmpok, $scheckrunerr, $scheckerr, $scheckok, $skipcnt )
643   = ( 0, 0, 0, 0, 0, 0, 0 );
644
645 exit(0) if $notest;
646 print "Outputting commands to $outfile\n" if $outfile ne "";
647 run_tests( $verify, $win32, $tprefix, $filter, $tvdir, $outfile );
648
649 if ($verify) {
650     print "ALGORITHM TEST VERIFY SUMMARY REPORT:\n";
651     print "Tests skipped due to missing files:        $skipcnt\n";
652     print "Algorithm test program execution failures: $runerr\n";
653     print "Test comparisons successful:               $cmpok\n";
654     print "Test comparisons failed:                   $cmperr\n";
655     print "Test sanity checks successful:             $scheckok\n";
656     print "Test sanity checks failed:                 $scheckerr\n";
657     print "Sanity check program execution failures:   $scheckrunerr\n";
658
659     if ( $runerr || $cmperr || $scheckrunerr || $scheckerr ) {
660         print "***TEST FAILURE***\n";
661     }
662     else {
663         print "***ALL TESTS SUCCESSFUL***\n";
664     }
665 }
666 elsif ($outfile eq "") {
667     print "ALGORITHM TEST SUMMARY REPORT:\n";
668     print "Tests skipped due to missing files:        $skipcnt\n";
669     print "Algorithm test program execution failures: $runerr\n";
670
671     if ($runerr) {
672         print "***TEST FAILURE***\n";
673     }
674     else {
675         print "***ALL TESTS SUCCESSFUL***\n";
676     }
677 }
678
679 #--------------------------------
680 sub Help {
681     ( my $cmd ) = ( $0 =~ m#([^/]+)$# );
682     print <<EOF;
683 $cmd: generate run CAVP algorithm tests
684         --debug                     Enable debug output
685         --dir=<dirname>             Optional root for *.req file search
686         --filter=<regexp>
687         --onedir <dirname>          Assume all components in current directory
688         --rspdir=<dirname>          Name of subdirectories containing *.rsp files, default "rsp"
689         --tprefix=<prefix>
690         --ignore-bogus              Ignore duplicate or bogus files
691         --ignore-missing            Ignore missing test files
692         --quiet                     Shhh....
693         --generate                  Generate algorithm test output
694         --win32                     Win32 environment
695         --enable-<alg>              Enable algorithm set <alg>.
696         --disable-<alg>             Disable algorithm set <alg>.
697         Where <alg> can be one of:
698 EOF
699
700 while (my ($key, $value) = each %fips_enabled)
701         {
702         printf "\t\t%-20s(%s by default)\n", $key ,
703                         $value ? "enabled" : "disabled";
704         }
705 }
706
707 # Sanity check to see if all necessary executables exist
708
709 sub sanity_check_exe {
710     my ( $win32, $tprefix, ) = @_;
711     my %exe_list;
712     my $bad = 0;
713     foreach (@fips_test_list) {
714         next unless ref($_);
715         my $cmd = $_->[1];
716         $cmd =~ s/ .*$//;
717         $cmd = $tprefix . $cmd;
718         $cmd .= ".exe" if $win32;
719         $exe_list{$cmd} = 1;
720     }
721
722     foreach ( sort keys %exe_list ) {
723         if ( !-f $_ ) {
724             print STDERR "ERROR: can't find executable $_\n";
725             $bad = 1;
726         }
727     }
728     if ($bad) {
729         print STDERR "FATAL ERROR: executables missing\n";
730         exit(1);
731     }
732     elsif ($debug) {
733         print STDERR "Executable sanity check passed OK\n";
734     }
735 }
736
737 # Search for all request and response files
738
739 sub find_files {
740     my ( $filter, $dir ) = @_;
741     my ( $dirh, $testname, $tref );
742     opendir( $dirh, $dir );
743     while ( $_ = readdir($dirh) ) {
744         next if ( $_ eq "." || $_ eq ".." );
745         $_ = "$dir/$_";
746         if ( -f "$_" ) {
747             if (/\/([^\/]*)\.rsp$/) {
748                 $tref = find_test($1, $_);
749                 if ( defined $tref ) {
750                     $testname = $$tref[0];
751                     if ( $$tref[4] eq "" ) {
752                         $$tref[4] = $_;
753                     }
754                     else {
755                         print STDERR
756 "WARNING: duplicate response file $_ for test $testname\n";
757                         $nbogus++;
758                     }
759                 }
760                 else {
761                     print STDERR "WARNING: bogus file $_\n" unless $no_warn_bogus;
762                     $nbogus++;
763                 }
764             }
765             next unless /$filter.*\.req$/i;
766             if (/\/([^\/]*)\.req$/) {
767                 $tref = find_test($1, $_);
768                 if ( defined $tref ) {
769                     $testname = $$tref[0];
770                     if ( $$tref[3] eq "" ) {
771                         $$tref[3] = $_;
772                     }
773                     else {
774                         print STDERR
775 "WARNING: duplicate request file $_ for test $testname\n";
776                         $nbogus++;
777                     }
778
779                 }
780                 elsif ( !/SHAmix\.req$/ ) {
781                     print STDERR "WARNING: unrecognized filename $_\n" unless $no_warn_bogus;
782                     $nbogus++;
783                 }
784             }
785         }
786         elsif ( -d "$_" ) {
787             find_files( $filter, $_ );
788         }
789     }
790     closedir($dirh);
791 }
792 #
793 # Find test based on filename.
794 # In ambiguous cases search file contents for a match
795 #
796
797 sub find_test {
798     my ( $test, $path ) = @_;
799     foreach $tref (@fips_test_list) {
800         next unless ref($tref);
801         my ( $tst, $cmd, $regexp, $req, $resp ) = @$tref;
802         $tst =~ s/\(.*$//;
803         if ($tst eq $test) {
804                 return $tref if (!defined $regexp);
805                 my $found = 0;
806                 my $line;
807                 open( IN, $path ) || die "Can't Open File $path";
808                 while ($line = <IN>) {
809                     if ($line =~ /$regexp/i) {
810                         $found = 1;
811                         last;
812                     }
813                 }
814                 close IN;
815                 return $tref if $found == 1;
816         }
817     }
818     return undef;
819 }
820
821 sub sanity_check_files {
822     my $bad = 0;
823     foreach (@fips_test_list) {
824         next unless ref($_);
825         my ( $tst, $cmd, $regexp, $req, $resp ) = @$_;
826
827         #print STDERR "FILES $tst, $cmd, $req, $resp\n";
828         if ( $req eq "" ) {
829             print STDERR "WARNING: missing request file for $tst\n" unless $no_warn_missing;
830             $bad = 1;
831             next;
832         }
833         if ( $verify && $resp eq "" ) {
834             print STDERR "WARNING: no response file for test $tst\n";
835             $bad = 1;
836         }
837         elsif ( !$verify && $resp ne "" ) {
838             print STDERR "WARNING: response file $resp will be overwritten\n";
839         }
840     }
841     if ($bad) {
842         print STDERR "ERROR: test vector file set not complete\n";
843         exit(1) unless $ignore_missing;
844     }
845     if ($nbogus) {
846         print STDERR
847           "ERROR: $nbogus bogus or duplicate request and response files\n";
848         exit(1) unless $ignore_bogus;
849     }
850     if ( $debug && !$nbogus && !$bad ) {
851         print STDERR "test vector file set complete\n";
852     }
853 }
854
855 sub run_tests {
856     my ( $verify, $win32, $tprefix, $filter, $tvdir, $outfile ) = @_;
857     my ( $tname, $tref );
858     my $bad = 0;
859     my $lastdir = "";
860     if ($outfile ne "") {
861         open OUT, ">$outfile" || die "Can't open $outfile";
862     }
863     if ($outfile ne "" && !$minimal_script) {
864         if ($win32) {
865             print OUT <<\END;
866 @echo off
867 rem Test vector run script
868 rem Auto generated by fipsalgtest.pl script
869 rem Do not edit
870
871 echo Running Algorithm Tests
872
873 END
874         } else {
875         $stprefix = $tprefix unless defined $stprefix;
876             print OUT <<END;
877 #!/bin/sh
878
879 # Test vector run script
880 # Auto generated by fipsalgtest.pl script
881 # Do not edit
882
883 echo Running Algorithm Tests
884
885 RM="$rmcmd";
886 MKDIR="$mkcmd";
887 TPREFIX=$stprefix
888
889 END
890         }
891
892     }
893
894     foreach (@fips_test_list) {
895         if ( !ref($_) ) {
896             if ($outfile ne "") {
897                 print "Generating script for $_ tests\n";
898                 print OUT "\n\n\necho \"Running $_ tests\"\n" unless $minimal_script;
899             } else {    
900                 print "Running $_ tests\n" unless $quiet;
901             }
902             next;
903         }
904         my ( $tname, $tcmd, $regexp, $req, $rsp ) = @$_;
905         my $out = $rsp;
906         if ($verify) {
907             $out =~ s/\.rsp$/.tst/;
908         }
909         if ( $req eq "" ) {
910             print STDERR
911               "WARNING: Request file for $tname missing: test skipped\n" unless $no_warn_missing;
912             $skipcnt++;
913             next;
914         }
915         if ( $verify && $rsp eq "" ) {
916             print STDERR
917               "WARNING: Response file for $tname missing: test skipped\n";
918             $skipcnt++;
919             next;
920         }
921         elsif ( !$verify ) {
922             if ( $rsp ne "" ) {
923                 print STDERR "WARNING: Response file for $tname deleted\n";
924                 unlink $rsp;
925             }
926             $out = $req;
927             $out =~ s|/req/(\S+)\.req|/$rspdir/$1.rsp|;
928             my $outdir = $out;
929             $outdir =~ s|/[^/]*$||;
930             if ($outfile ne "") {
931                 if ($win32) {
932                     $outdir =~ tr|/|\\|;
933                     $req =~ tr|/|\\|;
934                     $out =~ tr|/|\\|;
935                 }
936                 if ($outdir ne $lastdir && !$minimal_script) {
937                     if ($win32) {
938                     print OUT <<END
939 if exist \"$outdir\" rd /s /q "$outdir"
940 md \"$outdir\"
941
942 END
943                     } else {
944                     print OUT <<END
945 \$RM \"$outdir\"
946 \$MKDIR \"$outdir\"
947
948 END
949                     }
950                 $lastdir = $outdir;
951                 }
952             } elsif ( !-d $outdir ) {
953                 print STDERR "DEBUG: Creating directory $outdir\n" if $debug;
954                 mkdir($outdir) || die "Can't create directory $outdir";
955             }
956         }
957         my $cmd = "$tcmd \"$req\" \"$out\"";
958         print STDERR "DEBUG: running test $tname\n" if ( $debug && !$verify );
959         if ($outfile ne "") {
960             print OUT "echo \"    running $tname test\"\n" unless $minimal_script;
961             print OUT "\${TPREFIX}$cmd\n";
962         } else {
963             $cmd = "$tprefix$cmd";
964             system($cmd);
965             if ( $? != 0 ) {
966                 print STDERR
967                      "WARNING: error executing test $tname for command: $cmd\n";
968                 $runerr++;
969                 next;
970             }
971         }
972         if ($verify) {
973             if ( exists $verify_special{$tname} ) {
974                 my $vout = $rsp;
975                 $vout =~ s/\.rsp$/.ver/;
976                 $tcmd = $verify_special{$tname};
977                 $cmd  = "$tprefix$tcmd ";
978                 $cmd .= "\"$out\" \"$vout\"";
979                 system($cmd);
980                 if ( $? != 0 ) {
981                     print STDERR
982                       "WARNING: error executing verify test $tname $cmd\n";
983                     $scheckrunerr++;
984                     next;
985                 }
986                 my ( $fcount, $pcount ) = ( 0, 0 );
987                 open VER, "$vout";
988                 while (<VER>) {
989                     if (/^Result\s*=\s*(\S*)\s*$/i)
990
991                     {
992                         if ( $1 eq "F" ) {
993                             $fcount++;
994                         }
995                         else {
996                             $pcount++;
997                         }
998                     }
999                 }
1000                 close VER;
1001
1002                 unlink $vout;
1003                 if ( $fcount || $debug ) {
1004                     print STDERR "DEBUG: $tname, Pass=$pcount, Fail=$fcount\n";
1005                 }
1006                 if ( $fcount || !$pcount ) {
1007                     $scheckerr++;
1008                 }
1009                 else {
1010                     $scheckok++;
1011                 }
1012
1013             }
1014             elsif ( !cmp_file( $tname, $rsp, $out ) ) {
1015                 $cmperr++;
1016             }
1017             else {
1018                 $cmpok++;
1019             }
1020             unlink $out;
1021         }
1022     }
1023     if ($outfile ne "") {
1024         print OUT "\n\necho All Tests Completed\n" unless $minimal_script;
1025         close OUT;
1026     }
1027 }
1028
1029 sub cmp_file {
1030     my ( $tname, $rsp, $tst ) = @_;
1031     my ( $rspf,    $tstf );
1032     my ( $rspline, $tstline );
1033     if ( !open( $rspf, $rsp ) ) {
1034         print STDERR "ERROR: can't open request file $rsp\n";
1035         return 0;
1036     }
1037     if ( !open( $tstf, $tst ) ) {
1038         print STDERR "ERROR: can't open output file $tst\n";
1039         return 0;
1040     }
1041     for ( ; ; ) {
1042         $rspline = next_line($rspf);
1043         $tstline = next_line($tstf);
1044         if ( !defined($rspline) && !defined($tstline) ) {
1045             print STDERR "DEBUG: $tname file comparison OK\n" if $debug;
1046             return 1;
1047         }
1048         if ( !defined($rspline) ) {
1049             print STDERR "ERROR: $tname EOF on $rsp\n";
1050             return 0;
1051         }
1052         if ( !defined($tstline) ) {
1053             print STDERR "ERROR: $tname EOF on $tst\n";
1054             return 0;
1055         }
1056
1057         # Workaround for bug in RAND des2 test output */
1058         if ( $tstline =~ /^Key2 =/ && $rspline =~ /^Key1 =/ ) {
1059             $rspline =~ s/^Key1/Key2/;
1060         }
1061
1062         if ( $tstline ne $rspline ) {
1063             print STDERR "ERROR: $tname mismatch:\n";
1064             print STDERR "\t \"$tstline\" != \"$rspline\"\n";
1065             return 0;
1066         }
1067     }
1068     return 1;
1069 }
1070
1071 sub next_line {
1072     my ($in) = @_;
1073
1074     while (<$in>) {
1075         chomp;
1076
1077         # Delete comments
1078         s/#.*$//;
1079
1080         # Ignore blank lines
1081         next if (/^\s*$/);
1082
1083         # Translate multiple space into one
1084         s/\s+/ /g;
1085         # Delete trailing whitespace
1086         s/\s+$//;
1087         # Remove leading zeroes
1088         s/= 00/= /;
1089         # Translate to upper case
1090         return uc $_;
1091     }
1092     return undef;
1093 }