Another tweak for the RNG test code.
[libgcrypt.git] / tests / cavs_driver.pl
1 #!/usr/bin/env perl
2 #
3 # CAVS test driver (based on the OpenSSL driver)
4 # Written by: Stephan Müller <sm@atsec.com>
5 # Copyright (c) atsec information security corporation
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions: 
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 #                            NO WARRANTY
18 #
19 #    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
20 #    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
21 #    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
22 #    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
23 #    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 #    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
25 #    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
26 #    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
27 #    REPAIR OR CORRECTION.
28 #
29 #    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
30 #    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
31 #    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
32 #    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
33 #    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
34 #    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
35 #    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
36 #    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
37 #    POSSIBILITY OF SUCH DAMAGES.
38 #
39 #
40 # test execution instruction:
41 # 1. get the request files from the lab
42 # 2. call each request file from 1. with this program:
43 #       $0 <FILE>.rep
44 # 3. send the resulting file <FILE>.rsp to the lab
45 #
46 #
47 # Test should be easily adoptable to other implementations
48 # See the first functions for this task
49 #
50 # Following tests are covered (others may also be covered
51 # but have not been tested)
52 #
53 # AES
54 #       CBCGFSbox[128|192|256]
55 #       CBCMCT[128|192|256]
56 #       CBCVarKey[128|192|256]
57 #       CBCKeySbox[128|192|256]
58 #       CBCMMT[128|192|256]
59 #       CBCVarTxt[128|192|256]
60 #
61 # RSA
62 #       SigGen[15|RSA]
63 #       SigVer15
64 #       (SigVerRSA is not applicable for OpenSSL as X9.31 padding
65 #               is not done through openssl dgst)
66 #
67 # SHA
68 #       SHA1ShortMsg
69 #       SHA1LongMsg
70 #       SHA1Monte
71 #
72 # TDES
73 #       TCBCMonte[1|2|3]
74 #       TCBCpermop
75 #       TCBCMMT[1|2|3]
76 #       TCBCsubtab
77 #       TCBCvarkey
78 #       TCBCinvperm
79 #       TCBCvartext
80 #
81 # ANSI X9.31 RNG
82 #       ANSI931_AES128MCT
83 #       ANSI931_AES128VST
84 #
85 # RC4 (atsec developed tests)
86 #       RC4KeyBD
87 #       RC4MCT
88 #       RC4PltBD
89 #       RC4REGT
90 #
91
92 use strict;
93 use warnings;
94 use IPC::Open2;
95 use Getopt::Std;
96 use MIME::Base64;
97
98 # Contains the command line options
99 my %opt;
100
101
102 #################################################################
103 ##### Central interface functions to the external ciphers #######
104 #################################################################
105 # Only these interface routines should be changed in case of
106 # porting to a new cipher library
107 #
108 # For porting to a new library, create implementation of these functions
109 # and then add pointers to the respective implementation of each
110 # function to the given variables.
111
112 # common encryption/decryption routine
113 # $1 key in hex form
114 # $2 iv in hex form
115 # $3 cipher
116 # $4 encrypt=1/decrypt=0
117 # $5 de/encrypted data in hex form
118 # return en/decrypted data in hex form
119 my $encdec;
120
121 # Sign a message with RSA
122 # $1: data to be signed in hex form
123 # $2: Hash algo
124 # $3: Key file in PEM format with the private key
125 # return: digest in hex format
126 my $rsa_sign;
127
128 # Verify a message with RSA
129 # $1: data to be verified in hex form
130 # $2: hash algo
131 # $3: file holding the public RSA key in PEM format
132 # $4: file holding the signature in binary form
133 # return: 1 == verfied / 0 == not verified
134 my $rsa_verify;
135
136 # generate a new private RSA key in PEM format
137 # $1 key size in bit
138 # $2 keyfile name
139 # return: nothing, but file created
140 my $gen_rsakey;
141
142 # Creating a hash
143 # $1: Plaintext
144 # $2: hash type
145 # return: hash in hex form
146 my $hash;
147
148 # supplying the call to the external cipher implementation
149 # that is being used to keep STDIN and STDOUT open
150 # to maintain the state of the block chaining
151 # $1: cipher
152 # $2: 1=encryption, 0=decryption
153 # $3: buffersize needed for openssl
154 # $4: encryption key in binary form
155 # $5: IV in binary form
156 # return: command line to execute the application
157 my $state_cipher;
158
159 # supplying the call to the external cipher implementation
160 # that is being used to keep STDIN and STDOUT open
161 # to maintain the state of the RNG with its seed
162 #
163 # input holds seed values
164 # $1: cipher key in hex format
165 # $2: DT value in hex format
166 # $3: V value in hex format
167 #
168 # return: command line to execute the application
169 #
170 # the application is expected to deliver random values on STDOUT - the script
171 # reads 128 bits repeatedly where the state of the RNG must be retained
172 # between the reads. The output of the RNG on STDOUT is assumed to be binary.
173 my $state_rng;
174
175 ################################################################
176 ##### OpenSSL interface functions
177 ################################################################
178 sub openssl_encdec($$$$$) {
179         my $key=shift;
180         my $iv=shift;
181         my $cipher=shift;
182         my $enc = (shift) ? "-e" : "-d";
183         my $data=shift;
184
185         $data=hex2bin($data);
186         my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc -iv $iv";
187         $program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given
188         $data=pipe_through_program($data,$program);
189         return bin2hex($data);
190 }
191
192 sub openssl_rsa_sign($$$) {
193         my $data = shift;
194         my $cipher = shift;
195         my $keyfile = shift;
196
197         $data=hex2bin($data);
198         die "ARCFOUR not available for RSA" if $opt{'R'};
199         $data=pipe_through_program($data,
200                 "openssl dgst -$cipher -binary -sign $keyfile");
201         return bin2hex($data);
202 }
203
204 sub openssl_rsa_verify($$$$) {
205         my $data = shift;
206         my $cipher = shift;
207         my $keyfile = shift;
208         my $sigfile = shift;
209
210         $data = hex2bin($data);
211         die "ARCFOUR not available for RSA" if $opt{'R'};
212         $data = pipe_through_program($data,
213                 "openssl dgst -$cipher -binary -verify $keyfile -signature $sigfile");
214
215         # Parse through the OpenSSL output information
216         return ($data =~ /OK/);
217 }
218
219 sub openssl_gen_rsakey($$) {
220         my $keylen = shift;
221         my $file = shift;
222
223         die "ARCFOUR not available for RSA" if $opt{'R'};
224         # generating of a key with exponent 0x10001
225         my @args = ("openssl", "genrsa", "-F4", "-out", "$file", "$keylen");
226         system(@args) == 0
227                 or die "system @args failed: $?";
228         die "system @args failed: file $file not created" if (! -f $file);
229 }
230
231 sub openssl_hash($$) {
232         my $pt = shift;
233         my $cipher = shift;
234
235         die "ARCFOUR not available for hashes" if $opt{'R'};
236         my $hash = hex2bin($pt);
237         #bin2hex not needed as the '-hex' already converts it
238         return pipe_through_program($hash, "openssl dgst -$cipher -hex");
239 }
240
241 sub openssl_state_cipher($$$$$) {
242         my $cipher = shift;
243         my $encdec = shift;
244         my $bufsize = shift;
245         my $key = shift;
246         my $iv = shift;
247
248         my $enc = $encdec ? "-e": "-d";
249
250         my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." -iv ".bin2hex($iv);
251         #for ARCFOUR, no IV must be given
252         $out = "rc4 -k " . bin2hex($key) if $opt{'R'};
253         return $out;
254 }
255
256 ###### End of OpenSSL interface implementation ############
257
258 ###########################################################
259 ###### libgcrypt implementation
260 ###########################################################
261 sub libgcrypt_state_rng($$$) {
262         my $key = shift;
263         my $dt = shift;
264         my $v = shift;
265
266         return "fipsrngdrv --binary --loop $key $v $dt";
267 }
268
269 ######### End of libgcrypt implementation ################
270
271 ##### No other interface functions below this point ######
272 ##########################################################
273
274 ##########################################################
275 # General helper routines
276
277 # Executing a program by feeding STDIN and retrieving
278 # STDOUT
279 # $1: data string to be piped to the app on STDIN
280 # rest: program and args
281 # returns: STDOUT of program as string
282 sub pipe_through_program($@) {
283         my $in = shift;
284         my @args = @_;
285
286         my ($CO, $CI);
287         my $pid = open2($CO, $CI, @args);
288         
289         my $out = "";
290         my $len = length($in);
291         my $first = 1;
292         while (1) {
293                 my $rin = "";
294                 my $win = "";
295                 # Output of prog is FD that we read
296                 vec($rin,fileno($CO),1) = 1;
297                 # Input of prog is FD that we write
298                 # check for $first is needed because we can have NULL input
299                 # that is to be written to the app
300                 if ( $len > 0 || $first) {
301                         (vec($win,fileno($CI),1) = 1);
302                         $first=0;
303                 }
304                 # Let us wait for 100ms
305                 my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
306                 if ( $wout ) {
307                         my $written = syswrite($CI, $in, $len);
308                         die "broken pipe" if !defined $written;
309                         $len -= $written;
310                         substr($in, 0, $written) = "";
311                         if ($len <= 0) {
312                                 close $CI or die "broken pipe: $!";
313                         }
314                 }
315                 if ( $rout ) {
316                         my $tmp_out = "";
317                         my $bytes_read = sysread($CO, $tmp_out, 4096);
318                         $out .= $tmp_out;
319                         last if ($bytes_read == 0);
320                 }
321         }
322         close $CO or die "broken pipe: $!";
323         waitpid $pid, 0;
324         
325         return $out;
326 }
327
328 #
329 # convert ASCII hex to binary input
330 # $1 ASCII hex
331 # return binary representation
332 sub hex2bin($) {
333         my $in = shift;
334         my $len = length($in);
335         $len = 0 if ($in eq "00");
336         return pack("H$len", "$in");
337 }
338
339 #
340 # convert binary input to ASCII hex
341 # $1 binary value
342 # return ASCII hex representation
343 sub bin2hex($) {
344         my $in = shift;
345         my $len = length($in)*2;
346         return unpack("H$len", "$in");
347 }
348
349 # $1: binary byte (character)
350 # returns: binary byte with odd parity using low bit as parity bit
351 sub odd_par($) {
352         my $in = ord(shift);
353         my $odd_count=0;
354         for(my $i=1; $i<8; $i++) {
355                 $odd_count++ if ($in & (1<<$i));
356         }
357
358         my $out = $in;
359         if ($odd_count & 1) { # check if parity is already odd
360                 $out &= ~1; # clear the low bit
361         } else {
362                 $out |= 1; # set the low bit
363         }
364
365         return chr($out);
366 }
367
368 # DES keys uses only the 7 high bits of a byte, the 8th low bit
369 # is the parity bit
370 # as the new key is calculated from oldkey XOR cipher in the MCT test,
371 # the parity is not really checked and needs to be set to match
372 # expectation (OpenSSL does not really care, but the FIPS
373 # test result is expected that the key has the appropriate parity)
374 # $1: arbitrary binary string
375 # returns: string with odd parity set in low bit of each byte
376 sub fix_key_parity($) {
377         my $in = shift;
378         my $out = "";
379         for (my $i = 0; $i < length($in); $i++) {
380                 $out .= odd_par(substr($in, $i, 1));
381         }
382
383         return $out;
384 }
385
386 ####################################################
387 # Encrypt/Decrypt routines
388
389 # encryption
390 # $1 key in hex form
391 # $2 iv in hex form
392 # $3 cipher
393 # $4 data in hex form
394 # return encrypted data
395 sub encrypt($$$$) {
396         my $key=shift;
397         my $iv=shift;
398         my $cipher=shift;
399         my $data=shift;
400
401         return &$encdec($key, $iv, $cipher, 1, $data);
402 }
403
404 # decryption
405 # $1 key in hex form
406 # $2 iv in hex form
407 # $3 cipher
408 # $4 data in hex form
409 # return encrypted data
410 sub decrypt($$$$) {
411         my $key=shift;
412         my $iv=shift;
413         my $cipher=shift;
414         my $data=shift;
415
416         return &$encdec($key, $iv, $cipher, 0, $data);
417 }
418
419 ####################################################
420 # DER/PEM utility functions
421 # Cf. http://www.columbia.edu/~ariel/ssleay/layman.html
422
423 # Convert unsigned integer to base256 bigint bytes
424 # $1 integer
425 # returns base256 octet string
426 sub int_base256_unsigned($) {
427         my $n = shift;
428
429         my $out = chr($n & 255);
430         while ($n>>=8) {
431                 $out = chr($n & 255) . $out;
432         }
433
434         return $out;
435 }
436
437 # Convert signed integer to base256 bigint bytes
438 # $1 integer
439 # returns base256 octet string
440 sub int_base256_signed($) {
441         my $n = shift;
442         my $negative = ($n < 0);
443
444         if ($negative) {
445                 $n = -$n-1;
446         }
447
448         my $out = int_base256_unsigned($n);
449
450         if (ord(substr($out, 0, 1)) & 128) {
451                 # it's supposed to be positive but has sign bit set,
452                 # add a leading zero
453                 $out = chr(0) . $out;
454         }
455
456         if ($negative) {
457                 my $neg = chr(255) x length($out);
458                 $out ^= $neg;
459         }
460
461         return $out;
462 }
463
464 # Length header for specified DER object length
465 # $1 length as integer
466 # return octet encoding for length
467 sub der_len($) {
468         my $len = shift;
469
470         if ($len <= 127) {
471                 return chr($len);
472         } else {
473                 my $blen = int_base256_unsigned($len);
474
475                 return chr(128 | length($blen)) . $blen;
476         }
477 }
478
479 # Prepend length header to object
480 # $1 object as octet sequence
481 # return length header for object followed by object as octets
482 sub der_len_obj($) {
483         my $x = shift;
484
485         return der_len(length($x)) . $x;
486 }
487
488 # DER sequence
489 # $* objects
490 # returns DER sequence consisting of the objects passed as arguments
491 sub der_seq {
492         my $seq = join("", @_);
493         return chr(0x30) . der_len_obj($seq);
494 }
495
496 # DER bitstring
497 # $1 input octets (must be full octets, fractional octets not supported)
498 # returns input encapsulated as bitstring
499 sub der_bitstring($) {
500         my $x = shift;
501
502         $x = chr(0) . $x;
503
504         return chr(0x03) . der_len_obj($x);
505 }
506
507 # base-128-encoded integer, used for object numbers.
508 # $1 integer
509 # returns octet sequence
510 sub der_base128($) {
511         my $n = shift;
512
513         my $out = chr($n & 127);
514
515         while ($n>>=7) {
516                 $out = chr(128 | ($n & 127)) . $out;
517         }
518
519         return $out;
520 }
521
522 # Generating the PEM certificate string
523 # (base-64-encoded DER string)
524 # $1 DER string
525 # returns octet sequence
526 sub pem_cert($) {
527         my $n = shift;
528
529         my $out = "-----BEGIN PUBLIC KEY-----\n";
530         $out .= encode_base64($n);
531         $out .= "-----END PUBLIC KEY-----\n";
532
533         return $out;
534 }
535
536 # DER object identifier
537 # $* sequence of id numbers
538 # returns octets
539 sub der_objectid {
540         my $v1 = shift;
541         my $v2 = shift;
542
543         my $out = chr(40*$v1 + $v2) . join("", map { der_base128($_) } @_);
544
545         return chr(0x06) . der_len_obj($out);
546 }
547
548 # DER signed integer
549 # $1 number as octet string (base 256 representation, high byte first)
550 # returns number in DER integer encoding
551 sub der_bigint($) {
552         my $x = shift;
553
554         return chr(0x02) . der_len_obj($x);
555 }
556
557 # DER positive integer with leading zeroes stripped
558 # $1 number as octet string (base 256 representation, high byte first)
559 # returns number in DER integer encoding
560 sub der_pos_bigint($) {
561         my $x = shift;
562
563         # strip leading zero digits
564         $x =~ s/^[\0]+//;
565
566         # need to prepend a zero if high bit set, since it would otherwise be
567         # interpreted as a negative number. Also needed for number 0.
568         if (!length($x) || ord(substr($x, 0, 1)) >= 128) {
569                 $x = chr(0) . $x;
570         }
571
572         return der_bigint($x);
573 }
574
575 # $1 number as signed integer
576 # returns number as signed DER integer encoding
577 sub der_int($) {
578         my $n = shift;
579         
580         return der_bigint(int_base256_signed($n));
581 }
582
583 # the NULL object constant
584 sub der_null() {
585         return chr(0x05) . chr(0x00);
586 }
587
588 # Unit test helper
589 # $1 calculated result
590 # $2 expected result
591 # no return value, dies if results differ, showing caller's line number
592 sub der_test($$) {
593         my $actual = bin2hex(shift);
594         my $expected = shift;
595
596         my @caller = caller;
597         $actual eq $expected or die "Error:line $caller[2]:assertion failed: "
598                 ."$actual != $expected\n";
599 }
600
601 # Unit testing for the DER encoding functions
602 # Examples from http://www.columbia.edu/~ariel/ssleay/layman.html
603 # No input, no output. Dies if unit tests fail.
604 sub der_unit_test {
605         ## uncomment these if you want to test the test framework
606         #print STDERR "Unit test running\n";
607         #der_test chr(0), "42";
608
609         der_test der_null, "0500";
610
611         # length bytes
612         der_test der_len(1), "01";
613         der_test der_len(127), "7f";
614         der_test der_len(128), "8180";
615         der_test der_len(256), "820100";
616         der_test der_len(65536), "83010000";
617
618         # bigint
619         der_test der_bigint(chr(0)), "020100";
620         der_test der_bigint(chr(128)), "020180"; # -128
621         der_test der_pos_bigint(chr(128)), "02020080"; # +128
622         der_test der_pos_bigint(chr(0).chr(0).chr(1)), "020101";
623         der_test der_pos_bigint(chr(0)), "020100";
624
625         # integers (tests base256 conversion)
626         der_test der_int(     0), "020100";
627         der_test der_int(   127), "02017f";
628         der_test der_int(   128), "02020080";
629         der_test der_int(   256), "02020100";
630         der_test der_int(    -1), "0201ff";
631         der_test der_int(  -128), "020180";
632         der_test der_int(  -129), "0202ff7f";
633         der_test der_int(-65536), "0203ff0000";
634         der_test der_int(-65537), "0203feffff";
635
636         # object encoding, "RSA Security"
637         der_test der_base128(840), "8648";
638         der_test der_objectid(1, 2, 840, 113549), "06062a864886f70d";
639
640         # Combinations
641         der_test der_bitstring("ABCD"), "03050041424344";
642         der_test der_bitstring(der_null), "0303000500";
643         der_test der_seq(der_int(0), der_null), "30050201000500";
644
645         # The big picture
646         der_test der_seq(der_seq(der_objectid(1, 2, 840, 113549), der_null),
647                          der_bitstring(der_seq(der_pos_bigint(chr(5)),
648                                                der_pos_bigint(chr(3))))),
649                  "3017300a06062a864886f70d05000309003006020105020103";
650 }
651
652 ####################################################
653 # OpenSSL missing functionality workarounds
654
655 ## Format of an RSA public key:
656 #    0:d=0  hl=3 l= 159 cons: SEQUENCE          
657 #    3:d=1  hl=2 l=  13 cons:  SEQUENCE          
658 #    5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
659 #   16:d=2  hl=2 l=   0 prim:   NULL              
660 #   18:d=1  hl=3 l= 141 prim:  BIT STRING        
661 #                              [ sequence: INTEGER (n), INTEGER (e) ]
662
663 # generate RSA pub key in PEM format
664 # $1: filename where PEM key is to be stored
665 # $2: n of the RSA key in hex
666 # $3: e of the RSA key in hex
667 # return: nothing, but file created
668 sub gen_pubrsakey($$$) {
669         my $filename=shift;
670         my $n = shift;
671         my $e = shift;
672
673         # make sure the DER encoder works ;-)
674         der_unit_test();
675
676         # generate DER encoding of the public key
677
678         my $rsaEncryption = der_objectid(1, 2, 840, 113549, 1, 1, 1);
679
680         my $der = der_seq(der_seq($rsaEncryption, der_null),
681                           der_bitstring(der_seq(der_pos_bigint(hex2bin($n)),
682                                                 der_pos_bigint(hex2bin($e)))));
683
684         open(FH, ">", $filename) or die;
685         print FH pem_cert($der);
686         close FH;
687
688 }
689
690 # generate RSA pub key in PEM format
691 #
692 # This implementation uses "openssl asn1parse -genconf" which was added
693 # in openssl 0.9.8. It is not available in older openssl versions.
694 #
695 # $1: filename where PEM key is to be stored
696 # $2: n of the RSA key in hex
697 # $3: e of the RSA key in hex
698 # return: nothing, but file created
699 sub gen_pubrsakey_using_openssl($$$) {
700         my $filename=shift;
701         my $n = shift;
702         my $e = shift;
703
704         my $asn1 = "asn1=SEQUENCE:pubkeyinfo
705
706 [pubkeyinfo]
707 algorithm=SEQUENCE:rsa_alg
708 pubkey=BITWRAP,SEQUENCE:rsapubkey
709
710 [rsa_alg]
711 algorithm=OID:rsaEncryption
712 parameter=NULL
713
714 [rsapubkey]
715 n=INTEGER:0x$n
716
717 e=INTEGER:0x$e";
718
719         open(FH, ">$filename.cnf") or die "Cannot create file $filename.cnf: $?";
720         print FH $asn1;
721         close FH;
722         my @args = ("openssl", "asn1parse", "-genconf", "$filename.cnf", "-noout", "-out", "$filename.der");
723         system(@args) == 0 or die "system @args failed: $?";
724         @args = ("openssl", "rsa", "-inform", "DER", "-in", "$filename.der",
725                  "-outform", "PEM", "-pubin", "-pubout", "-out", "$filename");
726         system(@args) == 0 or die "system @args failed: $?";
727         die "RSA PEM formatted key file $filename was not created"
728                 if (! -f $filename);
729
730         unlink("$filename.cnf");
731         unlink("$filename.der");
732 }
733
734 ############################################
735 # Test cases
736
737 # This is the Known Answer Test
738 # $1: the string that we have to put in front of the key
739 #     when printing the key
740 # $2: crypto key1 in hex form
741 # $3: crypto key2 in hex form (TDES, undef otherwise)
742 # $4: crypto key3 in hex form (TDES, undef otherwise)
743 # $5: IV in hex form
744 # $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
745 # $7: cipher
746 # $8: encrypt=1/decrypt=0
747 # return: string formatted as expected by CAVS
748 sub kat($$$$$$$$) {
749         my $keytype = shift;
750         my $key1 = shift;
751         my $key2 = shift;
752         my $key3 = shift;
753         my $iv = shift;
754         my $pt = shift;
755         my $cipher = shift;
756         my $enc = shift;
757
758         my $out = "";
759
760         # this is the concardination of the keys for 3DES
761         # as used in OpenSSL
762         if (defined($key2)) {
763                 $out .= "$keytype = $key1\n";
764                 $out .= "KEY2 = $key2\n";
765                 $key1 = $key1 . $key2;
766         } else {
767                 $out .= "$keytype = $key1\n";
768         }
769         if (defined($key3)) {
770                 $out .= "KEY3 = $key3\n";
771                 $key1= $key1 . $key3;
772         }
773         
774         $out .= "IV = $iv\n";
775         if ($enc) {
776                 $out .= "PLAINTEXT = $pt\n";
777                 $out .= "CIPHERTEXT = " . encrypt($key1, $iv, $cipher, $pt) . "\n";
778         } else {
779                 $out .= "CIPHERTEXT = $pt\n";
780                 $out .= "PLAINTEXT = " . decrypt($key1, $iv, $cipher, $pt) . "\n";
781         }
782
783         return $out;
784 }
785
786 # This is the Known Answer Test for Hashes
787 # $1: Plaintext in hex form
788 # $2: hash
789 # $3: hash length (undef if not applicable)
790 # return: string formatted as expected by CAVS
791 sub hash_kat($$$) {
792         my $pt = shift;
793         my $cipher = shift;
794         my $len = shift;
795
796         my $out = "";
797         $out .= "Len = $len\n" if (defined($len));
798         $out .= "Msg = $pt\n";
799         $out .= "MD = " . &$hash($pt, $cipher);
800         return $out;
801 }
802
803 # Cipher Monte Carlo Testing
804 # $1: the string that we have to put in front of the key
805 #     when printing the key
806 # $2: crypto key1 in hex form
807 # $3: crypto key2 in hex form (TDES, undef otherwise)
808 # $4: crypto key3 in hex form (TDES, undef otherwise)
809 # $5: IV in hex form
810 # $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
811 # $7: cipher
812 # $8: encrypt=1/decrypt=0
813 # return: string formatted as expected by CAVS
814 sub crypto_mct($$$$$$$$) {
815         my $keytype = shift;
816         my $key1 = hex2bin(shift);
817         my $key2 = shift;
818         my $key3 = shift;
819         my $iv = hex2bin(shift);
820         my $source_data = hex2bin(shift);
821         my $cipher = shift;
822         my $enc = shift;
823
824         my $out = "";
825
826         $key2 = hex2bin($key2) if (defined($key2));
827         $key3 = hex2bin($key3) if (defined($key3));
828         my $bufsize = length($source_data);
829
830         # for AES: outer loop 0-99, inner 0-999 based on FIPS compliance tests
831         # for RC4: outer loop 0-99, inner 0-999 based on atsec compliance tests
832         # for DES: outer loop 0-399, inner 0-9999 based on FIPS compliance tests
833         my $ciph = substr($cipher,0,3);
834         my $oloop=100;
835         my $iloop=1000;
836         if ($ciph =~ /des/) {$oloop=400;$iloop=10000;}
837
838         for (my $i=0; $i<$oloop; ++$i) {
839                 $out .= "COUNT = $i\n";
840                 if (defined($key2)) {
841                         $out .= "$keytype = ". bin2hex($key1). "\n";
842                         $out .= "KEY2 = ". bin2hex($key2). "\n";
843                         $key1 = $key1 . $key2;
844                 } else {
845                         $out .= "$keytype = ". bin2hex($key1). "\n";
846                 }
847                 if(defined($key3)) {
848                         $out .= "KEY3 = ". bin2hex($key3). "\n";
849                         $key1 = $key1 . $key3;
850                 }
851                 my $keylen = length($key1);
852
853                 $out .= "IV = ". bin2hex($iv). "\n";
854
855                 if ($enc) {
856                         $out .= "PLAINTEXT = ". bin2hex($source_data). "\n";
857                 } else {
858                         $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n";
859                 }
860                 my ($CO, $CI);
861                 my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
862                 my $pid = open2($CO, $CI, $cipher_imp);
863
864                 my $calc_data = $iv; # CT[j]
865                 my $old_calc_data; # CT[j-1]
866                 my $old_old_calc_data; # CT[j-2]
867                 for (my $j = 0; $j < $iloop; ++$j) {
868                         $old_old_calc_data = $old_calc_data;
869                         $old_calc_data = $calc_data;
870
871                         # $calc_data = AES($key, $calc_data);
872                         #print STDERR "source_data=", bin2hex($source_data), "\n";
873                         syswrite $CI, $source_data or die;
874                         my $len = sysread $CO, $calc_data, $bufsize;
875                         #print STDERR "len=$len, bufsize=$bufsize\n";
876                         die if $len ne $bufsize;
877                         #print STDERR "calc_data=", bin2hex($calc_data), "\n";
878
879                         if ( (!$enc && $ciph =~ /des/) ||
880                              $ciph =~ /rc4/ ) {
881                                 #TDES in decryption mode and RC4 have a special rule
882                                 $source_data = $calc_data;
883                         } else {
884                                 $source_data = $old_calc_data;
885                         }
886                 }
887                 close $CO;
888                 close $CI;
889                 waitpid $pid, 0;
890
891                 if ($enc) {
892                         $out .= "CIPHERTEXT = ". bin2hex($calc_data). "\n\n";
893                 } else {
894                         $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n";
895                 }
896                 
897                 if ( $ciph =~ /aes/ ) {
898                         $key1 ^= substr($old_calc_data . $calc_data, -$keylen);
899                         #print STDERR bin2hex($key1)."\n";
900                 } elsif ( $ciph =~ /des/ ) {
901                         die "Wrong keylen $keylen" if ($keylen != 24);
902
903                         # $nkey needed as $key holds the concatenation of the
904                         # old key atm
905                         my $nkey = fix_key_parity(substr($key1,0,8) ^ $calc_data);
906                         #print STDERR "KEY1 = ". bin2hex($nkey)."\n";
907                         if (substr($key1,0,8) ne substr($key1,8,8)) {
908                                 #print STDERR "KEY2 recalc: KEY1==KEY3, KEY2 indep. or all KEYs are indep.\n";
909                                 $key2 = fix_key_parity((substr($key1,8,8) ^ $old_calc_data));
910                         } else {
911                                 #print STDERR "KEY2 recalc: KEY1==KEY2==KEY3\n";
912                                 $key2 = fix_key_parity((substr($key1,8,8) ^ $calc_data));
913                         }
914                         #print STDERR "KEY2 = ". bin2hex($key2)."\n";
915                         if ( substr($key1,0,8) eq substr($key1,16)) {
916                                 #print STDERR "KEY3 recalc: KEY1==KEY2==KEY3 or KEY1==KEY3, KEY2 indep.\n";
917                                 $key3 = fix_key_parity((substr($key1,16) ^ $calc_data));
918                         } else {
919                                 #print STDERR "KEY3 recalc: all KEYs are independent\n";
920                                 $key3 = fix_key_parity((substr($key1,16) ^ $old_old_calc_data));
921                         }
922                         #print STDERR "KEY3 = ". bin2hex($key3)."\n";
923
924                         # reset the first key - concardination happens at
925                         # beginning of loop
926                         $key1=$nkey;
927                 } elsif ($ciph =~ /rc4/ ) {
928                         $key1 ^= substr($calc_data, 0, 16);
929                         #print STDERR bin2hex($key1)."\n";
930                 } else {
931                         die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing";
932                 }
933
934                 if (! $enc && $ciph =~ /des/ ) {
935                         #TDES in decryption mode has a special rule
936                         $iv = $old_calc_data;
937                         $source_data = $calc_data;
938                 } elsif ( $ciph =~ /rc4/ ) {
939                         #No resetting of IV as the IV is all zero set initially (i.e. no IV)
940                         $source_data = $calc_data;
941                 } else {
942                         $iv = $calc_data;
943                         $source_data = $old_calc_data;
944                 }
945         }
946
947         return $out;
948 }
949
950 # Hash Monte Carlo Testing
951 # $1: Plaintext in hex form
952 # $2: hash
953 # return: string formatted as expected by CAVS
954 sub hash_mct($$) {
955         my $pt = shift;
956         my $cipher = shift;
957
958         my $out = "";
959
960         $out .= "Seed = $pt\n\n";
961         
962         for (my $j=0; $j<100; ++$j) {
963                 $out .= "COUNT = $j\n";
964                 my $md0=$pt;
965                 my $md1=$pt;
966                 my $md2=$pt;
967                 for (my $i=0; $i<1000; ++$i) {
968                         my $mi= $md0 . $md1 . $md2;
969                         $md0=$md1;
970                         $md1=$md2;
971                         $md2 = &$hash($mi, $cipher);
972                         $md2 =~ s/\n//;
973                 }
974                 $out .= "MD = $md2\n\n";
975                 $pt=$md2;
976         }
977
978         return $out;
979 }
980
981 # RSA SigGen test
982 # $1: Message to be signed in hex form
983 # $2: Hash algorithm
984 # $3: file name with RSA key in PEM form
985 # return: string formatted as expected by CAVS
986 sub rsa_siggen($$$) {
987         my $data = shift;
988         my $cipher = shift;
989         my $keyfile = shift;
990
991         my $out = "";
992         
993         $out .= "SHAAlg = $cipher\n";
994         $out .= "Msg = $data\n";
995         $out .= "S = " . &$rsa_sign($data, $cipher, $keyfile) . "\n";
996
997         return $out;
998 }
999
1000 # RSA SigVer test
1001 # $1: Message to be verified in hex form
1002 # $2: Hash algoritm
1003 # $3: Signature of message in hex form
1004 # $4: n of the RSA key in hex in hex form
1005 # $5: e of the RSA key in hex in hex form
1006 # return: string formatted as expected by CAVS
1007 sub rsa_sigver($$$$$) {
1008         my $data = shift;
1009         my $cipher = shift;
1010         my $signature = shift;
1011         my $n = shift;
1012         my $e = shift;
1013
1014         my $out = "";
1015
1016         $out .= "SHAAlg = $cipher\n";
1017         $out .= "e = $e\n";
1018         $out .= "Msg = $data\n";
1019         $out .= "S = $signature\n";
1020
1021         # XXX maybe a secure temp file name is better here
1022         # but since it is not run on a security sensitive
1023         # system, I hope that this is fine
1024         my $keyfile = "rsa_sigver.tmp.$$";
1025         gen_pubrsakey($keyfile, $n, $e);
1026
1027         my $sigfile = "$keyfile.sig";
1028         open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
1029         print FH hex2bin($signature);
1030         close FH;
1031
1032         $out .= "Result = " . (&$rsa_verify($data, $cipher, $keyfile, $sigfile) ? "P\n" : "F\n");
1033
1034         unlink($keyfile);
1035         unlink($sigfile);
1036
1037         return $out;
1038 }
1039
1040 # X9.31 RNG test
1041 # $1 key for the AES cipher
1042 # $2 DT value
1043 # $3 V value
1044 # $4 type ("VST", "MCT")
1045 # return: string formatted as expected by CAVS
1046 sub rngx931($$$$) {
1047         my $key=shift;
1048         my $dt=shift;
1049         my $v=shift;
1050         my $type=shift;
1051
1052         my $out = "Key = $key\n";
1053         $out   .= "DT = $dt\n";
1054         $out   .= "V = $v\n";
1055
1056         my $count = 1;
1057         $count = 10000 if ($type eq "MCT");
1058
1059         my $rnd_val = "";
1060
1061         # we read 16 bytes from RNG
1062         my $bufsize = 16;
1063
1064         my ($CO, $CI);
1065         my $rng_imp = &$state_rng($key, $dt, $v);
1066         my $pid = open2($CO, $CI, $rng_imp);
1067         for (my $i = 0; $i < $count; ++$i) {
1068                 my $len = sysread $CO, $rnd_val, $bufsize;
1069                 #print STDERR "len=$len, bufsize=$bufsize\n";
1070                 die "len=$len != bufsize=$bufsize" if $len ne $bufsize;
1071                 #print STDERR "calc_data=", bin2hex($rnd_val), "\n";
1072         }
1073         close $CO;
1074         close $CI;
1075         waitpid $pid, 0;
1076
1077         $out .= "R = " . bin2hex($rnd_val) . "\n\n";
1078
1079         return $out;
1080 }
1081
1082 ##############################################################
1083 # Parser of input file and generator of result file
1084 #
1085
1086 sub usage() {
1087
1088         print STDERR "Usage:
1089 $0 [-R] <CAVS-test vector file>
1090
1091 -R  execution of ARCFOUR instead of OpenSSL";
1092
1093 }
1094
1095 # Parser of CAVS test vector file
1096 # $1: Test vector file
1097 # $2: Output file for test results
1098 # return: nothing
1099 sub parse($$) {
1100         my $infile = shift;
1101         my $outfile = shift;
1102
1103         my $out = "";
1104
1105         # Do I need to generate the key?
1106         my $rsa_keygen = 0;
1107
1108         # this is my cipher/hash type
1109         my $cipher = "";
1110
1111         # Test type
1112         # 1 - cipher known answer test
1113         # 2 - cipher Monte Carlo test
1114         # 3 - hash known answer test
1115         # 4 - hash Monte Carlo test
1116         # 5 - RSA signature generation
1117         # 6 - RSA signature verification
1118         my $tt = 0;
1119
1120         # Variables for tests
1121         my $keytype = ""; # we can have "KEY", "KEYs", "KEY1"
1122         my $key1 = "";
1123         my $key2 = undef; #undef needed for allowing
1124         my $key3 = undef; #the use of them as input variables
1125         my $pt = "";
1126         my $enc = 1;
1127         my $iv = "";
1128         my $len = undef; #see key2|3
1129         my $n = "";
1130         my $e = "";
1131         my $signature = "";
1132         my $rsa_keyfile = "";
1133         my $dt = "";
1134         my $v = "";
1135
1136         my $mode = "";
1137
1138         open(IN, "<$infile");
1139         while(<IN>) {
1140
1141                 my $line = $_;
1142                 chomp($line);
1143                 $line =~ s/\r//;
1144
1145                 my $keylen = "";
1146
1147                 # Mode and type check
1148                 # consider the following parsed line
1149                 # '# AESVS MCT test data for CBC'
1150                 # '# TDES Multi block Message Test for CBC'
1151                 # '# INVERSE PERMUTATION - KAT for CBC'
1152                 # '# SUBSTITUTION TABLE - KAT for CBC'
1153                 # '# TDES Monte Carlo (Modes) Test for CBC'
1154                 # '#  "SHA-1 Monte" information for "IBMRHEL5"'
1155                 # '# "SigVer PKCS#1 Ver 1.5" information for "IBMRHEL5"'
1156                 # '# "SigGen PKCS#1 Ver 1.5" information for "IBMRHEL5"'
1157                 # '#RC4VS MCT test data'
1158                 
1159                 # avoid false positives from user specified 'for "PRODUCT"' strings
1160                 my $tmpline = $line;
1161                 $tmpline =~ s/ for ".*"//;
1162
1163                 ##### Extract cipher
1164                 # XXX there may be more - to be added
1165                 if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-1|SigGen|SigVer|RC4VS|ANSI X9\.31)/) {
1166                         if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
1167                         elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
1168                         elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
1169                         elsif ($tmpline =~ /CFB/)   { $mode="cfb"; }
1170                         #we do not need mode as the cipher is already clear
1171                         elsif ($tmpline =~ /SHA-1/) { $cipher="sha1"; }
1172                         #we do not need mode as the cipher is already clear
1173                         elsif ($tmpline =~ /RC4VS/) { $cipher="rc4"; }
1174                         elsif ($tmpline =~ /SigGen|SigVer/) {
1175                                 die "Error: X9.31 is not supported"
1176                                         if ($tmpline =~ /X9/);
1177                                 $cipher="sha1"; #place holder - might be overwritten later
1178                         }
1179
1180                         # RSA Key Generation test
1181                         if ($tmpline =~ /SigGen/) {
1182                                 $rsa_keygen = 1;
1183                         }
1184                         if ($tmpline =~ /^#.*AESVS/) {
1185                                 # AES cipher (part of it)
1186                                 $cipher="aes";
1187                         }
1188                         if ($tmpline =~ /^#.*(TDES|KAT)/) {
1189                                 # TDES cipher (full definition)
1190                                 # the FIPS-140 test generator tool does not produce
1191                                 # machine readable output!
1192                                 if ($mode eq "cbc") { $cipher="des-ede3-cbc"; }
1193                                 if ($mode eq "ecb") { $cipher="des-ede3"; }
1194                                 if ($mode eq "ofb") { $cipher="des-ede3-ofb"; }
1195                                 if ($mode eq "cfb") { $cipher="des-ede3-cfb"; }
1196                         }
1197
1198                         # check for RNG
1199                         if ($tmpline =~ /ANSI X9\.31/) {
1200                                 # change the tmpline to add the type of the
1201                                 # test which is ONLY visible from the file
1202                                 # name :-(
1203                                 if ($infile =~ /MCT\.req/) {
1204                                         $tmpline .= " MCT";
1205                                 } elsif ($infile =~ /VST\.req/) {
1206                                         $tmpline .= " VST";
1207                                 } else {
1208                                         die "Unexpected cipher type with $infile";
1209                                 }
1210                         }
1211
1212
1213                         ##### Identify the test type
1214                         if ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
1215                                 $tt = 8;
1216                                 die "Interface function state_rng for RNG MCT not defined for tested library"
1217                                         if (!defined($state_rng));
1218                         } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
1219                                 $tt = 7;
1220                                 die "Interface function state_rng for RNG KAT not defined for tested library"
1221                                         if (!defined($state_rng));
1222                         } elsif ($tmpline =~ /SigVer/ ) {
1223                                 $tt = 6;
1224                                 die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library"
1225                                         if (!defined($rsa_verify) || !defined($gen_rsakey));
1226                         } elsif ($tmpline =~ /SigGen/ ) {
1227                                 $tt = 5;
1228                                 die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library"
1229                                         if (!defined($rsa_sign) || !defined($gen_rsakey));
1230                         } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher eq "sha1") {
1231                                 $tt = 4;
1232                                 die "Interface function hash for Hashing not defined for tested library"
1233                                         if (!defined($hash));
1234                         } elsif ($tmpline =~ /Monte|MCT|Carlo/) {
1235                                 $tt = 2;
1236                                 die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
1237                                         if (!defined($state_cipher));
1238                         } elsif ($cipher eq "sha1" && $tt!=5 && $tt!=6) {
1239                                 $tt = 3;
1240                                 die "Interface function hash for Hashing not defined for tested library"
1241                                         if (!defined($hash));
1242                         } else {
1243                                 $tt = 1;
1244                                 die "Interface function encdec for Encryption/Decryption not defined for tested library"
1245                                         if (!defined($encdec));
1246                         }
1247                 }
1248
1249                 # This is needed as ARCFOUR does not operate with an IV
1250                 $iv = "00000000000000000000000000000000" if ($cipher eq "rc4"
1251                                                              && $iv eq "" );
1252
1253                 # we are now looking for the string
1254                 # '# Key Length : 256'
1255                 # found in AES
1256                 if ($tmpline =~ /^# Key Length.*?(128|192|256)/) {
1257                         if ($cipher eq "aes") {
1258                                 $cipher="$cipher-$1-$mode";
1259                         } else {
1260                                 die "Error: Key length $1 given for cipher $cipher which is unexpected";
1261                         }
1262                 }
1263
1264                 # Get the test data
1265                 if ($line =~ /^(KEY|KEYs|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
1266                         die "KEY seen twice - input file crap" if ($key1 ne "");
1267                         $keytype=$1;
1268                         $key1=$2;
1269                         $key1 =~ s/\s//g; #replace potential white spaces
1270                 }
1271                 elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES
1272                         die "First key not set, but got already second key - input file crap" if ($key1 eq "");
1273                         die "KEY2 seen twice - input file crap" if (defined($key2));
1274                         $key2=$1;
1275                         $key2 =~ s/\s//g; #replace potential white spaces
1276                 }
1277                 elsif ($line =~ /^KEY3\s*=\s*(.*)/) { # found in TDES
1278                         die "Second key not set, but got already third key - input file crap" if ($key2 eq "");
1279                         die "KEY2 seen twice - input file crap" if (defined($key3));
1280                         $key3=$1;
1281                         $key3 =~ s/\s//g; #replace potential white spaces
1282                 }
1283                 elsif ($line =~ /^IV\s*=\s*(.*)/) { # found in ciphers
1284                         die "IV seen twice - input file crap" if ($iv ne "");
1285                         $iv=$1;
1286                         $iv =~ s/\s//g; #replace potential white spaces
1287                 }
1288                 elsif ($line =~ /^PLAINTEXT\s*=\s*(.*)/) { # found in ciphers
1289                         if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
1290                                 die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
1291                                 $pt=$1;
1292                                 $pt =~ s/\s//g; #replace potential white spaces
1293                                 $enc=1;
1294                         }
1295                 }
1296                 elsif ($line =~ /^CIPHERTEXT\s*=\s*(.*)/) { # found in ciphers
1297                         if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
1298                                 die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
1299                                 $pt=$1;
1300                                 $pt =~ s/\s//g; #replace potential white spaces
1301                                 $enc=0;
1302                         }
1303                 }
1304                 elsif ($line =~ /^Len\s*=\s*(.*)/) { # found in hashs
1305                         $len=$1;
1306                 }
1307                 elsif ($line =~ /^(Msg|Seed)\s*=\s*(.*)/) { # found in hashs
1308                         die "Msg/Seed seen twice - input file crap" if ($pt ne "");
1309                         $pt=$2;
1310                 }
1311                 elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
1312                         $out .= $line . "\n"; # print it
1313                         # generate the private key with given bit length now
1314                         # as we have the required key length in bit
1315                         if ($tt == 5) {
1316                                 # XXX maybe a secure temp file name is better here
1317                                 # but since it is not run on a security sensitive
1318                                 # system, I hope that this is fine
1319                                 $rsa_keyfile = "rsa_siggen.tmp.$$";
1320                                 &$gen_rsakey($1, $rsa_keyfile);
1321                                 my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile");
1322                                 $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/;
1323                                 $out .= "\nn = $modulus\n";
1324                                 $out .= "\ne = 10001\n"
1325                         }
1326                 }
1327                 elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests
1328                         $cipher=$1;
1329                 }
1330                 elsif($line =~ /^n\s*=\s*(.*)/) { # found in RSA requests
1331                         $out .= $line . "\n";
1332                         $n=$1;
1333                 }
1334                 elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests
1335                         $e=$1;
1336                 }
1337                 elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests
1338                         die "S seen twice - input file crap" if ($signature ne "");
1339                         $signature=$1;
1340                 }
1341                 elsif ($line =~ /^DT\s*=\s*(.*)/) { # X9.31 RNG requests
1342                         die "DT seen twice - check input file"
1343                                 if ($dt ne "");
1344                         $dt=$1;
1345                 }
1346                 elsif ($line =~ /^V\s*=\s*(.*)/) { # X9.31 RNG requests
1347                         die "V seen twice - check input file"
1348                                 if ($v ne "");
1349                         $v=$1;
1350                 }
1351                 else {
1352                         $out .= $line . "\n";
1353                 }
1354
1355                 # call tests if all input data is there
1356                 if ($tt == 1) {
1357                         if ($key1 ne "" && $iv ne "" && $pt ne "" && $cipher ne "") {
1358                                 $out .= kat($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
1359                                 $keytype = "";
1360                                 $key1 = "";
1361                                 $key2 = undef;
1362                                 $key3 = undef;
1363                                 $iv = "";
1364                                 $pt = "";
1365                         }
1366                 }
1367                 elsif ($tt == 2) {
1368                         if ($key1 ne "" && $iv ne "" && $pt ne "" && $cipher ne "") {
1369                                 $out .= crypto_mct($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
1370                                 $keytype = "";
1371                                 $key1 = "";
1372                                 $key2 = undef;
1373                                 $key3 = undef;
1374                                 $iv = "";
1375                                 $pt = "";
1376                         }
1377                 }
1378                 elsif ($tt == 3) {
1379                         if ($pt ne "" && $cipher ne "") {
1380                                 $out .= hash_kat($pt, $cipher, $len);
1381                                 $pt = "";
1382                                 $len = undef;
1383                         }
1384                 }
1385                 elsif ($tt == 4) {
1386                         if ($pt ne "" && $cipher ne "") {
1387                                 $out .= hash_mct($pt, $cipher);
1388                                 $pt = "";
1389                         }
1390                 }
1391                 elsif ($tt == 5) {
1392                         if ($pt ne "" && $cipher ne "" && $rsa_keyfile ne "") {
1393                                 $out .= rsa_siggen($pt, $cipher, $rsa_keyfile);
1394                                 $pt = "";
1395                         }
1396                 }
1397                 elsif ($tt == 6) {
1398                         if ($pt ne "" && $cipher ne "" && $signature ne "" && $n ne "" && $e ne "") {
1399                                 $out .= rsa_sigver($pt, $cipher, $signature, $n, $e);
1400                                 $pt = "";
1401                                 $signature = "";
1402                         }
1403                 }
1404                 elsif ($tt == 7 ) {
1405                         if ($key1 ne "" && $dt ne "" && $v ne "") {
1406                                 $out .= rngx931($key1, $dt, $v, "VST");
1407                                 $key1 = "";
1408                                 $dt = "";
1409                                 $v = "";
1410                         }
1411                 }
1412                 elsif ($tt == 8 ) {
1413                         if ($key1 ne "" && $dt ne "" && $v ne "") {
1414                                 $out .= rngx931($key1, $dt, $v, "MCT");
1415                                 $key1 = "";
1416                                 $dt = "";
1417                                 $v = "";
1418                         }
1419                 }
1420                 elsif ($tt > 0) {
1421                         die "Test case $tt not defined";
1422                 }
1423         }
1424
1425         close IN;
1426         $out =~ s/\n/\r\n/g; # make it a dos file
1427         open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
1428         print OUT $out;
1429         close OUT;
1430
1431 }
1432
1433 # Signalhandler
1434 sub cleanup() {
1435         unlink("rsa_siggen.tmp.$$");
1436         unlink("rsa_sigver.tmp.$$");
1437         unlink("rsa_sigver.tmp.$$.sig");
1438         unlink("rsa_sigver.tmp.$$.der");
1439         unlink("rsa_sigver.tmp.$$.cnf");
1440         exit;
1441 }
1442
1443 ############################################################
1444 #
1445 # let us pretend to be C :-)
1446 sub main() {
1447
1448         usage() unless @ARGV;
1449
1450         getopts("R", \%opt) or die "bad option";
1451
1452         ##### Set library
1453
1454         #print STDERR "Using OpenSSL interface functions\n";
1455         #$encdec=\&openssl_encdec;
1456         #$rsa_sign=\&openssl_rsa_sign;
1457         #$rsa_verify=\&openssl_rsa_verify;
1458         #$gen_rsakey=\&openssl_gen_rsakey;
1459         #$hash=\&openssl_hash;
1460         #$state_cipher=\&openssl_state_cipher;
1461
1462         print STDERR "Using libgcrypt interface functions\n";
1463         $state_rng=\&libgcrypt_state_rng;
1464
1465         my $infile=$ARGV[0];
1466         die "Error: Test vector file $infile not found" if (! -f $infile);
1467
1468         my $outfile = $infile;
1469         # let us add .rsp regardless whether we could strip .req
1470         $outfile =~ s/\.req$//;
1471         if ($opt{'R'}) {
1472                 $outfile .= ".rc4";
1473         } else {
1474                 $outfile .= ".rsp";
1475         }
1476         if (-f $outfile) {
1477                 die "Output file $outfile could not be removed: $?"
1478                         unless unlink($outfile);
1479         }
1480         print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
1481
1482         #Signal handler
1483         $SIG{HUP} = \&cleanup;
1484         $SIG{INT} = \&cleanup;
1485         $SIG{QUIT} = \&cleanup;
1486         $SIG{TERM} = \&cleanup;
1487
1488         # Do the job
1489         parse($infile, $outfile);
1490
1491         unlink("rsa_siggen.tmp.$$");
1492
1493 }
1494
1495 ###########################################
1496 # Call it
1497 main();
1498 1;