mpi/ec: fix when 'unsigned long' is 32-bit but limb size is 64-bit
[libgcrypt.git] / tests / cavs_driver.pl
old mode 100644 (file)
new mode 100755 (executable)
index 55c238f..bc93feb
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 #
-# $Id: cavs_driver.pl 1236 2008-09-17 13:00:06Z smueller $
+# $Id: cavs_driver.pl 1497 2009-01-22 14:01:29Z smueller $
 #
 # CAVS test driver (based on the OpenSSL driver)
 # Written by: Stephan Müller <sm@atsec.com>
@@ -11,7 +11,7 @@
 # in the Software without restriction, including without limitation the rights
 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 # copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions: 
+# furnished to do so, subject to the following conditions:
 #
 # The above copyright notice and this permission notice shall be included in
 # all copies or substantial portions of the Software.
@@ -65,6 +65,7 @@
 #      SigVer15
 #      (SigVerRSA is not applicable for OpenSSL as X9.31 padding
 #              is not done through openssl dgst)
+#      KeyGen RSA X9.31
 #
 # SHA
 #      SHA[1|224|256|384|512]ShortMsg
 #      ANSI931_AES128MCT
 #      ANSI931_AES128VST
 #
+# DSA
+#      PQGGen
+#      SigGen
+#      SigVer
+#
 # RC4 (atsec developed tests)
 #      RC4KeyBD
 #      RC4MCT
@@ -105,7 +111,6 @@ use MIME::Base64;
 # Contains the command line options
 my %opt;
 
-
 #################################################################
 ##### Central interface functions to the external ciphers #######
 #################################################################
@@ -131,6 +136,24 @@ my %opt;
 # return en/decrypted data in hex form
 my $encdec;
 
+#
+# Derive an RSA key from the given X9.31 parameters.
+# $1: modulus size
+# $2: E   in hex form
+# $3: Xp1 in hex form
+# $4: Xp2 in hex form
+# $5: Xp  in hex form
+# $6: Xq1 in hex form
+# $7: Xq2 in hex form
+# $8: Xq  in hex form
+# return: string with the calculated values in hex format, where each value
+#        is separated from the previous with a \n in the following order:
+#         P\n
+#         Q\n
+#         N\n
+#         D\n
+my $rsa_derive;
+
 # Sign a message with RSA
 # $1: data to be signed in hex form
 # $2: Hash algo
@@ -143,7 +166,7 @@ my $rsa_sign;
 # $2: hash algo
 # $3: file holding the public RSA key in PEM format
 # $4: file holding the signature in binary form
-# return: 1 == verfied / 0 == not verified
+# return: 1 == verified / 0 == not verified
 my $rsa_verify;
 
 # generate a new private RSA key with the following properties:
@@ -171,6 +194,9 @@ my $hash;
 # $5: IV in binary form
 # return: command line to execute the application
 my $state_cipher;
+# the only difference of the DES version is that it implements the inner loop
+# of the TDES tests
+my $state_cipher_des;
 
 # supplying the call to the external cipher implementation
 # that is being used to keep STDIN and STDOUT open
@@ -196,6 +222,49 @@ my $state_rng;
 # return: calculated HMAC in hex format
 my $hmac;
 
+#
+# Generate the P, Q, G, Seed, counter, h (value used to generate g) values
+# for DSA
+# $1: modulus size
+# return: string with the calculated values in hex format, where each value
+#        is separated from the previous with a \n in the following order:
+#         P\n
+#         Q\n
+#         G\n
+#         Seed\n
+#         counter\n
+#         h
+my $dsa_pqggen;
+
+#
+# Generate an DSA public key from the provided parameters:
+# $1: Name of file to create
+# $2: P in hex form
+# $3: Q in hex form
+# $4: G in hex form
+# $5: Y in hex form
+my $dsa_genpubkey;
+
+# Verify a message with DSA
+# $1: data to be verified in hex form
+# $2: file holding the public DSA key in PEM format
+# $3: R value of the signature
+# $4: S value of the signature
+# return: 1 == verified / 0 == not verified
+my $dsa_verify;
+
+# generate a new DSA key with the following properties:
+#      PEM format
+# $1 keyfile name
+# return: file created, hash with keys of P, Q, G in hex format
+my $gen_dsakey;
+
+# Sign a message with DSA
+# $1: data to be signed in hex form
+# $2: Key file in PEM format with the private key
+# return: hash of digest information in hex format with Y, R, S as keys
+my $dsa_sign;
+
 ################################################################
 ##### OpenSSL interface functions
 ################################################################
@@ -206,8 +275,12 @@ sub openssl_encdec($$$$$) {
        my $enc = (shift) ? "-e" : "-d";
        my $data=shift;
 
+       # We only invoke the driver with the IV parameter, if we have
+       # an IV, otherwise, we skip it
+       $iv = "-iv $iv" if ($iv);
+
        $data=hex2bin($data);
-       my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc -iv $iv";
+       my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc $iv";
        $program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given
        $data=pipe_through_program($data,$program);
        return bin2hex($data);
@@ -271,7 +344,11 @@ sub openssl_state_cipher($$$$$) {
 
        my $enc = $encdec ? "-e": "-d";
 
-       my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." -iv ".bin2hex($iv);
+       # We only invoke the driver with the IV parameter, if we have
+       # an IV, otherwise, we skip it
+       $iv = "-iv ".bin2hex($iv) if ($iv);
+
+       my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." $iv";
        #for ARCFOUR, no IV must be given
        $out = "rc4 -k " . bin2hex($key) if $opt{'R'};
        return $out;
@@ -282,12 +359,135 @@ sub openssl_state_cipher($$$$$) {
 ###########################################################
 ###### libgcrypt implementation
 ###########################################################
+sub libgcrypt_encdec($$$$$) {
+       my $key=shift;
+       my $iv=shift;
+       my $cipher=shift;
+       my $enc = (shift) ? "encrypt" : "decrypt";
+       my $data=shift;
+
+       # We only invoke the driver with the IV parameter, if we have
+       # an IV, otherwise, we skip it
+       $iv = "--iv $iv" if ($iv);
+
+       my $program="fipsdrv --key $key $iv --algo $cipher $enc";
+
+       return pipe_through_program($data,$program);
+
+}
+
+sub libgcrypt_rsa_derive($$$$$$$$) {
+       my $n   = shift;
+       my $e   = shift;
+       my $xp1 = shift;
+       my $xp2 = shift;
+       my $xp  = shift;
+       my $xq1 = shift;
+       my $xq2 = shift;
+       my $xq  = shift;
+       my $sexp;
+       my @tmp;
+
+       $n = sprintf ("%u", $n);
+       $e = sprintf ("%u", hex($e));
+       $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")"
+               . "(rsa-use-e " . sprintf ("%u:%s", length($e), $e) . ")"
+               . "(derive-parms"
+               . "(Xp1 #$xp1#)"
+               . "(Xp2 #$xp2#)"
+               . "(Xp  #$xp#)"
+               . "(Xq1 #$xq1#)"
+               . "(Xq2 #$xq2#)"
+               . "(Xq  #$xq#))))\n";
+
+       return pipe_through_program($sexp, "fipsdrv rsa-derive");
+}
+
+
+sub libgcrypt_rsa_sign($$$) {
+       my $data = shift;
+       my $hashalgo = shift;
+       my $keyfile = shift;
+
+       die "ARCFOUR not available for RSA" if $opt{'R'};
+
+       return pipe_through_program($data,
+               "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign");
+}
+
+sub libgcrypt_rsa_verify($$$$) {
+       my $data = shift;
+       my $hashalgo = shift;
+       my $keyfile = shift;
+       my $sigfile = shift;
+
+       die "ARCFOUR not available for RSA" if $opt{'R'};
+       $data = pipe_through_program($data,
+               "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify");
+
+       # Parse through the output information
+       return ($data =~ /GOOD signature/);
+}
+
+sub libgcrypt_gen_rsakey($$) {
+       my $keylen = shift;
+       my $file = shift;
+
+       die "ARCFOUR not available for RSA" if $opt{'R'};
+       my @args = ("fipsdrv --keysize $keylen rsa-gen > $file");
+       system(@args) == 0
+               or die "system @args failed: $?";
+       die "system @args failed: file $file not created" if (! -f $file);
+}
+
+sub libgcrypt_hash($$) {
+       my $pt = shift;
+       my $hashalgo = shift;
+
+       my $program = "fipsdrv --algo $hashalgo digest";
+       die "ARCFOUR not available for hashes" if $opt{'R'};
+
+       return pipe_through_program($pt, $program);
+}
+
+sub libgcrypt_state_cipher($$$$$) {
+       my $cipher = shift;
+       my $enc = (shift) ? "encrypt": "decrypt";
+       my $bufsize = shift;
+       my $key = shift;
+       my $iv = shift;
+
+       # We only invoke the driver with the IV parameter, if we have
+       # an IV, otherwise, we skip it
+       $iv = "--iv ".bin2hex($iv) if ($iv);
+
+       my $program="fipsdrv --binary --key ".bin2hex($key)." $iv --algo '$cipher' --chunk '$bufsize' $enc";
+
+       return $program;
+}
+
+sub libgcrypt_state_cipher_des($$$$$) {
+       my $cipher = shift;
+       my $enc = (shift) ? "encrypt": "decrypt";
+       my $bufsize = shift;
+       my $key = shift;
+       my $iv = shift;
+
+       # We only invoke the driver with the IV parameter, if we have
+       # an IV, otherwise, we skip it
+       $iv = "--iv ".bin2hex($iv) if ($iv);
+
+       my $program="fipsdrv --algo '$cipher' --mct-server $enc";
+
+       return $program;
+}
+
 sub libgcrypt_state_rng($$$) {
        my $key = shift;
        my $dt = shift;
        my $v = shift;
 
-       return "fipsrngdrv --binary --loop $key $v $dt";
+       return "fipsdrv --binary --loop --key $key --iv $v --dt $dt random";
 }
 
 sub libgcrypt_hmac($$$$) {
@@ -296,12 +496,116 @@ sub libgcrypt_hmac($$$$) {
        my $msg = shift;
        my $hashtype = shift;
 
-       die "libgcrypt HMAC test not yet implemented: key $key, maclen $maclen, msg $msg, hashtype $hashtype";
-       
+       my $program = "fipsdrv --key $key --algo $hashtype hmac-sha";
+       return pipe_through_program($msg, $program);
+}
+
+sub libgcrypt_dsa_pqggen($) {
+       my $mod = shift;
+
+       my $program = "fipsdrv --keysize $mod dsa-pqg-gen";
+       return pipe_through_program("", $program);
+}
+
+sub libgcrypt_gen_dsakey($) {
+       my $file = shift;
+
+       my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
+       my $tmp;
+       my %ret;
+
+       die "ARCFOUR not available for DSA" if $opt{'R'};
+
+       $tmp = pipe_through_program("", $program);
+       die "dsa key gen failed: file $file not created" if (! -f $file);
+
+       @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
+       return %ret;
+}
+
+sub libgcrypt_dsa_genpubkey($$$$$) {
+       my $filename = shift;
+       my $p = shift;
+       my $q = shift;
+       my $g = shift;
+       my $y = shift;
+
+       my $sexp;
+
+       $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))";
+
+       open(FH, ">", $filename) or die;
+       print FH $sexp;
+       close FH;
+}
+
+sub libgcrypt_dsa_sign($$) {
+       my $data = shift;
+       my $keyfile = shift;
+       my $tmp;
+       my %ret;
+
+       die "ARCFOUR not available for DSA" if $opt{'R'};
+
+       $tmp = pipe_through_program($data, "fipsdrv --key $keyfile dsa-sign");
+       @ret{'Y', 'R', 'S'} = split(/\n/, $tmp);
+       return %ret;
+}
+
+sub libgcrypt_dsa_verify($$$$) {
+       my $data = shift;
+       my $keyfile = shift;
+       my $r = shift;
+       my $s = shift;
+
+       my $ret;
+
+       die "ARCFOUR not available for DSA" if $opt{'R'};
+
+       my $sigfile = "$keyfile.sig";
+       open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
+       print FH "(sig-val(dsa(r #$r#)(s #$s#)))";
+       close FH;
+
+       $ret = pipe_through_program($data,
+               "fipsdrv --key $keyfile --signature $sigfile dsa-verify");
+       unlink ($sigfile);
+       # Parse through the output information
+       return ($ret =~ /GOOD signature/);
 }
 
 ######### End of libgcrypt implementation ################
 
+################################################################
+###### Vendor1 interface functions
+################################################################
+
+sub vendor1_encdec($$$$$) {
+       my $key=shift;
+       my $iv=shift;
+       my $cipher=shift;
+       my $enc = (shift) ? "encrypt" : "decrypt";
+       my $data=shift;
+
+       $data=hex2bin($data);
+       my $program = "./aes $enc $key";
+       $data=pipe_through_program($data,$program);
+       return bin2hex($data);
+}
+
+sub vendor1_state_cipher($$$$$) {
+       my $cipher = shift;
+       my $encdec = shift;
+       my $bufsize = shift;
+       my $key = shift;
+       my $iv = shift;
+
+       $key = bin2hex($key);
+       my $enc = $encdec ? "encrypt": "decrypt";
+       my $out = "./aes $enc $key $bufsize";
+       return $out;
+}
+
 ##### No other interface functions below this point ######
 ##########################################################
 
@@ -319,7 +623,7 @@ sub pipe_through_program($@) {
 
        my ($CO, $CI);
        my $pid = open2($CO, $CI, @args);
-       
+
        my $out = "";
        my $len = length($in);
        my $first = 1;
@@ -355,7 +659,7 @@ sub pipe_through_program($@) {
        }
        close $CO or die "broken pipe: $!";
        waitpid $pid, 0;
-       
+
        return $out;
 }
 
@@ -418,39 +722,6 @@ sub fix_key_parity($) {
 }
 
 ####################################################
-# Encrypt/Decrypt routines
-
-# encryption
-# $1 key in hex form
-# $2 iv in hex form
-# $3 cipher
-# $4 data in hex form
-# return encrypted data
-sub encrypt($$$$) {
-       my $key=shift;
-       my $iv=shift;
-       my $cipher=shift;
-       my $data=shift;
-
-       return &$encdec($key, $iv, $cipher, 1, $data);
-}
-
-# decryption
-# $1 key in hex form
-# $2 iv in hex form
-# $3 cipher
-# $4 data in hex form
-# return encrypted data
-sub decrypt($$$$) {
-       my $key=shift;
-       my $iv=shift;
-       my $cipher=shift;
-       my $data=shift;
-
-       return &$encdec($key, $iv, $cipher, 0, $data);
-}
-
-####################################################
 # DER/PEM utility functions
 # Cf. http://www.columbia.edu/~ariel/ssleay/layman.html
 
@@ -610,7 +881,7 @@ sub der_pos_bigint($) {
 # returns number as signed DER integer encoding
 sub der_int($) {
        my $n = shift;
-       
+
        return der_bigint(int_base256_signed($n));
 }
 
@@ -687,11 +958,11 @@ sub der_unit_test {
 # OpenSSL missing functionality workarounds
 
 ## Format of an RSA public key:
-#    0:d=0  hl=3 l= 159 cons: SEQUENCE          
-#    3:d=1  hl=2 l=  13 cons:  SEQUENCE          
+#    0:d=0  hl=3 l= 159 cons: SEQUENCE
+#    3:d=1  hl=2 l=  13 cons:  SEQUENCE
 #    5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
-#   16:d=2  hl=2 l=   0 prim:   NULL              
-#   18:d=1  hl=3 l= 141 prim:  BIT STRING        
+#   16:d=2  hl=2 l=   0 prim:   NULL
+#   18:d=1  hl=3 l= 141 prim:  BIT STRING
 #                              [ sequence: INTEGER (n), INTEGER (e) ]
 
 # generate RSA pub key in PEM format
@@ -802,14 +1073,14 @@ sub kat($$$$$$$$) {
                $out .= "KEY3 = $key3\n";
                $key1= $key1 . $key3;
        }
-       
-       $out .= "IV = $iv\n";
+
+       $out .= "IV = $iv\n" if (defined($iv) && $iv ne "");
        if ($enc) {
                $out .= "PLAINTEXT = $pt\n";
-               $out .= "CIPHERTEXT = " . encrypt($key1, $iv, $cipher, $pt) . "\n";
+               $out .= "CIPHERTEXT = " . &$encdec($key1, $iv, $cipher, 1, $pt) . "\n";
        } else {
                $out .= "CIPHERTEXT = $pt\n";
-               $out .= "PLAINTEXT = " . decrypt($key1, $iv, $cipher, $pt) . "\n";
+               $out .= "PLAINTEXT = " . &$encdec($key1, $iv, $cipher, 0, $pt) . "\n";
        }
 
        return $out;
@@ -828,7 +1099,9 @@ sub hash_kat($$$) {
        my $out = "";
        $out .= "Len = $len\n" if (defined($len));
        $out .= "Msg = $pt\n";
-       $out .= "MD = " . &$hash($pt, $cipher);
+
+       $pt = "" if(!$len);
+       $out .= "MD = " . &$hash($pt, $cipher) . "\n";
        return $out;
 }
 
@@ -866,7 +1139,7 @@ sub hmac_kat($$$$) {
        $out .= "Tlen = $tlen\n";
        $out .= "Key = $key\n";
        $out .= "Msg = $msg\n";
-       $out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n\n";
+       $out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n";
 
        return $out;
 }
@@ -922,7 +1195,8 @@ sub crypto_mct($$$$$$$$) {
                }
                my $keylen = length($key1);
 
-                $out .= "IV = ". bin2hex($iv). "\n";
+                $out .= "IV = ". bin2hex($iv) . "\n"
+                       if (defined($iv) && $iv ne "");
 
                 if ($enc) {
                         $out .= "PLAINTEXT = ". bin2hex($source_data). "\n";
@@ -931,31 +1205,61 @@ sub crypto_mct($$$$$$$$) {
                 }
                 my ($CO, $CI);
                my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
+               $cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/);
                 my $pid = open2($CO, $CI, $cipher_imp);
 
                 my $calc_data = $iv; # CT[j]
                 my $old_calc_data; # CT[j-1]
                 my $old_old_calc_data; # CT[j-2]
-                for (my $j = 0; $j < $iloop; ++$j) {
-                       $old_old_calc_data = $old_calc_data;
-                        $old_calc_data = $calc_data;
-
-                       # $calc_data = AES($key, $calc_data);
-                       #print STDERR "source_data=", bin2hex($source_data), "\n";
-                       syswrite $CI, $source_data or die;
-                       my $len = sysread $CO, $calc_data, $bufsize;
-                       #print STDERR "len=$len, bufsize=$bufsize\n";
-                       die if $len ne $bufsize;
-                       #print STDERR "calc_data=", bin2hex($calc_data), "\n";
-
-                       if ( (!$enc && $ciph =~ /des/) ||
-                            $ciph =~ /rc4/ ) {
-                               #TDES in decryption mode and RC4 have a special rule
-                               $source_data = $calc_data;
-                       } else {
-                               $source_data = $old_calc_data;
-                       }
-                }
+               my $next_source;
+
+               # TDES inner loop implements logic within driver
+               if ($cipher =~ /des/) {
+                       # Need to provide a dummy IV in case of ECB mode.
+                       my $iv_arg = (defined($iv) && $iv ne "")
+                                       ? bin2hex($iv)
+                                       : "00"x(length($source_data));
+                       print $CI "1\n"
+                                 .$iloop."\n"
+                                 .bin2hex($key1)."\n"
+                                 .$iv_arg."\n"
+                                 .bin2hex($source_data)."\n\n" or die;
+                       chomp(my $line = <$CO>);
+                       $calc_data = hex2bin($line);
+                       chomp($line = <$CO>);
+                       $old_calc_data = hex2bin($line);
+                       chomp($line = <$CO>);
+                       $old_old_calc_data = hex2bin($line);
+                       chomp($line = <$CO>);
+                       $iv = hex2bin($line) if (defined($iv) && $iv ne "");
+                       chomp($line = <$CO>);
+                       $next_source = hex2bin($line);
+                       # Skip over empty line.
+                       $line = <$CO>;
+               } else {
+                       for (my $j = 0; $j < $iloop; ++$j) {
+                               $old_old_calc_data = $old_calc_data;
+                               $old_calc_data = $calc_data;
+
+                               #print STDERR "source_data=", bin2hex($source_data), "\n";
+                               syswrite $CI, $source_data or die $!;
+                               my $len = sysread $CO, $calc_data, $bufsize;
+
+                               #print STDERR "len=$len, bufsize=$bufsize\n";
+                               die if $len ne $bufsize;
+                               #print STDERR "calc_data=", bin2hex($calc_data), "\n";
+
+                               if ( (!$enc && $ciph =~ /des/) ||
+                                    $ciph =~ /rc4/ ||
+                                    $cipher =~ /ecb/ ) {
+                                       #TDES in decryption mode, RC4 and ECB mode
+                                       #have a special rule
+                                       $source_data = $calc_data;
+                               } else {
+                                       $source_data = $old_calc_data;
+                               }
+                       }
+               }
                 close $CO;
                 close $CI;
                 waitpid $pid, 0;
@@ -965,7 +1269,7 @@ sub crypto_mct($$$$$$$$) {
                 } else {
                         $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n";
                 }
-               
+
                if ( $ciph =~ /aes/ ) {
                        $key1 ^= substr($old_calc_data . $calc_data, -$keylen);
                        #print STDERR bin2hex($key1)."\n";
@@ -1003,13 +1307,18 @@ sub crypto_mct($$$$$$$$) {
                        die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing";
                }
 
-               if (! $enc && $ciph =~ /des/ ) {
+               if ($cipher =~ /des-ede3-ofb/) {
+                        $source_data = $source_data ^ $next_source;
+               } elsif (!$enc && $cipher =~ /des-ede3-cfb/) {
+                       #TDES decryption CFB has a special rule
+                       $source_data = $next_source;
+               } elsif ( $ciph =~ /rc4/ || $cipher eq "des-ede3" || $cipher =~ /ecb/) {
+                       #No resetting of IV as the IV is all zero set initially (i.e. no IV)
+                       $source_data = $calc_data;
+               } elsif (! $enc && $ciph =~ /des/ ) {
                        #TDES in decryption mode has a special rule
                        $iv = $old_calc_data;
                        $source_data = $calc_data;
-               } elsif ( $ciph =~ /rc4/ ) {
-                       #No resetting of IV as the IV is all zero set initially (i.e. no IV)
-                       $source_data = $calc_data;
                } else {
                        $iv = $calc_data;
                        $source_data = $old_calc_data;
@@ -1030,13 +1339,14 @@ sub hash_mct($$) {
        my $out = "";
 
        $out .= "Seed = $pt\n\n";
-       
+
         for (my $j=0; $j<100; ++$j) {
                $out .= "COUNT = $j\n";
                my $md0=$pt;
                my $md1=$pt;
                my $md2=$pt;
                for (my $i=0; $i<1000; ++$i) {
+                       #print STDERR "outer loop $j; inner loop $i\n";
                        my $mi= $md0 . $md1 . $md2;
                        $md0=$md1;
                        $md1=$md2;
@@ -1061,17 +1371,17 @@ sub rsa_siggen($$$) {
        my $keyfile = shift;
 
        my $out = "";
-       
+
        $out .= "SHAAlg = $cipher\n";
        $out .= "Msg = $data\n";
-       $out .= "S = " . &$rsa_sign($data, $cipher, $keyfile) . "\n";
+       $out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n";
 
        return $out;
 }
 
 # RSA SigVer test
 # $1: Message to be verified in hex form
-# $2: Hash algoritm
+# $2: Hash algorithm
 # $3: Signature of message in hex form
 # $4: n of the RSA key in hex in hex form
 # $5: e of the RSA key in hex in hex form
@@ -1101,7 +1411,7 @@ sub rsa_sigver($$$$$) {
        print FH hex2bin($signature);
        close FH;
 
-       $out .= "Result = " . (&$rsa_verify($data, $cipher, $keyfile, $sigfile) ? "P\n" : "F\n");
+       $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n");
 
        unlink($keyfile);
        unlink($sigfile);
@@ -1109,6 +1419,48 @@ sub rsa_sigver($$$$$) {
        return $out;
 }
 
+# RSA X9.31 key generation test
+# $1 modulus size
+# $2 e
+# $3 xp1
+# $4 xp2
+# $5 Xp
+# $6 xq1
+# $7 xq2
+# $8 Xq
+# return: string formatted as expected by CAVS
+sub rsa_keygen($$$$$$$$) {
+       my $modulus = shift;
+       my $e = shift;
+       my $xp1 = shift;
+       my $xp2 = shift;
+       my $Xp = shift;
+       my $xq1 = shift;
+       my $xq2 = shift;
+       my $Xq = shift;
+
+       my $out = "";
+
+       my $ret = &$rsa_derive($modulus, $e, $xp1, $xp2, $Xp, $xq1, $xq2, $Xq);
+
+       my ($P, $Q, $N, $D) = split(/\n/, $ret);
+
+       $out .= "e = $e\n";
+       $out .= "xp1 = $xp1\n";
+       $out .= "xp2 = $xp2\n";
+       $out .= "Xp = $Xp\n";
+       $out .= "p = $P\n";
+       $out .= "xq1 = $xq1\n";
+       $out .= "xq2 = $xq2\n";
+       $out .= "Xq = $Xq\n";
+       $out .= "q = $Q\n";
+       $out .= "n = $N\n";
+       $out .= "d = $D\n\n";
+
+       return $out;
+
+}
+
 # X9.31 RNG test
 # $1 key for the AES cipher
 # $2 DT value
@@ -1151,6 +1503,101 @@ sub rngx931($$$$) {
        return $out;
 }
 
+# DSA PQGGen test
+# $1 modulus size
+# $2 number of rounds to perform the test
+# return: string formatted as expected by CAVS
+sub dsa_pqggen_driver($$) {
+       my $mod = shift;
+       my $rounds = shift;
+
+       my $out = "";
+       for(my $i=0; $i<$rounds; $i++) {
+               my $ret = &$dsa_pqggen($mod);
+               my ($P, $Q, $G, $Seed, $c, $H) = split(/\n/, $ret);
+               die "Return value does not contain all expected values of P, Q, G, Seed, c, H for dsa_pqggen"
+                       if (!defined($P) || !defined($Q) || !defined($G) ||
+                           !defined($Seed) || !defined($c) || !defined($H));
+
+               # now change the counter to decimal as CAVS wants decimal
+               # counter value although all other is HEX
+               $c = hex($c);
+
+               $out .= "P = $P\n";
+               $out .= "Q = $Q\n";
+               $out .= "G = $G\n";
+               $out .= "Seed = $Seed\n";
+               $out .= "c = $c\n";
+               $out .= "H = $H\n\n";
+       }
+
+       return $out;
+}
+
+
+# DSA SigGen test
+# $1: Message to be signed in hex form
+# $2: file name with DSA key in PEM form
+# return: string formatted as expected by CAVS
+sub dsa_siggen($$) {
+       my $data = shift;
+       my $keyfile = shift;
+
+       my $out = "";
+
+       my %ret = &$dsa_sign($data, $keyfile);
+
+       $out .= "Msg = $data\n";
+       $out .= "Y = " . $ret{'Y'} . "\n";
+       $out .= "R = " . $ret{'R'} . "\n";
+       $out .= "S = " . $ret{'S'} . "\n";
+
+       return $out;
+}
+
+
+# DSA signature verification
+# $1 modulus
+# $2 P
+# $3 Q
+# $4 G
+# $5 Y - public key
+# $6 r
+# $7 s
+# $8 message to be verified
+# return: string formatted as expected by CAVS
+sub dsa_sigver($$$$$$$$) {
+       my $modulus = shift;
+       my $p = shift;
+       my $q = shift;
+       my $g = shift;
+       my $y = shift;
+       my $r = shift;
+       my $s = shift;
+       my $msg = shift;
+
+       my $out = "";
+
+       #PQG are already printed - do not print them here
+
+       $out .= "Msg = $msg\n";
+       $out .= "Y = $y\n";
+       $out .= "R = $r\n";
+       $out .= "S = $s\n";
+
+       # XXX maybe a secure temp file name is better here
+       # but since it is not run on a security sensitive
+       # system, I hope that this is fine
+       my $keyfile = "dsa_sigver.tmp.$$";
+       &$dsa_genpubkey($keyfile, $p, $q, $g, $y);
+
+       $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n");
+
+       unlink($keyfile);
+
+       return $out;
+}
+
 ##############################################################
 # Parser of input file and generator of result file
 #
@@ -1158,10 +1605,16 @@ sub rngx931($$$$) {
 sub usage() {
 
        print STDERR "Usage:
-$0 [-R] <CAVS-test vector file>
-
--R  execution of ARCFOUR instead of OpenSSL";
-
+$0 [-R] [-D] [-I name] <CAVS-test vector file>
+
+-R     execution of ARCFOUR instead of OpenSSL
+-I NAME        Use interface style NAME:
+               openssl     OpenSSL (default)
+               libgcrypt   Libgcrypt
+-D     SigGen and SigVer are executed with DSA
+       Please note that the DSA CAVS vectors do not allow distinguishing
+       them from the RSA vectors. As the RSA test is the default, you have
+       to supply this option to apply the DSA logic";
 }
 
 # Parser of CAVS test vector file
@@ -1174,9 +1627,6 @@ sub parse($$) {
 
        my $out = "";
 
-       # Do I need to generate the key?
-       my $rsa_keygen = 0;
-
        # this is my cipher/hash type
        my $cipher = "";
 
@@ -1202,10 +1652,24 @@ sub parse($$) {
        my $e = "";
        my $signature = "";
        my $rsa_keyfile = "";
+       my $dsa_keyfile = "";
        my $dt = "";
        my $v = "";
        my $klen = "";
        my $tlen = "";
+       my $modulus = "";
+       my $capital_n = 0;
+       my $capital_p = "";
+       my $capital_q = "";
+       my $capital_g = "";
+       my $capital_y = "";
+       my $capital_r = "";
+       my $xp1 = "";
+       my $xp2 = "";
+       my $Xp = "";
+       my $xq1 = "";
+       my $xq2 = "";
+       my $Xq = "";
 
        my $mode = "";
 
@@ -1229,14 +1693,14 @@ sub parse($$) {
                # '# "SigVer PKCS#1 Ver 1.5" information for "IBMRHEL5"'
                # '# "SigGen PKCS#1 Ver 1.5" information for "IBMRHEL5"'
                # '#RC4VS MCT test data'
-               
+
                # avoid false positives from user specified 'for "PRODUCT"' strings
                my $tmpline = $line;
                $tmpline =~ s/ for ".*"//;
 
                ##### Extract cipher
                # XXX there may be more - to be added
-               if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested)/) {
+               if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA)/) {
                        if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
                        elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
                        elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
@@ -1255,10 +1719,6 @@ sub parse($$) {
                                $cipher="sha1"; #place holder - might be overwritten later
                        }
 
-                       # RSA Key Generation test
-                       if ($tmpline =~ /SigGen/) {
-                               $rsa_keygen = 1;
-                       }
                        if ($tmpline =~ /^#.*AESVS/) {
                                # AES cipher (part of it)
                                $cipher="aes";
@@ -1287,44 +1747,61 @@ sub parse($$) {
                                }
                        }
 
-
+                       if ($tt == 0) {
                        ##### Identify the test type
-                       if ($tmpline =~ /Hash sizes tested/) {
-                               $tt = 9;
-                               die "Interface function hmac for HMAC testing not defined for tested library"
-                                       if (!defined($hmac));
-                       } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
-                               $tt = 8;
-                               die "Interface function state_rng for RNG MCT not defined for tested library"
-                                       if (!defined($state_rng));
-                       } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
-                               $tt = 7;
-                               die "Interface function state_rng for RNG KAT not defined for tested library"
-                                       if (!defined($state_rng));
-                       } elsif ($tmpline =~ /SigVer/ ) {
-                               $tt = 6;
-                               die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library"
-                                       if (!defined($rsa_verify) || !defined($gen_rsakey));
-                       } elsif ($tmpline =~ /SigGen/ ) {
-                               $tt = 5;
-                               die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library"
-                                       if (!defined($rsa_sign) || !defined($gen_rsakey));
-                       } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher eq "sha") {
-                               $tt = 4;
-                               die "Interface function hash for Hashing not defined for tested library"
-                                       if (!defined($hash));
-                       } elsif ($tmpline =~ /Monte|MCT|Carlo/) {
-                               $tt = 2;
-                               die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
-                                       if (!defined($state_cipher));
-                       } elsif ($cipher eq "sha" && $tt!=5 && $tt!=6) {
-                               $tt = 3;
-                               die "Interface function hash for Hashing not defined for tested library"
-                                       if (!defined($hash));
-                       } else {
-                               $tt = 1;
-                               die "Interface function encdec for Encryption/Decryption not defined for tested library"
-                                       if (!defined($encdec));
+                               if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) {
+                                       $tt = 13;
+                                       die "Interface function rsa_derive for RSA key generation not defined for tested library"
+                                               if (!defined($rsa_derive));
+                               } elsif ($tmpline =~ /SigVer/ && $opt{'D'} ) {
+                                       $tt = 12;
+                                       die "Interface function dsa_verify or dsa_genpubkey for DSA verification not defined for tested library"
+                                               if (!defined($dsa_verify) || !defined($dsa_genpubkey));
+                               } elsif ($tmpline =~ /SigGen/ && $opt{'D'}) {
+                                       $tt = 11;
+                                       die "Interface function dsa_sign or gen_dsakey for DSA sign not defined for tested library"
+                                               if (!defined($dsa_sign) || !defined($gen_rsakey));
+                               } elsif ($tmpline =~ /PQGGen/) {
+                                       $tt = 10;
+                                       die "Interface function for DSA PQGGen testing not defined for tested library"
+                                               if (!defined($dsa_pqggen));
+                               } elsif ($tmpline =~ /Hash sizes tested/) {
+                                       $tt = 9;
+                                       die "Interface function hmac for HMAC testing not defined for tested library"
+                                               if (!defined($hmac));
+                               } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
+                                       $tt = 8;
+                                       die "Interface function state_rng for RNG MCT not defined for tested library"
+                                               if (!defined($state_rng));
+                               } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
+                                       $tt = 7;
+                                       die "Interface function state_rng for RNG KAT not defined for tested library"
+                                               if (!defined($state_rng));
+                               } elsif ($tmpline =~ /SigVer/ ) {
+                                       $tt = 6;
+                                       die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library"
+                                               if (!defined($rsa_verify) || !defined($gen_rsakey));
+                               } elsif ($tmpline =~ /SigGen/ ) {
+                                       $tt = 5;
+                                       die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library"
+                                               if (!defined($rsa_sign) || !defined($gen_rsakey));
+                               } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher =~ /^sha/) {
+                                       $tt = 4;
+                                       die "Interface function hash for Hashing not defined for tested library"
+                                               if (!defined($hash));
+                               } elsif ($tmpline =~ /Monte|MCT|Carlo/) {
+                                       $tt = 2;
+                                       die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
+                                               if (!defined($state_cipher) || !defined($state_cipher_des));
+                               } elsif ($cipher =~ /^sha/) {
+                                       $tt = 3;
+                                       die "Interface function hash for Hashing not defined for tested library"
+                                               if (!defined($hash));
+                               } else {
+                                       $tt = 1;
+                                       die "Interface function encdec for Encryption/Decryption not defined for tested library"
+                                               if (!defined($encdec));
+                               }
                        }
                }
 
@@ -1344,12 +1821,20 @@ sub parse($$) {
                }
 
                # Get the test data
-               if ($line =~ /^(KEY|KEYs|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
+               if ($line =~ /^(KEY|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
                        die "KEY seen twice - input file crap" if ($key1 ne "");
                        $keytype=$1;
                        $key1=$2;
                        $key1 =~ s/\s//g; #replace potential white spaces
                }
+               elsif ($line =~ /^(KEYs)\s*=\s*(.*)/) { # found in ciphers and RNG
+                       die "KEY seen twice - input file crap" if ($key1 ne "");
+                       $keytype=$1;
+                       $key1=$2;
+                       $key1 =~ s/\s//g; #replace potential white spaces
+                       $key2 = $key1;
+                       $key3 = $key1;
+               }
                elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES
                        die "First key not set, but got already second key - input file crap" if ($key1 eq "");
                        die "KEY2 seen twice - input file crap" if (defined($key2));
@@ -1391,19 +1876,26 @@ sub parse($$) {
                        $pt=$2;
                }
                elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
-                       $out .= $line . "\n"; # print it
+                       $modulus = $1;
+                       $out .= $line . "\n\n"; # print it
                        # generate the private key with given bit length now
                        # as we have the required key length in bit
-                       if ($tt == 5) {
+                       if ($tt == 11) {
+                               $dsa_keyfile = "dsa_siggen.tmp.$$";
+                               my %pqg = &$gen_dsakey($dsa_keyfile);
+                               $out .= "P = " . $pqg{'P'} . "\n";
+                               $out .= "Q = " . $pqg{'Q'} . "\n";
+                               $out .= "G = " . $pqg{'G'} . "\n";
+                       } elsif ( $tt == 5 ) {
                                # XXX maybe a secure temp file name is better here
                                # but since it is not run on a security sensitive
                                # system, I hope that this is fine
                                $rsa_keyfile = "rsa_siggen.tmp.$$";
-                               &$gen_rsakey($1, $rsa_keyfile);
+                               &$gen_rsakey($modulus, $rsa_keyfile);
                                my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile");
                                $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/;
-                               $out .= "\nn = $modulus\n";
-                               $out .= "\ne = 10001\n"
+                               $out .= "n = $modulus\n";
+                               $out .= "\ne = 10001\n"
                        }
                }
                elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests
@@ -1440,13 +1932,76 @@ sub parse($$) {
                                if ($tlen ne "");
                        $tlen=$1;
                }
+               elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA PQGGen
+                       die "N seen twice - check input file"
+                               if ($capital_n);
+                       $capital_n = $1;
+               }
+               elsif ($line =~ /^P\s*=\s*(.*)/) { #DSA SigVer
+                       die "P seen twice - check input file"
+                               if ($capital_p);
+                       $capital_p = $1;
+                       $out .= $line . "\n"; # print it
+               }
+               elsif ($line =~ /^Q\s*=\s*(.*)/) { #DSA SigVer
+                       die "Q seen twice - check input file"
+                               if ($capital_q);
+                       $capital_q = $1;
+                       $out .= $line . "\n"; # print it
+               }
+               elsif ($line =~ /^G\s*=\s*(.*)/) { #DSA SigVer
+                       die "G seen twice - check input file"
+                               if ($capital_g);
+                       $capital_g = $1;
+                       $out .= $line . "\n"; # print it
+               }
+               elsif ($line =~ /^Y\s*=\s*(.*)/) { #DSA SigVer
+                       die "Y seen twice - check input file"
+                               if ($capital_y);
+                       $capital_y = $1;
+               }
+               elsif ($line =~ /^R\s*=\s*(.*)/) { #DSA SigVer
+                       die "R seen twice - check input file"
+                               if ($capital_r);
+                       $capital_r = $1;
+               }
+               elsif ($line =~ /^xp1\s*=\s*(.*)/) { #RSA key gen
+                       die "xp1 seen twice - check input file"
+                               if ($xp1);
+                       $xp1 = $1;
+               }
+               elsif ($line =~ /^xp2\s*=\s*(.*)/) { #RSA key gen
+                       die "xp2 seen twice - check input file"
+                               if ($xp2);
+                       $xp2 = $1;
+               }
+               elsif ($line =~ /^Xp\s*=\s*(.*)/) { #RSA key gen
+                       die "Xp seen twice - check input file"
+                               if ($Xp);
+                       $Xp = $1;
+               }
+               elsif ($line =~ /^xq1\s*=\s*(.*)/) { #RSA key gen
+                       die "xq1 seen twice - check input file"
+                               if ($xq1);
+                       $xq1 = $1;
+               }
+               elsif ($line =~ /^xq2\s*=\s*(.*)/) { #RSA key gen
+                       die "xq2 seen twice - check input file"
+                               if ($xq2);
+                       $xq2 = $1;
+               }
+               elsif ($line =~ /^Xq\s*=\s*(.*)/) { #RSA key gen
+                       die "Xq seen twice - check input file"
+                               if ($Xq);
+                       $Xq = $1;
+               }
                else {
                        $out .= $line . "\n";
                }
 
                # call tests if all input data is there
                if ($tt == 1) {
-                       if ($key1 ne "" && $iv ne "" && $pt ne "" && $cipher ne "") {
+                       if ($key1 ne "" && $pt ne "" && $cipher ne "") {
                                $out .= kat($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
                                $keytype = "";
                                $key1 = "";
@@ -1457,7 +2012,7 @@ sub parse($$) {
                        }
                }
                elsif ($tt == 2) {
-                       if ($key1 ne "" && $iv ne "" && $pt ne "" && $cipher ne "") {
+                       if ($key1 ne "" && $pt ne "" && $cipher ne "") {
                                $out .= crypto_mct($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
                                $keytype = "";
                                $key1 = "";
@@ -1518,6 +2073,74 @@ sub parse($$) {
                                $pt = "";
                        }
                }
+               elsif ($tt == 10) {
+                       if ($modulus ne "" && $capital_n > 0) {
+                               $out .= dsa_pqggen_driver($modulus, $capital_n);
+                               #$mod is not resetted
+                               $capital_n = 0;
+                       }
+               }
+               elsif ($tt == 11) {
+                       if ($pt ne "" && $dsa_keyfile ne "") {
+                               $out .= dsa_siggen($pt, $dsa_keyfile);
+                               $pt = "";
+                       }
+               }
+               elsif ($tt == 12) {
+                       if ($modulus ne "" &&
+                           $capital_p ne "" &&
+                           $capital_q ne "" &&
+                           $capital_g ne "" &&
+                           $capital_y ne "" &&
+                           $capital_r ne "" &&
+                           $signature ne "" &&
+                           $pt ne "") {
+                               $out .= dsa_sigver($modulus,
+                                                  $capital_p,
+                                                  $capital_q,
+                                                  $capital_g,
+                                                  $capital_y,
+                                                  $capital_r,
+                                                  $signature,
+                                                  $pt);
+
+                               # We do not clear the domain values PQG and
+                               # the modulus value as they
+                               # are specified only once in a file
+                               # and we do not need to print them as they
+                               # are already printed above
+                               $capital_y = "";
+                               $capital_r = "";
+                               $signature = "";
+                               $pt = "";
+                       }
+               }
+               elsif ($tt == 13) {
+                       if($modulus ne "" &&
+                          $e ne "" &&
+                          $xp1 ne "" &&
+                          $xp2 ne "" &&
+                          $Xp ne "" &&
+                          $xq1 ne "" &&
+                          $xq2 ne "" &&
+                          $Xq ne "") {
+                               $out .= rsa_keygen($modulus,
+                                                  $e,
+                                                  $xp1,
+                                                  $xp2,
+                                                  $Xp,
+                                                  $xq1,
+                                                  $xq2,
+                                                  $Xq);
+                               $e = "";
+                               $xp1 = "";
+                               $xp2 = "";
+                               $Xp = "";
+                               $xq1 = "";
+                               $xq2 = "";
+                               $Xq = "";
+                       }
+               }
                elsif ($tt > 0) {
                        die "Test case $tt not defined";
                }
@@ -1538,6 +2161,9 @@ sub cleanup() {
        unlink("rsa_sigver.tmp.$$.sig");
        unlink("rsa_sigver.tmp.$$.der");
        unlink("rsa_sigver.tmp.$$.cnf");
+       unlink("dsa_siggen.tmp.$$");
+       unlink("dsa_sigver.tmp.$$");
+       unlink("dsa_sigver.tmp.$$.sig");
        exit;
 }
 
@@ -1548,21 +2174,38 @@ sub main() {
 
        usage() unless @ARGV;
 
-       getopts("R", \%opt) or die "bad option";
+       getopts("DRI:", \%opt) or die "bad option";
 
        ##### Set library
 
-       #print STDERR "Using OpenSSL interface functions\n";
-       #$encdec =              \&openssl_encdec;
-       #$rsa_sign =            \&openssl_rsa_sign;
-       #$rsa_verify =          \&openssl_rsa_verify;
-       #$gen_rsakey =          \&openssl_gen_rsakey;
-       #$hash =                \&openssl_hash;
-       #$state_cipher =        \&openssl_state_cipher;
-
-       print STDERR "Using libgcrypt interface functions\n";
-       $state_rng =    \&libgcrypt_state_rng;
-       $hmac =         \&libgcrypt_hmac;
+       if ( ! defined $opt{'I'} || $opt{'I'} eq 'openssl' ) {
+               print STDERR "Using OpenSSL interface functions\n";
+               $encdec =       \&openssl_encdec;
+               $rsa_sign =     \&openssl_rsa_sign;
+               $rsa_verify =   \&openssl_rsa_verify;
+               $gen_rsakey =   \&openssl_gen_rsakey;
+               $hash =         \&openssl_hash;
+               $state_cipher = \&openssl_state_cipher;
+       } elsif ( $opt{'I'} eq 'libgcrypt' ) {
+               print STDERR "Using libgcrypt interface functions\n";
+               $encdec =       \&libgcrypt_encdec;
+               $rsa_sign =     \&libgcrypt_rsa_sign;
+               $rsa_verify =   \&libgcrypt_rsa_verify;
+               $gen_rsakey =   \&libgcrypt_gen_rsakey;
+               $rsa_derive =   \&libgcrypt_rsa_derive;
+               $hash =         \&libgcrypt_hash;
+               $state_cipher = \&libgcrypt_state_cipher;
+               $state_cipher_des =     \&libgcrypt_state_cipher_des;
+               $state_rng =    \&libgcrypt_state_rng;
+               $hmac =         \&libgcrypt_hmac;
+               $dsa_pqggen =   \&libgcrypt_dsa_pqggen;
+               $gen_dsakey =   \&libgcrypt_gen_dsakey;
+               $dsa_sign =     \&libgcrypt_dsa_sign;
+               $dsa_verify =   \&libgcrypt_dsa_verify;
+               $dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
+        } else {
+                die "Invalid interface option given";
+        }
 
        my $infile=$ARGV[0];
        die "Error: Test vector file $infile not found" if (! -f $infile);
@@ -1590,7 +2233,7 @@ sub main() {
        # Do the job
        parse($infile, $outfile);
 
-       unlink("rsa_siggen.tmp.$$");
+       cleanup();
 
 }