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