More DSA FIPS test suport.
[libgcrypt.git] / tests / cavs_driver.pl
1 #!/usr/bin/env perl
2 #
3 # $Id: cavs_driver.pl 1395 2008-11-10 15:18:03Z smueller $
4 #
5 # CAVS test driver (based on the OpenSSL driver)
6 # Written by: Stephan Müller <sm@atsec.com>
7 # Copyright (c) atsec information security corporation
8 #
9 # Permission is hereby granted, free of charge, to any person obtaining a copy
10 # of this software and associated documentation files (the "Software"), to deal
11 # in the Software without restriction, including without limitation the rights
12 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 # copies of the Software, and to permit persons to whom the Software is
14 # furnished to do so, subject to the following conditions: 
15 #
16 # The above copyright notice and this permission notice shall be included in
17 # all copies or substantial portions of the Software.
18 #
19 #                            NO WARRANTY
20 #
21 #    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
22 #    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
23 #    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
24 #    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
25 #    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 #    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
27 #    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
28 #    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
29 #    REPAIR OR CORRECTION.
30 #
31 #    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
32 #    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
33 #    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
34 #    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
35 #    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
36 #    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
37 #    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
38 #    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
39 #    POSSIBILITY OF SUCH DAMAGES.
40 #
41 #
42 # test execution instruction:
43 # 1. get the request files from the lab
44 # 2. call each request file from 1. with this program:
45 #       $0 <FILE>.rep
46 # 3. send the resulting file <FILE>.rsp to the lab
47 #
48 #
49 # Test should be easily adoptable to other implementations
50 # See the first functions for this task
51 #
52 # Following tests are covered (others may also be covered
53 # but have not been tested)
54 #
55 # AES
56 #       [CBC|CFB128|ECB|OFB]GFSbox[128|192|256]
57 #       [CBC|CFB128|ECB|OFB]MCT[128|192|256]
58 #       [CBC|CFB128|ECB|OFB]VarKey[128|192|256]
59 #       [CBC|CFB128|ECB|OFB]KeySbox[128|192|256]
60 #       [CBC|CFB128|ECB|OFB]MMT[128|192|256]
61 #       [CBC|CFB128|ECB|OFB]VarTxt[128|192|256]
62 #
63 # RSA
64 #       SigGen[15|RSA]
65 #       SigVer15
66 #       (SigVerRSA is not applicable for OpenSSL as X9.31 padding
67 #               is not done through openssl dgst)
68 #
69 # SHA
70 #       SHA[1|224|256|384|512]ShortMsg
71 #       SHA[1|224|256|384|512]LongMsg
72 #       SHA[1|224|256|384|512]Monte
73 #
74 # HMAC (SHA - caveat: we only support hash output equal to the block size of
75 #       of the hash - we do not support truncation of the hash; to support
76 #       that, we first need to decipher the HMAC.req file - see hmac_kat() )
77 #       HMAC
78 #
79 # TDES
80 #       T[CBC|CFB??|ECB|OFB]Monte[1|2|3]
81 #       T[CBC|CFB??|ECB|OFB]permop
82 #       T[CBC|CFB??|ECB|OFB]MMT[1|2|3]
83 #       T[CBC|CFB??|ECB|OFB]subtab
84 #       T[CBC|CFB??|ECB|OFB]varkey
85 #       T[CBC|CFB??|ECB|OFB]invperm
86 #       T[CBC|CFB??|ECB|OFB]vartext
87 #
88 # ANSI X9.31 RNG
89 #       ANSI931_AES128MCT
90 #       ANSI931_AES128VST
91 #
92 # DSA
93 #       PQGGen
94 #       SigGen
95 #       SigVer
96 #
97 # RC4 (atsec developed tests)
98 #       RC4KeyBD
99 #       RC4MCT
100 #       RC4PltBD
101 #       RC4REGT
102 #
103
104 use strict;
105 use warnings;
106 use IPC::Open2;
107 use Getopt::Std;
108 use MIME::Base64;
109
110 # Contains the command line options
111 my %opt;
112
113 #################################################################
114 ##### Central interface functions to the external ciphers #######
115 #################################################################
116 # Only these interface routines should be changed in case of
117 # porting to a new cipher library
118 #
119 # For porting to a new library, create implementation of these functions
120 # and then add pointers to the respective implementation of each
121 # function to the given variables.
122
123 # common encryption/decryption routine
124 # $1 key in hex form (please note for 3DES: even when ede3 for three
125 #    independent ciphers is given with the cipher specification, we hand in
126 #    either one key for k1 = k2 = k3, two keys which are concatinated for
127 #    k1 = k3, k2 independent, or three keys which are concatinated for
128 #    k1, k2, k3 independent)
129 # $2 iv in hex form
130 # $3 cipher - the cipher string is defined as specified in the openssl
131 #    enc(1ssl) specification for the option "-ciphername"
132 #    (e.g. aes-128-cbc or des-ede3-cbc)
133 # $4 encrypt=1/decrypt=0
134 # $5 de/encrypted data in hex form
135 # return en/decrypted data in hex form
136 my $encdec;
137
138 # Sign a message with RSA
139 # $1: data to be signed in hex form
140 # $2: Hash algo
141 # $3: Key file in PEM format with the private key
142 # return: digest in hex format
143 my $rsa_sign;
144
145 # Verify a message with RSA
146 # $1: data to be verified in hex form
147 # $2: hash algo
148 # $3: file holding the public RSA key in PEM format
149 # $4: file holding the signature in binary form
150 # return: 1 == verified / 0 == not verified
151 my $rsa_verify;
152
153 # generate a new private RSA key with the following properties:
154 #       exponent is 65537
155 #       PEM format
156 # $1 key size in bit
157 # $2 keyfile name
158 # return: nothing, but file created
159 my $gen_rsakey;
160
161 # Creating a hash
162 # $1: Plaintext in hex form
163 # $2: hash type in the form documented in openssl's dgst(1ssl) - e.g.
164 #     sha1, sha224, sha256, sha384, sha512
165 # return: hash in hex form
166 my $hash;
167
168 # supplying the call to the external cipher implementation
169 # that is being used to keep STDIN and STDOUT open
170 # to maintain the state of the block chaining
171 # $1: cipher
172 # $2: 1=encryption, 0=decryption
173 # $3: buffersize needed for openssl
174 # $4: encryption key in binary form
175 # $5: IV in binary form
176 # return: command line to execute the application
177 my $state_cipher;
178 # the only difference of the DES version is that it implements the inner loop
179 # of the TDES tests
180 my $state_cipher_des;
181
182 # supplying the call to the external cipher implementation
183 # that is being used to keep STDIN and STDOUT open
184 # to maintain the state of the RNG with its seed
185 #
186 # input holds seed values
187 # $1: cipher key in hex format
188 # $2: DT value in hex format
189 # $3: V value in hex format
190 #
191 # return: command line to execute the application
192 #
193 # the application is expected to deliver random values on STDOUT - the script
194 # reads 128 bits repeatedly where the state of the RNG must be retained
195 # between the reads. The output of the RNG on STDOUT is assumed to be binary.
196 my $state_rng;
197
198 # Generate an HMAC based on SHAx
199 # $1: Key to be used for the HMAC in hex format
200 # $2: length of the hash to be calculated in bits
201 # $3: Message for which the HMAC shall be calculated in hex format
202 # $4: hash type (1 - SHA1, 224 - SHA224, and so on)
203 # return: calculated HMAC in hex format
204 my $hmac;
205
206 #
207 # Generate the P, Q, G, Seed, counter, h (value used to generate g) values
208 # for DSA
209 # $1: modulus size
210 # return: string with the calculated values in hex format, where each value
211 #         is separated from the previous with a \n in the following order:
212 #         P\n
213 #         Q\n
214 #         G\n
215 #         Seed\n
216 #         counter\n
217 #         h
218 my $dsa_pqggen;
219
220 #
221 # Generate an DSA public key from the provided parameters:
222 # $1: Name of file to create
223 # $2: P in hex form
224 # $3: Q in hex form
225 # $4: G in hex form
226 # $5: Y in hex form  
227 my $dsa_genpubkey;
228
229
230 # Verify a message with DSA
231 # $1: data to be verified in hex form
232 # $2: file holding the public DSA key in PEM format
233 # $3: R value of the signature
234 # $4: S value of the signature
235 # return: 1 == verified / 0 == not verified
236 my $dsa_verify;
237
238 # generate a new DSA key with the following properties:
239 #       PEM format
240 # $1 keyfile name 
241 # return: file created, hash with keys of P, Q, G in hex format
242 my $gen_dsakey;
243
244 # Sign a message with DSA
245 # $1: data to be signed in hex form
246 # $2: Key file in PEM format with the private key
247 # return: hash of digest information in hex format with Y, R, S as keys
248 my $dsa_sign;
249
250 ################################################################
251 ##### OpenSSL interface functions
252 ################################################################
253 sub openssl_encdec($$$$$) {
254         my $key=shift;
255         my $iv=shift;
256         my $cipher=shift;
257         my $enc = (shift) ? "-e" : "-d";
258         my $data=shift;
259
260         # We only invoke the driver with the IV parameter, if we have
261         # an IV, otherwise, we skip it
262         $iv = "-iv $iv" if ($iv);
263
264         $data=hex2bin($data);
265         my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc $iv";
266         $program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given
267         $data=pipe_through_program($data,$program);
268         return bin2hex($data);
269 }
270
271 sub openssl_rsa_sign($$$) {
272         my $data = shift;
273         my $cipher = shift;
274         my $keyfile = shift;
275
276         $data=hex2bin($data);
277         die "ARCFOUR not available for RSA" if $opt{'R'};
278         $data=pipe_through_program($data,
279                 "openssl dgst -$cipher -binary -sign $keyfile");
280         return bin2hex($data);
281 }
282
283 sub openssl_rsa_verify($$$$) {
284         my $data = shift;
285         my $cipher = shift;
286         my $keyfile = shift;
287         my $sigfile = shift;
288
289         $data = hex2bin($data);
290         die "ARCFOUR not available for RSA" if $opt{'R'};
291         $data = pipe_through_program($data,
292                 "openssl dgst -$cipher -binary -verify $keyfile -signature $sigfile");
293
294         # Parse through the OpenSSL output information
295         return ($data =~ /OK/);
296 }
297
298 sub openssl_gen_rsakey($$) {
299         my $keylen = shift;
300         my $file = shift;
301
302         die "ARCFOUR not available for RSA" if $opt{'R'};
303         # generating of a key with exponent 0x10001
304         my @args = ("openssl", "genrsa", "-F4", "-out", "$file", "$keylen");
305         system(@args) == 0
306                 or die "system @args failed: $?";
307         die "system @args failed: file $file not created" if (! -f $file);
308 }
309
310 sub openssl_hash($$) {
311         my $pt = shift;
312         my $cipher = shift;
313
314         die "ARCFOUR not available for hashes" if $opt{'R'};
315         my $hash = hex2bin($pt);
316         #bin2hex not needed as the '-hex' already converts it
317         return pipe_through_program($hash, "openssl dgst -$cipher -hex");
318 }
319
320 sub openssl_state_cipher($$$$$) {
321         my $cipher = shift;
322         my $encdec = shift;
323         my $bufsize = shift;
324         my $key = shift;
325         my $iv = shift;
326
327         my $enc = $encdec ? "-e": "-d";
328
329         # We only invoke the driver with the IV parameter, if we have
330         # an IV, otherwise, we skip it
331         $iv = "-iv ".bin2hex($iv) if ($iv);
332
333         my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." $iv";
334         #for ARCFOUR, no IV must be given
335         $out = "rc4 -k " . bin2hex($key) if $opt{'R'};
336         return $out;
337 }
338
339 ###### End of OpenSSL interface implementation ############
340
341 ###########################################################
342 ###### libgcrypt implementation
343 ###########################################################
344 sub libgcrypt_encdec($$$$$) {
345         my $key=shift;
346         my $iv=shift;
347         my $cipher=shift;
348         my $enc = (shift) ? "encrypt" : "decrypt";
349         my $data=shift;
350
351         # We only invoke the driver with the IV parameter, if we have
352         # an IV, otherwise, we skip it
353         $iv = "--iv $iv" if ($iv);
354
355         my $program="fipsdrv --key $key $iv --algo $cipher $enc";
356
357         return pipe_through_program($data,$program);
358
359 }
360
361 sub libgcrypt_rsa_sign($$$) {
362         my $data = shift;
363         my $hashalgo = shift;
364         my $keyfile = shift;
365
366         die "ARCFOUR not available for RSA" if $opt{'R'};
367
368         return pipe_through_program($data,
369                 "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign");
370 }
371
372 sub libgcrypt_rsa_verify($$$$) {
373         my $data = shift;
374         my $hashalgo = shift;
375         my $keyfile = shift;
376         my $sigfile = shift;
377
378         die "ARCFOUR not available for RSA" if $opt{'R'};
379         $data = pipe_through_program($data,
380                 "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify");
381
382         # Parse through the output information
383         return ($data =~ /GOOD signature/);
384 }
385
386 sub libgcrypt_gen_rsakey($$) {
387         my $keylen = shift;
388         my $file = shift;
389
390         die "ARCFOUR not available for RSA" if $opt{'R'};
391         my @args = ("fipsdrv --keysize $keylen rsa-gen > $file");
392         system(@args) == 0
393                 or die "system @args failed: $?";
394         die "system @args failed: file $file not created" if (! -f $file);
395 }
396
397 sub libgcrypt_hash($$) {
398         my $pt = shift;
399         my $hashalgo = shift;
400
401         my $program = "fipsdrv --algo $hashalgo digest";
402         die "ARCFOUR not available for hashes" if $opt{'R'};
403
404         return pipe_through_program($pt, $program);
405 }
406
407 sub libgcrypt_state_cipher($$$$$) {
408         my $cipher = shift;
409         my $enc = (shift) ? "encrypt": "decrypt";
410         my $bufsize = shift;
411         my $key = shift;
412         my $iv = shift;
413
414         # We only invoke the driver with the IV parameter, if we have
415         # an IV, otherwise, we skip it
416         $iv = "--iv ".bin2hex($iv) if ($iv);
417
418         my $program="fipsdrv --binary --key ".bin2hex($key)." $iv --algo '$cipher' --chunk '$bufsize' $enc";
419
420         return $program;
421 }
422
423 sub libgcrypt_state_cipher_des($$$$$) {
424         my $cipher = shift;
425         my $enc = (shift) ? "encrypt": "decrypt";
426         my $bufsize = shift;
427         my $key = shift;
428         my $iv = shift;
429
430         # We only invoke the driver with the IV parameter, if we have
431         # an IV, otherwise, we skip it
432         $iv = "--iv ".bin2hex($iv) if ($iv);
433
434         my $program="fipsdrv --algo '$cipher' --mct-server $enc";
435
436         return $program;
437 }
438
439 sub libgcrypt_state_rng($$$) {
440         my $key = shift;
441         my $dt = shift;
442         my $v = shift;
443
444         return "fipsdrv --binary --loop --key $key --iv $v --dt $dt random";
445 }
446
447 sub libgcrypt_hmac($$$$) {
448         my $key = shift;
449         my $maclen = shift;
450         my $msg = shift;
451         my $hashtype = shift;
452
453         my $program = "fipsdrv --key $key --algo $hashtype hmac-sha";
454         return pipe_through_program($msg, $program);    
455 }
456
457 sub libgcrypt_dsa_pqggen($) {
458         my $mod = shift;
459
460         my $program = "fipsdrv --keysize $mod dsa-pqg-gen";
461         return pipe_through_program("", $program);
462 }
463
464 sub libgcrypt_gen_dsakey($) {
465         my $file = shift;
466
467         my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
468         my $tmp;
469         my %ret;
470
471         die "ARCFOUR not available for DSA" if $opt{'R'};
472
473         $tmp = pipe_through_program("", $program);
474         die "dsa key gen failed: file $file not created" if (! -f $file);
475
476         @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
477         return %ret;
478 }
479
480 sub libgcrypt_dsa_genpubkey($$$$$) {
481         my $filename = shift;
482         my $p = shift;
483         my $q = shift;
484         my $g = shift;
485         my $y = shift;
486
487         my $sexp;
488
489         $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))"; 
490
491         open(FH, ">", $filename) or die;
492         print FH $sexp;
493         close FH;  
494 }
495
496 sub libgcrypt_dsa_sign($$) {
497         my $data = shift;
498         my $keyfile = shift;
499         my $tmp;
500         my %ret; 
501         
502         die "ARCFOUR not available for DSA" if $opt{'R'};
503
504         $tmp = pipe_through_program($data, "fipsdrv --key $keyfile dsa-sign");
505         @ret{'Y', 'R', 'S'} = split(/\n/, $tmp);
506         return %ret;
507 }
508
509 sub libgcrypt_dsa_verify($$$$) {
510         my $data = shift;
511         my $keyfile = shift;
512         my $r = shift;
513         my $s = shift;
514         
515         my $ret;
516
517         die "ARCFOUR not available for DSA" if $opt{'R'};
518
519         my $sigfile = "$keyfile.sig";
520         open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
521         print FH "(sig-val(dsa(r #$r)(s #$s#)))";
522         close FH;
523
524         $ret = pipe_through_program($data, 
525                  "fipsdrv --verbose --key $keyfile --signature $sigfile dsa-verify");
526         unlink ($sigfile);
527         # Parse through the output information
528         return ($ret =~ /GOOD signature/);
529 }
530
531
532
533 ######### End of libgcrypt implementation ################
534
535 ################################################################
536 ###### Vendor1 interface functions
537 ################################################################
538
539 sub vendor1_encdec($$$$$) {
540         my $key=shift;
541         my $iv=shift;
542         my $cipher=shift;
543         my $enc = (shift) ? "encrypt" : "decrypt";
544         my $data=shift;
545
546         $data=hex2bin($data);
547         my $program = "./aes $enc $key";
548         $data=pipe_through_program($data,$program);
549         return bin2hex($data);
550 }
551
552 sub vendor1_state_cipher($$$$$) {
553         my $cipher = shift;
554         my $encdec = shift;
555         my $bufsize = shift;
556         my $key = shift;
557         my $iv = shift;
558
559         $key = bin2hex($key);
560         my $enc = $encdec ? "encrypt": "decrypt";
561         my $out = "./aes $enc $key $bufsize";
562         return $out;
563 }
564
565 ##### No other interface functions below this point ######
566 ##########################################################
567
568 ##########################################################
569 # General helper routines
570
571 # Executing a program by feeding STDIN and retrieving
572 # STDOUT
573 # $1: data string to be piped to the app on STDIN
574 # rest: program and args
575 # returns: STDOUT of program as string
576 sub pipe_through_program($@) {
577         my $in = shift;
578         my @args = @_;
579
580         my ($CO, $CI);
581         my $pid = open2($CO, $CI, @args);
582         
583         my $out = "";
584         my $len = length($in);
585         my $first = 1;
586         while (1) {
587                 my $rin = "";
588                 my $win = "";
589                 # Output of prog is FD that we read
590                 vec($rin,fileno($CO),1) = 1;
591                 # Input of prog is FD that we write
592                 # check for $first is needed because we can have NULL input
593                 # that is to be written to the app
594                 if ( $len > 0 || $first) {
595                         (vec($win,fileno($CI),1) = 1);
596                         $first=0;
597                 }
598                 # Let us wait for 100ms
599                 my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
600                 if ( $wout ) {
601                         my $written = syswrite($CI, $in, $len);
602                         die "broken pipe" if !defined $written;
603                         $len -= $written;
604                         substr($in, 0, $written) = "";
605                         if ($len <= 0) {
606                                 close $CI or die "broken pipe: $!";
607                         }
608                 }
609                 if ( $rout ) {
610                         my $tmp_out = "";
611                         my $bytes_read = sysread($CO, $tmp_out, 4096);
612                         $out .= $tmp_out;
613                         last if ($bytes_read == 0);
614                 }
615         }
616         close $CO or die "broken pipe: $!";
617         waitpid $pid, 0;
618         
619         return $out;
620 }
621
622 #
623 # convert ASCII hex to binary input
624 # $1 ASCII hex
625 # return binary representation
626 sub hex2bin($) {
627         my $in = shift;
628         my $len = length($in);
629         $len = 0 if ($in eq "00");
630         return pack("H$len", "$in");
631 }
632
633 #
634 # convert binary input to ASCII hex
635 # $1 binary value
636 # return ASCII hex representation
637 sub bin2hex($) {
638         my $in = shift;
639         my $len = length($in)*2;
640         return unpack("H$len", "$in");
641 }
642
643 # $1: binary byte (character)
644 # returns: binary byte with odd parity using low bit as parity bit
645 sub odd_par($) {
646         my $in = ord(shift);
647         my $odd_count=0;
648         for(my $i=1; $i<8; $i++) {
649                 $odd_count++ if ($in & (1<<$i));
650         }
651
652         my $out = $in;
653         if ($odd_count & 1) { # check if parity is already odd
654                 $out &= ~1; # clear the low bit
655         } else {
656                 $out |= 1; # set the low bit
657         }
658
659         return chr($out);
660 }
661
662 # DES keys uses only the 7 high bits of a byte, the 8th low bit
663 # is the parity bit
664 # as the new key is calculated from oldkey XOR cipher in the MCT test,
665 # the parity is not really checked and needs to be set to match
666 # expectation (OpenSSL does not really care, but the FIPS
667 # test result is expected that the key has the appropriate parity)
668 # $1: arbitrary binary string
669 # returns: string with odd parity set in low bit of each byte
670 sub fix_key_parity($) {
671         my $in = shift;
672         my $out = "";
673         for (my $i = 0; $i < length($in); $i++) {
674                 $out .= odd_par(substr($in, $i, 1));
675         }
676
677         return $out;
678 }
679
680 ####################################################
681 # DER/PEM utility functions
682 # Cf. http://www.columbia.edu/~ariel/ssleay/layman.html
683
684 # Convert unsigned integer to base256 bigint bytes
685 # $1 integer
686 # returns base256 octet string
687 sub int_base256_unsigned($) {
688         my $n = shift;
689
690         my $out = chr($n & 255);
691         while ($n>>=8) {
692                 $out = chr($n & 255) . $out;
693         }
694
695         return $out;
696 }
697
698 # Convert signed integer to base256 bigint bytes
699 # $1 integer
700 # returns base256 octet string
701 sub int_base256_signed($) {
702         my $n = shift;
703         my $negative = ($n < 0);
704
705         if ($negative) {
706                 $n = -$n-1;
707         }
708
709         my $out = int_base256_unsigned($n);
710
711         if (ord(substr($out, 0, 1)) & 128) {
712                 # it's supposed to be positive but has sign bit set,
713                 # add a leading zero
714                 $out = chr(0) . $out;
715         }
716
717         if ($negative) {
718                 my $neg = chr(255) x length($out);
719                 $out ^= $neg;
720         }
721
722         return $out;
723 }
724
725 # Length header for specified DER object length
726 # $1 length as integer
727 # return octet encoding for length
728 sub der_len($) {
729         my $len = shift;
730
731         if ($len <= 127) {
732                 return chr($len);
733         } else {
734                 my $blen = int_base256_unsigned($len);
735
736                 return chr(128 | length($blen)) . $blen;
737         }
738 }
739
740 # Prepend length header to object
741 # $1 object as octet sequence
742 # return length header for object followed by object as octets
743 sub der_len_obj($) {
744         my $x = shift;
745
746         return der_len(length($x)) . $x;
747 }
748
749 # DER sequence
750 # $* objects
751 # returns DER sequence consisting of the objects passed as arguments
752 sub der_seq {
753         my $seq = join("", @_);
754         return chr(0x30) . der_len_obj($seq);
755 }
756
757 # DER bitstring
758 # $1 input octets (must be full octets, fractional octets not supported)
759 # returns input encapsulated as bitstring
760 sub der_bitstring($) {
761         my $x = shift;
762
763         $x = chr(0) . $x;
764
765         return chr(0x03) . der_len_obj($x);
766 }
767
768 # base-128-encoded integer, used for object numbers.
769 # $1 integer
770 # returns octet sequence
771 sub der_base128($) {
772         my $n = shift;
773
774         my $out = chr($n & 127);
775
776         while ($n>>=7) {
777                 $out = chr(128 | ($n & 127)) . $out;
778         }
779
780         return $out;
781 }
782
783 # Generating the PEM certificate string
784 # (base-64-encoded DER string)
785 # $1 DER string
786 # returns octet sequence
787 sub pem_cert($) {
788         my $n = shift;
789
790         my $out = "-----BEGIN PUBLIC KEY-----\n";
791         $out .= encode_base64($n);
792         $out .= "-----END PUBLIC KEY-----\n";
793
794         return $out;
795 }
796
797 # DER object identifier
798 # $* sequence of id numbers
799 # returns octets
800 sub der_objectid {
801         my $v1 = shift;
802         my $v2 = shift;
803
804         my $out = chr(40*$v1 + $v2) . join("", map { der_base128($_) } @_);
805
806         return chr(0x06) . der_len_obj($out);
807 }
808
809 # DER signed integer
810 # $1 number as octet string (base 256 representation, high byte first)
811 # returns number in DER integer encoding
812 sub der_bigint($) {
813         my $x = shift;
814
815         return chr(0x02) . der_len_obj($x);
816 }
817
818 # DER positive integer with leading zeroes stripped
819 # $1 number as octet string (base 256 representation, high byte first)
820 # returns number in DER integer encoding
821 sub der_pos_bigint($) {
822         my $x = shift;
823
824         # strip leading zero digits
825         $x =~ s/^[\0]+//;
826
827         # need to prepend a zero if high bit set, since it would otherwise be
828         # interpreted as a negative number. Also needed for number 0.
829         if (!length($x) || ord(substr($x, 0, 1)) >= 128) {
830                 $x = chr(0) . $x;
831         }
832
833         return der_bigint($x);
834 }
835
836 # $1 number as signed integer
837 # returns number as signed DER integer encoding
838 sub der_int($) {
839         my $n = shift;
840         
841         return der_bigint(int_base256_signed($n));
842 }
843
844 # the NULL object constant
845 sub der_null() {
846         return chr(0x05) . chr(0x00);
847 }
848
849 # Unit test helper
850 # $1 calculated result
851 # $2 expected result
852 # no return value, dies if results differ, showing caller's line number
853 sub der_test($$) {
854         my $actual = bin2hex(shift);
855         my $expected = shift;
856
857         my @caller = caller;
858         $actual eq $expected or die "Error:line $caller[2]:assertion failed: "
859                 ."$actual != $expected\n";
860 }
861
862 # Unit testing for the DER encoding functions
863 # Examples from http://www.columbia.edu/~ariel/ssleay/layman.html
864 # No input, no output. Dies if unit tests fail.
865 sub der_unit_test {
866         ## uncomment these if you want to test the test framework
867         #print STDERR "Unit test running\n";
868         #der_test chr(0), "42";
869
870         der_test der_null, "0500";
871
872         # length bytes
873         der_test der_len(1), "01";
874         der_test der_len(127), "7f";
875         der_test der_len(128), "8180";
876         der_test der_len(256), "820100";
877         der_test der_len(65536), "83010000";
878
879         # bigint
880         der_test der_bigint(chr(0)), "020100";
881         der_test der_bigint(chr(128)), "020180"; # -128
882         der_test der_pos_bigint(chr(128)), "02020080"; # +128
883         der_test der_pos_bigint(chr(0).chr(0).chr(1)), "020101";
884         der_test der_pos_bigint(chr(0)), "020100";
885
886         # integers (tests base256 conversion)
887         der_test der_int(     0), "020100";
888         der_test der_int(   127), "02017f";
889         der_test der_int(   128), "02020080";
890         der_test der_int(   256), "02020100";
891         der_test der_int(    -1), "0201ff";
892         der_test der_int(  -128), "020180";
893         der_test der_int(  -129), "0202ff7f";
894         der_test der_int(-65536), "0203ff0000";
895         der_test der_int(-65537), "0203feffff";
896
897         # object encoding, "RSA Security"
898         der_test der_base128(840), "8648";
899         der_test der_objectid(1, 2, 840, 113549), "06062a864886f70d";
900
901         # Combinations
902         der_test der_bitstring("ABCD"), "03050041424344";
903         der_test der_bitstring(der_null), "0303000500";
904         der_test der_seq(der_int(0), der_null), "30050201000500";
905
906         # The big picture
907         der_test der_seq(der_seq(der_objectid(1, 2, 840, 113549), der_null),
908                          der_bitstring(der_seq(der_pos_bigint(chr(5)),
909                                                der_pos_bigint(chr(3))))),
910                  "3017300a06062a864886f70d05000309003006020105020103";
911 }
912
913 ####################################################
914 # OpenSSL missing functionality workarounds
915
916 ## Format of an RSA public key:
917 #    0:d=0  hl=3 l= 159 cons: SEQUENCE          
918 #    3:d=1  hl=2 l=  13 cons:  SEQUENCE          
919 #    5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
920 #   16:d=2  hl=2 l=   0 prim:   NULL              
921 #   18:d=1  hl=3 l= 141 prim:  BIT STRING        
922 #                              [ sequence: INTEGER (n), INTEGER (e) ]
923
924 # generate RSA pub key in PEM format
925 # $1: filename where PEM key is to be stored
926 # $2: n of the RSA key in hex
927 # $3: e of the RSA key in hex
928 # return: nothing, but file created
929 sub gen_pubrsakey($$$) {
930         my $filename=shift;
931         my $n = shift;
932         my $e = shift;
933
934         # make sure the DER encoder works ;-)
935         der_unit_test();
936
937         # generate DER encoding of the public key
938
939         my $rsaEncryption = der_objectid(1, 2, 840, 113549, 1, 1, 1);
940
941         my $der = der_seq(der_seq($rsaEncryption, der_null),
942                           der_bitstring(der_seq(der_pos_bigint(hex2bin($n)),
943                                                 der_pos_bigint(hex2bin($e)))));
944
945         open(FH, ">", $filename) or die;
946         print FH pem_cert($der);
947         close FH;
948
949 }
950
951 # generate RSA pub key in PEM format
952 #
953 # This implementation uses "openssl asn1parse -genconf" which was added
954 # in openssl 0.9.8. It is not available in older openssl versions.
955 #
956 # $1: filename where PEM key is to be stored
957 # $2: n of the RSA key in hex
958 # $3: e of the RSA key in hex
959 # return: nothing, but file created
960 sub gen_pubrsakey_using_openssl($$$) {
961         my $filename=shift;
962         my $n = shift;
963         my $e = shift;
964
965         my $asn1 = "asn1=SEQUENCE:pubkeyinfo
966
967 [pubkeyinfo]
968 algorithm=SEQUENCE:rsa_alg
969 pubkey=BITWRAP,SEQUENCE:rsapubkey
970
971 [rsa_alg]
972 algorithm=OID:rsaEncryption
973 parameter=NULL
974
975 [rsapubkey]
976 n=INTEGER:0x$n
977
978 e=INTEGER:0x$e";
979
980         open(FH, ">$filename.cnf") or die "Cannot create file $filename.cnf: $?";
981         print FH $asn1;
982         close FH;
983         my @args = ("openssl", "asn1parse", "-genconf", "$filename.cnf", "-noout", "-out", "$filename.der");
984         system(@args) == 0 or die "system @args failed: $?";
985         @args = ("openssl", "rsa", "-inform", "DER", "-in", "$filename.der",
986                  "-outform", "PEM", "-pubin", "-pubout", "-out", "$filename");
987         system(@args) == 0 or die "system @args failed: $?";
988         die "RSA PEM formatted key file $filename was not created"
989                 if (! -f $filename);
990
991         unlink("$filename.cnf");
992         unlink("$filename.der");
993 }
994
995 ############################################
996 # Test cases
997
998 # This is the Known Answer Test
999 # $1: the string that we have to put in front of the key
1000 #     when printing the key
1001 # $2: crypto key1 in hex form
1002 # $3: crypto key2 in hex form (TDES, undef otherwise)
1003 # $4: crypto key3 in hex form (TDES, undef otherwise)
1004 # $5: IV in hex form
1005 # $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
1006 # $7: cipher
1007 # $8: encrypt=1/decrypt=0
1008 # return: string formatted as expected by CAVS
1009 sub kat($$$$$$$$) {
1010         my $keytype = shift;
1011         my $key1 = shift;
1012         my $key2 = shift;
1013         my $key3 = shift;
1014         my $iv = shift;
1015         my $pt = shift;
1016         my $cipher = shift;
1017         my $enc = shift;
1018
1019         my $out = "";
1020
1021         $out .= "$keytype = $key1\n";
1022
1023         # this is the concardination of the keys for 3DES
1024         if (defined($key2)) {
1025                 $out .= "KEY2 = $key2\n";
1026                 $key1 = $key1 . $key2;
1027         }
1028         if (defined($key3)) {
1029                 $out .= "KEY3 = $key3\n";
1030                 $key1= $key1 . $key3;
1031         }
1032         
1033         $out .= "IV = $iv\n" if (defined($iv) && $iv ne "");
1034         if ($enc) {
1035                 $out .= "PLAINTEXT = $pt\n";
1036                 $out .= "CIPHERTEXT = " . &$encdec($key1, $iv, $cipher, 1, $pt) . "\n";
1037         } else {
1038                 $out .= "CIPHERTEXT = $pt\n";
1039                 $out .= "PLAINTEXT = " . &$encdec($key1, $iv, $cipher, 0, $pt) . "\n";
1040         }
1041
1042         return $out;
1043 }
1044
1045 # This is the Known Answer Test for Hashes
1046 # $1: Plaintext in hex form
1047 # $2: hash
1048 # $3: hash length (undef if not applicable)
1049 # return: string formatted as expected by CAVS
1050 sub hash_kat($$$) {
1051         my $pt = shift;
1052         my $cipher = shift;
1053         my $len = shift;
1054
1055         my $out = "";
1056         $out .= "Len = $len\n" if (defined($len));
1057         $out .= "Msg = $pt\n";
1058
1059         $pt = "" if(!$len);
1060         $out .= "MD = " . &$hash($pt, $cipher) . "\n";
1061         return $out;
1062 }
1063
1064 # Known Answer Test for HMAC hash
1065 # $1: key length in bytes
1066 # $2: MAC length in bytes
1067 # $3: key for HMAC in hex form
1068 # $4: message to be hashed
1069 # return: string formatted as expected by CAVS
1070 sub hmac_kat($$$$) {
1071         my $klen = shift;
1072         my $tlen = shift;
1073         my $key  = shift;
1074         my $msg  = shift;
1075
1076         # XXX this is a hack - we need to decipher the HMAC REQ files in a more
1077         # sane way
1078         #
1079         # This is a conversion table from the expected hash output size
1080         # to the assumed hash type - we only define here the block size of
1081         # the underlying hashes and do not allow any truncation
1082         my %hashtype = (
1083                 20 => 1,
1084                 28 => 224,
1085                 32 => 256,
1086                 48 => 384,
1087                 64 => 512
1088         );
1089
1090         die "Hash output size $tlen is not supported!"
1091                 if(!defined($hashtype{$tlen}));
1092
1093         my $out = "";
1094         $out .= "Klen = $klen\n";
1095         $out .= "Tlen = $tlen\n";
1096         $out .= "Key = $key\n";
1097         $out .= "Msg = $msg\n";
1098         $out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n\n";
1099
1100         return $out;
1101 }
1102
1103
1104 # Cipher Monte Carlo Testing
1105 # $1: the string that we have to put in front of the key
1106 #     when printing the key
1107 # $2: crypto key1 in hex form
1108 # $3: crypto key2 in hex form (TDES, undef otherwise)
1109 # $4: crypto key3 in hex form (TDES, undef otherwise)
1110 # $5: IV in hex form
1111 # $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
1112 # $7: cipher
1113 # $8: encrypt=1/decrypt=0
1114 # return: string formatted as expected by CAVS
1115 sub crypto_mct($$$$$$$$) {
1116         my $keytype = shift;
1117         my $key1 = hex2bin(shift);
1118         my $key2 = shift;
1119         my $key3 = shift;
1120         my $iv = hex2bin(shift);
1121         my $source_data = hex2bin(shift);
1122         my $cipher = shift;
1123         my $enc = shift;
1124
1125         my $out = "";
1126
1127         $key2 = hex2bin($key2) if (defined($key2));
1128         $key3 = hex2bin($key3) if (defined($key3));
1129         my $bufsize = length($source_data);
1130
1131         # for AES: outer loop 0-99, inner 0-999 based on FIPS compliance tests
1132         # for RC4: outer loop 0-99, inner 0-999 based on atsec compliance tests
1133         # for DES: outer loop 0-399, inner 0-9999 based on FIPS compliance tests
1134         my $ciph = substr($cipher,0,3);
1135         my $oloop=100;
1136         my $iloop=1000;
1137         if ($ciph =~ /des/) {$oloop=400;$iloop=10000;}
1138
1139         for (my $i=0; $i<$oloop; ++$i) {
1140                 $out .= "COUNT = $i\n";
1141                 if (defined($key2)) {
1142                         $out .= "$keytype = ". bin2hex($key1). "\n";
1143                         $out .= "KEY2 = ". bin2hex($key2). "\n";
1144                         $key1 = $key1 . $key2;
1145                 } else {
1146                         $out .= "$keytype = ". bin2hex($key1). "\n";
1147                 }
1148                 if(defined($key3)) {
1149                         $out .= "KEY3 = ". bin2hex($key3). "\n";
1150                         $key1 = $key1 . $key3;
1151                 }
1152                 my $keylen = length($key1);
1153
1154                 $out .= "IV = ". bin2hex($iv) . "\n"
1155                         if (defined($iv) && $iv ne "");
1156
1157                 if ($enc) {
1158                         $out .= "PLAINTEXT = ". bin2hex($source_data). "\n";
1159                 } else {
1160                         $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n";
1161                 }
1162                 my ($CO, $CI);
1163                 my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
1164                 $cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/);
1165                 my $pid = open2($CO, $CI, $cipher_imp);
1166
1167                 my $calc_data = $iv; # CT[j]
1168                 my $old_calc_data; # CT[j-1]
1169                 my $old_old_calc_data; # CT[j-2]
1170                 my $next_source;
1171
1172                 # TDES inner loop implements logic within driver
1173                 if ($cipher =~ /des/) {
1174                         print $CI "1\n"
1175                                   .$iloop."\n"
1176                                   .bin2hex($key1)."\n"
1177                                   .bin2hex($iv)."\n"
1178                                   .bin2hex($source_data)."\n\n" or die;
1179                         chomp(my $line = <$CO>);
1180                         $calc_data = hex2bin($line);
1181                         chomp($line = <$CO>);
1182                         $old_calc_data = hex2bin($line);
1183                         chomp($line = <$CO>);
1184                         $old_old_calc_data = hex2bin($line);
1185                         chomp($line = <$CO>);
1186                         $iv = hex2bin($line);
1187                         chomp($line = <$CO>);
1188                         $next_source = hex2bin($line);
1189                         # Skip over empty line.
1190                         $line = <$CO>;
1191                 } else {
1192                         for (my $j = 0; $j < $iloop; ++$j) {
1193                                 $old_old_calc_data = $old_calc_data;
1194                                 $old_calc_data = $calc_data;
1195
1196                                 #print STDERR "source_data=", bin2hex($source_data), "\n";
1197                                 syswrite $CI, $source_data or die $!;
1198                                 my $len = sysread $CO, $calc_data, $bufsize;
1199
1200                                 #print STDERR "len=$len, bufsize=$bufsize\n";
1201                                 die if $len ne $bufsize;
1202                                 #print STDERR "calc_data=", bin2hex($calc_data), "\n";
1203
1204                                 if ( (!$enc && $ciph =~ /des/) ||
1205                                      $ciph =~ /rc4/ || 
1206                                      $cipher =~ /ecb/ ) {
1207                                         #TDES in decryption mode, RC4 and ECB mode
1208                                         #have a special rule
1209                                         $source_data = $calc_data;
1210                                 } else {
1211                                         $source_data = $old_calc_data;
1212                                 }
1213                         }
1214                 }
1215                 close $CO;
1216                 close $CI;
1217                 waitpid $pid, 0;
1218
1219                 if ($enc) {
1220                         $out .= "CIPHERTEXT = ". bin2hex($calc_data). "\n\n";
1221                 } else {
1222                         $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n";
1223                 }
1224                 
1225                 if ( $ciph =~ /aes/ ) {
1226                         $key1 ^= substr($old_calc_data . $calc_data, -$keylen);
1227                         #print STDERR bin2hex($key1)."\n";
1228                 } elsif ( $ciph =~ /des/ ) {
1229                         die "Wrong keylen $keylen" if ($keylen != 24);
1230
1231                         # $nkey needed as $key holds the concatenation of the
1232                         # old key atm
1233                         my $nkey = fix_key_parity(substr($key1,0,8) ^ $calc_data);
1234                         #print STDERR "KEY1 = ". bin2hex($nkey)."\n";
1235                         if (substr($key1,0,8) ne substr($key1,8,8)) {
1236                                 #print STDERR "KEY2 recalc: KEY1==KEY3, KEY2 indep. or all KEYs are indep.\n";
1237                                 $key2 = fix_key_parity((substr($key1,8,8) ^ $old_calc_data));
1238                         } else {
1239                                 #print STDERR "KEY2 recalc: KEY1==KEY2==KEY3\n";
1240                                 $key2 = fix_key_parity((substr($key1,8,8) ^ $calc_data));
1241                         }
1242                         #print STDERR "KEY2 = ". bin2hex($key2)."\n";
1243                         if ( substr($key1,0,8) eq substr($key1,16)) {
1244                                 #print STDERR "KEY3 recalc: KEY1==KEY2==KEY3 or KEY1==KEY3, KEY2 indep.\n";
1245                                 $key3 = fix_key_parity((substr($key1,16) ^ $calc_data));
1246                         } else {
1247                                 #print STDERR "KEY3 recalc: all KEYs are independent\n";
1248                                 $key3 = fix_key_parity((substr($key1,16) ^ $old_old_calc_data));
1249                         }
1250                         #print STDERR "KEY3 = ". bin2hex($key3)."\n";
1251
1252                         # reset the first key - concardination happens at
1253                         # beginning of loop
1254                         $key1=$nkey;
1255                 } elsif ($ciph =~ /rc4/ ) {
1256                         $key1 ^= substr($calc_data, 0, 16);
1257                         #print STDERR bin2hex($key1)."\n";
1258                 } else {
1259                         die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing";
1260                 }
1261
1262                 if ($cipher =~ /des-ede3-ofb/) {
1263                         $source_data = $source_data ^ $next_source;
1264                 } elsif (!$enc && $cipher =~ /des-ede3-cfb/) {
1265                         #TDES decryption CFB has a special rule
1266                         $source_data = $next_source;
1267                 } elsif (! $enc && $ciph =~ /des/ ) {
1268                         #TDES in decryption mode has a special rule
1269                         $iv = $old_calc_data;
1270                         $source_data = $calc_data;
1271                 } elsif ( $ciph =~ /rc4/ || $cipher =~ /ecb/ ) {
1272                         #No resetting of IV as the IV is all zero set initially (i.e. no IV)
1273                         $source_data = $calc_data;
1274                 } else {
1275                         $iv = $calc_data;
1276                         $source_data = $old_calc_data;
1277                 }
1278         }
1279
1280         return $out;
1281 }
1282
1283 # Hash Monte Carlo Testing
1284 # $1: Plaintext in hex form
1285 # $2: hash
1286 # return: string formatted as expected by CAVS
1287 sub hash_mct($$) {
1288         my $pt = shift;
1289         my $cipher = shift;
1290
1291         my $out = "";
1292
1293         $out .= "Seed = $pt\n\n";
1294
1295         for (my $j=0; $j<100; ++$j) {
1296                 $out .= "COUNT = $j\n";
1297                 my $md0=$pt;
1298                 my $md1=$pt;
1299                 my $md2=$pt;
1300                 for (my $i=0; $i<1000; ++$i) {
1301                         #print STDERR "outer loop $j; inner loop $i\n";
1302                         my $mi= $md0 . $md1 . $md2;
1303                         $md0=$md1;
1304                         $md1=$md2;
1305                         $md2 = &$hash($mi, $cipher);
1306                         $md2 =~ s/\n//;
1307                 }
1308                 $out .= "MD = $md2\n\n";
1309                 $pt=$md2;
1310         }
1311
1312         return $out;
1313 }
1314
1315 # RSA SigGen test
1316 # $1: Message to be signed in hex form
1317 # $2: Hash algorithm
1318 # $3: file name with RSA key in PEM form
1319 # return: string formatted as expected by CAVS
1320 sub rsa_siggen($$$) {
1321         my $data = shift;
1322         my $cipher = shift;
1323         my $keyfile = shift;
1324
1325         my $out = "";
1326
1327         $out .= "SHAAlg = $cipher\n";
1328         $out .= "Msg = $data\n";
1329         $out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n";
1330
1331         return $out;
1332 }
1333
1334 # RSA SigVer test
1335 # $1: Message to be verified in hex form
1336 # $2: Hash algoritm
1337 # $3: Signature of message in hex form
1338 # $4: n of the RSA key in hex in hex form
1339 # $5: e of the RSA key in hex in hex form
1340 # return: string formatted as expected by CAVS
1341 sub rsa_sigver($$$$$) {
1342         my $data = shift;
1343         my $cipher = shift;
1344         my $signature = shift;
1345         my $n = shift;
1346         my $e = shift;
1347
1348         my $out = "";
1349
1350         $out .= "SHAAlg = $cipher\n";
1351         $out .= "e = $e\n";
1352         $out .= "Msg = $data\n";
1353         $out .= "S = $signature\n";
1354
1355         # XXX maybe a secure temp file name is better here
1356         # but since it is not run on a security sensitive
1357         # system, I hope that this is fine
1358         my $keyfile = "rsa_sigver.tmp.$$";
1359         gen_pubrsakey($keyfile, $n, $e);
1360
1361         my $sigfile = "$keyfile.sig";
1362         open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
1363         print FH hex2bin($signature);
1364         close FH;
1365
1366         $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n");
1367
1368         unlink($keyfile);
1369         unlink($sigfile);
1370
1371         return $out;
1372 }
1373
1374 # X9.31 RNG test
1375 # $1 key for the AES cipher
1376 # $2 DT value
1377 # $3 V value
1378 # $4 type ("VST", "MCT")
1379 # return: string formatted as expected by CAVS
1380 sub rngx931($$$$) {
1381         my $key=shift;
1382         my $dt=shift;
1383         my $v=shift;
1384         my $type=shift;
1385
1386         my $out = "Key = $key\n";
1387         $out   .= "DT = $dt\n";
1388         $out   .= "V = $v\n";
1389
1390         my $count = 1;
1391         $count = 10000 if ($type eq "MCT");
1392
1393         my $rnd_val = "";
1394
1395         # we read 16 bytes from RNG
1396         my $bufsize = 16;
1397
1398         my ($CO, $CI);
1399         my $rng_imp = &$state_rng($key, $dt, $v);
1400         my $pid = open2($CO, $CI, $rng_imp);
1401         for (my $i = 0; $i < $count; ++$i) {
1402                 my $len = sysread $CO, $rnd_val, $bufsize;
1403                 #print STDERR "len=$len, bufsize=$bufsize\n";
1404                 die "len=$len != bufsize=$bufsize" if $len ne $bufsize;
1405                 #print STDERR "calc_data=", bin2hex($rnd_val), "\n";
1406         }
1407         close $CO;
1408         close $CI;
1409         waitpid $pid, 0;
1410
1411         $out .= "R = " . bin2hex($rnd_val) . "\n\n";
1412
1413         return $out;
1414 }
1415
1416 # DSA PQGGen test
1417 # $1 modulus size
1418 # $2 number of rounds to perform the test
1419 # return: string formatted as expected by CAVS
1420 sub dsa_pqggen_driver($$) {
1421         my $mod = shift;
1422         my $rounds = shift;
1423
1424         my $out = "";
1425         for(my $i=0; $i<$rounds; $i++) {
1426                 my $ret = &$dsa_pqggen($mod);
1427                 my ($P, $Q, $G, $Seed, $c, $H) = split(/\n/, $ret);
1428                 die "Return value does not contain all expected values of P, Q, G, Seed, c, H for dsa_pqggen"
1429                         if (!defined($P) || !defined($Q) || !defined($G) ||
1430                             !defined($Seed) || !defined($c) || !defined($H));
1431                 $out .= "P = $P\n";
1432                 $out .= "Q = $Q\n";
1433                 $out .= "G = $G\n";
1434                 $out .= "Seed = $Seed\n";
1435                 $out .= "c = $c\n";
1436                 $out .= "H = $H\n\n";
1437         }
1438
1439         return $out;
1440 }
1441
1442
1443 # DSA SigGen test
1444 # $1: Message to be signed in hex form
1445 # $2: file name with DSA key in PEM form
1446 # return: string formatted as expected by CAVS
1447 sub dsa_siggen($$) {
1448         my $data = shift;
1449         my $keyfile = shift;
1450
1451         my $out = "";
1452
1453         my %ret = &$dsa_sign($data, $keyfile);
1454
1455         $out .= "Msg = $data\n";
1456         $out .= "Y = " . $ret{'Y'} . "\n";
1457         $out .= "R = " . $ret{'R'} . "\n";
1458         $out .= "S = " . $ret{'S'} . "\n";
1459
1460         return $out;
1461 }
1462
1463
1464 # DSA signature verification
1465 # $1 modulus
1466 # $2 P
1467 # $3 Q
1468 # $4 G
1469 # $5 Y - public key
1470 # $6 r
1471 # $7 s
1472 # $8 message to be verified
1473 # return: string formatted as expected by CAVS
1474 sub dsa_sigver($$$$$$$$) {
1475         my $modulus = shift;
1476         my $p = shift;
1477         my $q = shift;
1478         my $g = shift;
1479         my $y = shift;
1480         my $r = shift;
1481         my $s = shift;
1482         my $msg = shift;
1483
1484         my $out = "";
1485
1486         #PQG are already printed - do not print them here
1487
1488         $out .= "Msg = $msg\n";
1489         $out .= "Y = $y\n";
1490         $out .= "R = $r\n";
1491         $out .= "S = $s\n";
1492
1493         # XXX maybe a secure temp file name is better here
1494         # but since it is not run on a security sensitive
1495         # system, I hope that this is fine
1496         my $keyfile = "dsa_sigver.tmp.$$";
1497         &dsa_genpubkey($keyfile, $p, $q, $g, $y);
1498
1499         $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n");
1500
1501         unlink($keyfile);
1502
1503         return $out;
1504 }
1505
1506 ##############################################################
1507 # Parser of input file and generator of result file
1508 #
1509
1510 sub usage() {
1511
1512         print STDERR "Usage:
1513 $0 [-R] [-D] [-I name] <CAVS-test vector file>
1514
1515 -R      execution of ARCFOUR instead of OpenSSL
1516 -I NAME Use interface style NAME:
1517                 openssl     OpenSSL (default)
1518                 libgcrypt   Libgcrypt
1519 -D      SigGen and SigVer are executed with DSA
1520         Please note that the DSA CAVS vectors do not allow distinguishing
1521         them from the RSA vectors. As the RSA test is the default, you have
1522         to supply this option to apply the DSA logic";
1523 }
1524
1525 # Parser of CAVS test vector file
1526 # $1: Test vector file
1527 # $2: Output file for test results
1528 # return: nothing
1529 sub parse($$) {
1530         my $infile = shift;
1531         my $outfile = shift;
1532
1533         my $out = "";
1534
1535         # this is my cipher/hash type
1536         my $cipher = "";
1537
1538         # Test type
1539         # 1 - cipher known answer test
1540         # 2 - cipher Monte Carlo test
1541         # 3 - hash known answer test
1542         # 4 - hash Monte Carlo test
1543         # 5 - RSA signature generation
1544         # 6 - RSA signature verification
1545         my $tt = 0;
1546
1547         # Variables for tests
1548         my $keytype = ""; # we can have "KEY", "KEYs", "KEY1"
1549         my $key1 = "";
1550         my $key2 = undef; #undef needed for allowing
1551         my $key3 = undef; #the use of them as input variables
1552         my $pt = "";
1553         my $enc = 1;
1554         my $iv = "";
1555         my $len = undef; #see key2|3
1556         my $n = "";
1557         my $e = "";
1558         my $signature = "";
1559         my $rsa_keyfile = "";
1560         my $dsa_keyfile = "";
1561         my $dt = "";
1562         my $v = "";
1563         my $klen = "";
1564         my $tlen = "";
1565         my $modulus = "";
1566         my $capital_n = 0;
1567         my $capital_p = "";
1568         my $capital_q = "";
1569         my $capital_g = "";
1570         my $capital_y = "";
1571         my $capital_r = "";
1572         my $capital_s = "";
1573
1574         my $mode = "";
1575
1576         open(IN, "<$infile");
1577         while(<IN>) {
1578
1579                 my $line = $_;
1580                 chomp($line);
1581                 $line =~ s/\r//;
1582
1583                 my $keylen = "";
1584
1585                 # Mode and type check
1586                 # consider the following parsed line
1587                 # '# AESVS MCT test data for CBC'
1588                 # '# TDES Multi block Message Test for CBC'
1589                 # '# INVERSE PERMUTATION - KAT for CBC'
1590                 # '# SUBSTITUTION TABLE - KAT for CBC'
1591                 # '# TDES Monte Carlo (Modes) Test for CBC'
1592                 # '#  "SHA-1 Monte" information for "IBMRHEL5"'
1593                 # '# "SigVer PKCS#1 Ver 1.5" information for "IBMRHEL5"'
1594                 # '# "SigGen PKCS#1 Ver 1.5" information for "IBMRHEL5"'
1595                 # '#RC4VS MCT test data'
1596                 
1597                 # avoid false positives from user specified 'for "PRODUCT"' strings
1598                 my $tmpline = $line;
1599                 $tmpline =~ s/ for ".*"//;
1600
1601                 ##### Extract cipher
1602                 # XXX there may be more - to be added
1603                 if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen)/) {
1604                         if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
1605                         elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
1606                         elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
1607                         elsif ($tmpline =~ /CFB/)   { $mode="cfb"; }
1608                         #we do not need mode as the cipher is already clear
1609                         elsif ($tmpline =~ /SHA-1/) { $cipher="sha1"; }
1610                         elsif ($tmpline =~ /SHA-224/) { $cipher="sha224"; }
1611                         elsif ($tmpline =~ /SHA-256/) { $cipher="sha256"; }
1612                         elsif ($tmpline =~ /SHA-384/) { $cipher="sha384"; }
1613                         elsif ($tmpline =~ /SHA-512/) { $cipher="sha512"; }
1614                         #we do not need mode as the cipher is already clear
1615                         elsif ($tmpline =~ /RC4VS/) { $cipher="rc4"; }
1616                         elsif ($tmpline =~ /SigGen|SigVer/) {
1617                                 die "Error: X9.31 is not supported"
1618                                         if ($tmpline =~ /X9/);
1619                                 $cipher="sha1"; #place holder - might be overwritten later
1620                         }
1621
1622                         if ($tmpline =~ /^#.*AESVS/) {
1623                                 # AES cipher (part of it)
1624                                 $cipher="aes";
1625                         }
1626                         if ($tmpline =~ /^#.*(TDES|KAT)/) {
1627                                 # TDES cipher (full definition)
1628                                 # the FIPS-140 test generator tool does not produce
1629                                 # machine readable output!
1630                                 if ($mode eq "cbc") { $cipher="des-ede3-cbc"; }
1631                                 if ($mode eq "ecb") { $cipher="des-ede3"; }
1632                                 if ($mode eq "ofb") { $cipher="des-ede3-ofb"; }
1633                                 if ($mode eq "cfb") { $cipher="des-ede3-cfb"; }
1634                         }
1635
1636                         # check for RNG
1637                         if ($tmpline =~ /ANSI X9\.31/) {
1638                                 # change the tmpline to add the type of the
1639                                 # test which is ONLY visible from the file
1640                                 # name :-(
1641                                 if ($infile =~ /MCT\.req/) {
1642                                         $tmpline .= " MCT";
1643                                 } elsif ($infile =~ /VST\.req/) {
1644                                         $tmpline .= " VST";
1645                                 } else {
1646                                         die "Unexpected cipher type with $infile";
1647                                 }
1648                         }
1649
1650                         if ($tt == 0) {
1651                         ##### Identify the test type
1652                                 if ($tmpline =~ /SigVer/ && $opt{'D'} ) {
1653                                         $tt = 12;
1654                                         die "Interface function dsa_verify or dsa_genpubey for dSA verification not defined for tested library"
1655                                                 if (!defined($dsa_verify) || !defined($dsa_genpubkey));
1656                                 } elsif ($tmpline =~ /SigGen/ && $opt{'D'}) {
1657                                         $tt = 11;
1658                                         die "Interface function dsa_sign or gen_dsakey for DSA sign not defined for tested library"
1659                                                 if (!defined($dsa_sign) || !defined($gen_rsakey));
1660                                 } elsif ($tmpline =~ /PQGGen/) {
1661                                         $tt = 10;
1662                                         die "Interface function for DSA PQGGen testing not defined for tested library"
1663                                                 if (!defined($dsa_pqggen));
1664                                 } elsif ($tmpline =~ /Hash sizes tested/) {
1665                                         $tt = 9;
1666                                         die "Interface function hmac for HMAC testing not defined for tested library"
1667                                                 if (!defined($hmac));
1668                                 } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
1669                                         $tt = 8;
1670                                         die "Interface function state_rng for RNG MCT not defined for tested library"
1671                                                 if (!defined($state_rng));
1672                                 } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
1673                                         $tt = 7;
1674                                         die "Interface function state_rng for RNG KAT not defined for tested library"
1675                                                 if (!defined($state_rng));
1676                                 } elsif ($tmpline =~ /SigVer/ ) {
1677                                         $tt = 6;
1678                                         die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library"
1679                                                 if (!defined($rsa_verify) || !defined($gen_rsakey));
1680                                 } elsif ($tmpline =~ /SigGen/ ) {
1681                                         $tt = 5;
1682                                         die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library"
1683                                                 if (!defined($rsa_sign) || !defined($gen_rsakey));
1684                                 } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher =~ /^sha/) {
1685                                         $tt = 4;
1686                                         die "Interface function hash for Hashing not defined for tested library"
1687                                                 if (!defined($hash));
1688                                 } elsif ($tmpline =~ /Monte|MCT|Carlo/) {
1689                                         $tt = 2;
1690                                         die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
1691                                                 if (!defined($state_cipher) || !defined($state_cipher_des));
1692                                 } elsif ($cipher =~ /^sha/) {
1693                                         $tt = 3;
1694                                         die "Interface function hash for Hashing not defined for tested library"
1695                                                 if (!defined($hash));
1696                                 } else {
1697                                         $tt = 1;
1698                                         die "Interface function encdec for Encryption/Decryption not defined for tested library"
1699                                                 if (!defined($encdec));
1700                                 }
1701                         }
1702                 }
1703
1704                 # This is needed as ARCFOUR does not operate with an IV
1705                 $iv = "00000000000000000000000000000000" if ($cipher eq "rc4"
1706                                                              && $iv eq "" );
1707
1708                 # we are now looking for the string
1709                 # '# Key Length : 256'
1710                 # found in AES
1711                 if ($tmpline =~ /^# Key Length.*?(128|192|256)/) {
1712                         if ($cipher eq "aes") {
1713                                 $cipher="$cipher-$1-$mode";
1714                         } else {
1715                                 die "Error: Key length $1 given for cipher $cipher which is unexpected";
1716                         }
1717                 }
1718
1719                 # Get the test data
1720                 if ($line =~ /^(KEY|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
1721                         die "KEY seen twice - input file crap" if ($key1 ne "");
1722                         $keytype=$1;
1723                         $key1=$2;
1724                         $key1 =~ s/\s//g; #replace potential white spaces
1725                 }
1726                 elsif ($line =~ /^(KEYs)\s*=\s*(.*)/) { # found in ciphers and RNG
1727                         die "KEY seen twice - input file crap" if ($key1 ne "");
1728                         $keytype=$1;
1729                         $key1=$2;
1730                         $key1 =~ s/\s//g; #replace potential white spaces
1731                         $key2 = $key1;
1732                         $key3 = $key1;
1733                 }
1734                 elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES
1735                         die "First key not set, but got already second key - input file crap" if ($key1 eq "");
1736                         die "KEY2 seen twice - input file crap" if (defined($key2));
1737                         $key2=$1;
1738                         $key2 =~ s/\s//g; #replace potential white spaces
1739                 }
1740                 elsif ($line =~ /^KEY3\s*=\s*(.*)/) { # found in TDES
1741                         die "Second key not set, but got already third key - input file crap" if ($key2 eq "");
1742                         die "KEY3 seen twice - input file crap" if (defined($key3));
1743                         $key3=$1;
1744                         $key3 =~ s/\s//g; #replace potential white spaces
1745                 }
1746                 elsif ($line =~ /^IV\s*=\s*(.*)/) { # found in ciphers
1747                         die "IV seen twice - input file crap" if ($iv ne "");
1748                         $iv=$1;
1749                         $iv =~ s/\s//g; #replace potential white spaces
1750                 }
1751                 elsif ($line =~ /^PLAINTEXT\s*=\s*(.*)/) { # found in ciphers
1752                         if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
1753                                 die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
1754                                 $pt=$1;
1755                                 $pt =~ s/\s//g; #replace potential white spaces
1756                                 $enc=1;
1757                         }
1758                 }
1759                 elsif ($line =~ /^CIPHERTEXT\s*=\s*(.*)/) { # found in ciphers
1760                         if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
1761                                 die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
1762                                 $pt=$1;
1763                                 $pt =~ s/\s//g; #replace potential white spaces
1764                                 $enc=0;
1765                         }
1766                 }
1767                 elsif ($line =~ /^Len\s*=\s*(.*)/) { # found in hashs
1768                         $len=$1;
1769                 }
1770                 elsif ($line =~ /^(Msg|Seed)\s*=\s*(.*)/) { # found in hashs
1771                         die "Msg/Seed seen twice - input file crap" if ($pt ne "");
1772                         $pt=$2;
1773                 }
1774                 elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
1775                         $modulus = $1;
1776                         $out .= $line . "\n\n"; # print it
1777                         # generate the private key with given bit length now
1778                         # as we have the required key length in bit
1779                         if ($tt == 11) {
1780                                 $dsa_keyfile = "dsa_siggen.tmp.$$";
1781                                 my %pqg = &$gen_dsakey($dsa_keyfile);
1782                                 $out .= "P = " . $pqg{'P'} . "\n";
1783                                 $out .= "Q = " . $pqg{'Q'} . "\n";
1784                                 $out .= "G = " . $pqg{'G'} . "\n";
1785                         } elsif ( $tt == 5 ) {
1786                                 # XXX maybe a secure temp file name is better here
1787                                 # but since it is not run on a security sensitive
1788                                 # system, I hope that this is fine
1789                                 $rsa_keyfile = "rsa_siggen.tmp.$$";
1790                                 &$gen_rsakey($modulus, $rsa_keyfile);
1791                                 my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile");
1792                                 $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/;
1793                                 $out .= "n = $modulus\n";
1794                                 $out .= "\ne = 10001\n"
1795                         }
1796                 }
1797                 elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests
1798                         $cipher=$1;
1799                 }
1800                 elsif($line =~ /^n\s*=\s*(.*)/) { # found in RSA requests
1801                         $out .= $line . "\n";
1802                         $n=$1;
1803                 }
1804                 elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests
1805                         $e=$1;
1806                 }
1807                 elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests
1808                         die "S seen twice - input file crap" if ($signature ne "");
1809                         $signature=$1;
1810                 }
1811                 elsif ($line =~ /^DT\s*=\s*(.*)/) { # X9.31 RNG requests
1812                         die "DT seen twice - check input file"
1813                                 if ($dt ne "");
1814                         $dt=$1;
1815                 }
1816                 elsif ($line =~ /^V\s*=\s*(.*)/) { # X9.31 RNG requests
1817                         die "V seen twice - check input file"
1818                                 if ($v ne "");
1819                         $v=$1;
1820                 }
1821                 elsif ($line =~ /^Klen\s*=\s*(.*)/) { # HMAC requests
1822                         die "Klen seen twice - check input file"
1823                                 if ($klen ne "");
1824                         $klen=$1;
1825                 }
1826                 elsif ($line =~ /^Tlen\s*=\s*(.*)/) { # HMAC RNG requests
1827                         die "Tlen seen twice - check input file"
1828                                 if ($tlen ne "");
1829                         $tlen=$1;
1830                 }
1831                 elsif ($line =~ /^N\s*=\s*(.)/) { #DSA PQGGen
1832                         die "N seen twice - check input file"
1833                                 if ($capital_n);
1834                         $capital_n = $1;
1835                 }
1836                 elsif ($line =~ /^P\s*=\s*(.)/) { #DSA SigVer
1837                         die "P seen twice - check input file"
1838                                 if ($capital_p);
1839                         $capital_p = $1;
1840                         $out .= $line . "\n"; # print it
1841                 }
1842                 elsif ($line =~ /^Q\s*=\s*(.)/) { #DSA SigVer
1843                         die "Q seen twice - check input file"
1844                                 if ($capital_q);
1845                         $capital_q = $1;
1846                         $out .= $line . "\n"; # print it
1847                 }
1848                 elsif ($line =~ /^G\s*=\s*(.)/) { #DSA SigVer
1849                         die "G seen twice - check input file"
1850                                 if ($capital_g);
1851                         $capital_g = $1;
1852                         $out .= $line . "\n"; # print it
1853                 }
1854                 elsif ($line =~ /^Y\s*=\s*(.)/) { #DSA SigVer
1855                         die "Y seen twice - check input file"
1856                                 if ($capital_y);
1857                         $capital_y = $1;
1858                 }
1859                 elsif ($line =~ /^R\s*=\s*(.)/) { #DSA SigVer
1860                         die "R seen twice - check input file"
1861                                 if ($capital_r);
1862                         $capital_r = $1;
1863                 }
1864                 elsif ($line =~ /^S\s*=\s*(.)/) { #DSA SigVer
1865                         die "S seen twice - check input file"
1866                                 if ($capital_s);
1867                         $capital_s = $1;
1868                 }
1869                 else {
1870                         $out .= $line . "\n";
1871                 }
1872
1873                 # call tests if all input data is there
1874                 if ($tt == 1) {
1875                         if ($key1 ne "" && $pt ne "" && $cipher ne "") {
1876                                 $out .= kat($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
1877                                 $keytype = "";
1878                                 $key1 = "";
1879                                 $key2 = undef;
1880                                 $key3 = undef;
1881                                 $iv = "";
1882                                 $pt = "";
1883                         }
1884                 }
1885                 elsif ($tt == 2) {
1886                         if ($key1 ne "" && $pt ne "" && $cipher ne "") {
1887                                 $out .= crypto_mct($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
1888                                 $keytype = "";
1889                                 $key1 = "";
1890                                 $key2 = undef;
1891                                 $key3 = undef;
1892                                 $iv = "";
1893                                 $pt = "";
1894                         }
1895                 }
1896                 elsif ($tt == 3) {
1897                         if ($pt ne "" && $cipher ne "") {
1898                                 $out .= hash_kat($pt, $cipher, $len);
1899                                 $pt = "";
1900                                 $len = undef;
1901                         }
1902                 }
1903                 elsif ($tt == 4) {
1904                         if ($pt ne "" && $cipher ne "") {
1905                                 $out .= hash_mct($pt, $cipher);
1906                                 $pt = "";
1907                         }
1908                 }
1909                 elsif ($tt == 5) {
1910                         if ($pt ne "" && $cipher ne "" && $rsa_keyfile ne "") {
1911                                 $out .= rsa_siggen($pt, $cipher, $rsa_keyfile);
1912                                 $pt = "";
1913                         }
1914                 }
1915                 elsif ($tt == 6) {
1916                         if ($pt ne "" && $cipher ne "" && $signature ne "" && $n ne "" && $e ne "") {
1917                                 $out .= rsa_sigver($pt, $cipher, $signature, $n, $e);
1918                                 $pt = "";
1919                                 $signature = "";
1920                         }
1921                 }
1922                 elsif ($tt == 7 ) {
1923                         if ($key1 ne "" && $dt ne "" && $v ne "") {
1924                                 $out .= rngx931($key1, $dt, $v, "VST");
1925                                 $key1 = "";
1926                                 $dt = "";
1927                                 $v = "";
1928                         }
1929                 }
1930                 elsif ($tt == 8 ) {
1931                         if ($key1 ne "" && $dt ne "" && $v ne "") {
1932                                 $out .= rngx931($key1, $dt, $v, "MCT");
1933                                 $key1 = "";
1934                                 $dt = "";
1935                                 $v = "";
1936                         }
1937                 }
1938                 elsif ($tt == 9) {
1939                         if ($klen ne "" && $tlen ne "" && $key1 ne "" && $pt ne "") {
1940                                 $out .= hmac_kat($klen, $tlen, $key1, $pt);
1941                                 $key1 = "";
1942                                 $tlen = "";
1943                                 $klen = "";
1944                                 $pt = "";
1945                         }
1946                 }
1947                 elsif ($tt == 10) {
1948                         if ($modulus ne "" && $capital_n > 0) {
1949                                 $out .= dsa_pqggen_driver($modulus, $capital_n);
1950                                 #$mod is not resetted
1951                                 $capital_n = 0;
1952                         }
1953                 }
1954                 elsif ($tt == 11) {
1955                         if ($pt ne "" && $dsa_keyfile ne "") {
1956                                 $out .= dsa_siggen($pt, $dsa_keyfile);
1957                                 $pt = "";
1958                         }
1959                 }
1960                 elsif ($tt == 12) {
1961                         if ($modulus ne "" &&
1962                             $capital_p ne "" &&
1963                             $capital_q ne "" &&
1964                             $capital_g ne "" &&
1965                             $capital_y ne "" &&
1966                             $capital_r ne "" &&
1967                             $capital_s ne "" &&
1968                             $pt ne "") {
1969                                 $out .= dsa_sigver($modulus,
1970                                                    $capital_p,
1971                                                    $capital_q,
1972                                                    $capital_g,
1973                                                    $capital_y,
1974                                                    $capital_r,
1975                                                    $capital_s,
1976                                                    $pt);
1977
1978                                 # We do not clear the domain values PQG and
1979                                 # the modulus value as they
1980                                 # are specified only once in a file
1981                                 # and we do not need to print them as they
1982                                 # are already printed above
1983                                 $capital_y = "";
1984                                 $capital_r = "";
1985                                 $capital_s = "";
1986                                 $pt = "";
1987                         }
1988                 }
1989                 elsif ($tt > 0) {
1990                         die "Test case $tt not defined";
1991                 }
1992         }
1993
1994         close IN;
1995         $out =~ s/\n/\r\n/g; # make it a dos file
1996         open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
1997         print OUT $out;
1998         close OUT;
1999
2000 }
2001
2002 # Signalhandler
2003 sub cleanup() {
2004         unlink("rsa_siggen.tmp.$$");
2005         unlink("rsa_sigver.tmp.$$");
2006         unlink("rsa_sigver.tmp.$$.sig");
2007         unlink("rsa_sigver.tmp.$$.der");
2008         unlink("rsa_sigver.tmp.$$.cnf");
2009
2010         unlink("dsa_sigver.tmp.$$.sig");
2011         exit;
2012 }
2013
2014 ############################################################
2015 #
2016 # let us pretend to be C :-)
2017 sub main() {
2018
2019         usage() unless @ARGV;
2020
2021         getopts("DRI:", \%opt) or die "bad option";
2022
2023         ##### Set library
2024
2025         if ( ! defined $opt{'I'} || $opt{'I'} eq 'openssl' ) {
2026                 print STDERR "Using OpenSSL interface functions\n";
2027                 $encdec =       \&openssl_encdec;
2028                 $rsa_sign =     \&openssl_rsa_sign;
2029                 $rsa_verify =   \&openssl_rsa_verify;
2030                 $gen_rsakey =   \&openssl_gen_rsakey;
2031                 $hash =         \&openssl_hash;
2032                 $state_cipher = \&openssl_state_cipher;
2033         } elsif ( $opt{'I'} eq 'libgcrypt' ) {
2034                 print STDERR "Using libgcrypt interface functions\n";
2035                 $encdec =       \&libgcrypt_encdec;
2036                 $rsa_sign =     \&libgcrypt_rsa_sign;
2037                 $rsa_verify =   \&libgcrypt_rsa_verify;
2038                 $gen_rsakey =   \&libgcrypt_gen_rsakey;
2039                 $hash =         \&libgcrypt_hash;
2040                 $state_cipher = \&libgcrypt_state_cipher;
2041                 $state_cipher_des =     \&libgcrypt_state_cipher_des;
2042                 $state_rng =    \&libgcrypt_state_rng;
2043                 $hmac =         \&libgcrypt_hmac;
2044                 $dsa_pqggen =   \&libgcrypt_dsa_pqggen;
2045                 $gen_dsakey =   \&libgcrypt_gen_dsakey;
2046                 $dsa_sign =     \&libgcrypt_dsa_sign;
2047                 $dsa_verify =   \&libgcrypt_dsa_verify;
2048                 $dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
2049         } else {
2050                 die "Invalid interface option given";
2051         }
2052
2053         my $infile=$ARGV[0];
2054         die "Error: Test vector file $infile not found" if (! -f $infile);
2055
2056         my $outfile = $infile;
2057         # let us add .rsp regardless whether we could strip .req
2058         $outfile =~ s/\.req$//;
2059         if ($opt{'R'}) {
2060                 $outfile .= ".rc4";
2061         } else {
2062                 $outfile .= ".rsp";
2063         }
2064         if (-f $outfile) {
2065                 die "Output file $outfile could not be removed: $?"
2066                         unless unlink($outfile);
2067         }
2068         print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
2069
2070         #Signal handler
2071         $SIG{HUP} = \&cleanup;
2072         $SIG{INT} = \&cleanup;
2073         $SIG{QUIT} = \&cleanup;
2074         $SIG{TERM} = \&cleanup;
2075
2076         # Do the job
2077         parse($infile, $outfile);
2078
2079         unlink("rsa_siggen.tmp.$$");
2080
2081 }
2082
2083 ###########################################
2084 # Call it
2085 main();
2086 1;