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