f268f1
diff -up libgcrypt-1.5.3/cipher/dsa.c.cavs libgcrypt-1.5.3/cipher/dsa.c
f268f1
--- libgcrypt-1.5.3/cipher/dsa.c.cavs	2014-09-26 17:45:38.429674771 +0200
f268f1
+++ libgcrypt-1.5.3/cipher/dsa.c	2014-09-26 17:45:38.433674862 +0200
6e4d5d
@@ -479,7 +479,6 @@ generate_fips186 (DSA_secret_key *sk, un
6e4d5d
             initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1,
6e4d5d
                                                     &initial_seed.seedlen);
6e4d5d
         }
6e4d5d
-      
6e4d5d
       if (use_fips186_2)
6e4d5d
         ec = _gcry_generate_fips186_2_prime (nbits, qbits, 
6e4d5d
                                            initial_seed.seed, 
6e4d5d
@@ -487,13 +486,22 @@ generate_fips186 (DSA_secret_key *sk, un
6e4d5d
                                            &prime_q, &prime_p,
6e4d5d
                                            r_counter,
6e4d5d
                                            r_seed, r_seedlen);
6e4d5d
-      else
6e4d5d
+      else if (!domain->p || !domain->q)
6e4d5d
         ec = _gcry_generate_fips186_3_prime (nbits, qbits,
6e4d5d
                                           initial_seed.seed,
6e4d5d
                                           initial_seed.seedlen,
6e4d5d
                                           &prime_q, &prime_p,
6e4d5d
                                           r_counter,
6e4d5d
                                           r_seed, r_seedlen, NULL);
6e4d5d
+      else
6e4d5d
+        {
6e4d5d
+          /* Domain parameters p and q are given; use them.  */
6e4d5d
+          prime_p = mpi_copy (domain->p);
6e4d5d
+          prime_q = mpi_copy (domain->q);
6e4d5d
+          gcry_assert (mpi_get_nbits (prime_p) == nbits);
6e4d5d
+          gcry_assert (mpi_get_nbits (prime_q) == qbits);
6e4d5d
+          ec = 0;
6e4d5d
+        }
6e4d5d
       gcry_sexp_release (initial_seed.sexp);
6e4d5d
       if (ec)
6e4d5d
         goto leave;
6e4d5d
@@ -784,13 +792,12 @@ dsa_generate_ext (int algo, unsigned int
6e4d5d
           gcry_sexp_release (l1);
6e4d5d
           gcry_sexp_release (domainsexp);
6e4d5d
 
6e4d5d
-          /* Check that all domain parameters are available.  */
6e4d5d
-          if (!domain.p || !domain.q || !domain.g)
6e4d5d
+          /* Check that p and q domain parameters are available.  */
6e4d5d
+          if (!domain.p || !domain.q || (!domain.g && !use_fips186))
6e4d5d
             {
6e4d5d
               gcry_mpi_release (domain.p);
6e4d5d
               gcry_mpi_release (domain.q);
6e4d5d
               gcry_mpi_release (domain.g);
6e4d5d
-              gcry_sexp_release (deriveparms);
6e4d5d
               return GPG_ERR_MISSING_VALUE;
6e4d5d
             }
6e4d5d
 
f268f1
diff -up libgcrypt-1.5.3/tests/cavs_driver.pl.cavs libgcrypt-1.5.3/tests/cavs_driver.pl
f268f1
--- libgcrypt-1.5.3/tests/cavs_driver.pl.cavs	2013-05-22 18:02:55.000000000 +0200
f268f1
+++ libgcrypt-1.5.3/tests/cavs_driver.pl	2014-10-21 09:38:34.250691408 +0200
6e4d5d
@@ -1,9 +1,11 @@
6e4d5d
 #!/usr/bin/env perl
6e4d5d
 #
6e4d5d
-# $Id: cavs_driver.pl 1497 2009-01-22 14:01:29Z smueller $
6e4d5d
+# $Id: cavs_driver.pl 2124 2010-12-20 07:56:30Z smueller $
6e4d5d
 #
6e4d5d
 # CAVS test driver (based on the OpenSSL driver)
6e4d5d
 # Written by: Stephan Müller <sm@atsec.com>
6e4d5d
+#	      Werner Koch <wk@g10code.com> (libgcrypt interface)
6e4d5d
+#	      Tomas Mraz <tmraz@redhat.com> (addition of DSA2)
6e4d5d
 # Copyright (c) atsec information security corporation
6e4d5d
 #
6e4d5d
 # Permission is hereby granted, free of charge, to any person obtaining a copy
6e4d5d
@@ -85,13 +87,16 @@
6e4d5d
 #	T[CBC|CFB??|ECB|OFB]varkey
6e4d5d
 #	T[CBC|CFB??|ECB|OFB]invperm
6e4d5d
 #	T[CBC|CFB??|ECB|OFB]vartext
6e4d5d
+# WARNING: TDES in CFB and OFB mode problems see below
6e4d5d
 #
6e4d5d
 # ANSI X9.31 RNG
6e4d5d
 # 	ANSI931_AES128MCT
6e4d5d
 # 	ANSI931_AES128VST
6e4d5d
 #
6e4d5d
-# DSA
6e4d5d
+# DSA2
6e4d5d
 # 	PQGGen
6e4d5d
+#	PQGVer
6e4d5d
+#	KeyPair
6e4d5d
 # 	SigGen
6e4d5d
 # 	SigVer
6e4d5d
 #
6e4d5d
@@ -101,6 +106,36 @@
6e4d5d
 # 	RC4PltBD
6e4d5d
 # 	RC4REGT
6e4d5d
 #
6e4d5d
+#
6e4d5d
+# TDES MCT for CFB and OFB:
6e4d5d
+# -------------------------
6e4d5d
+# The inner loop cannot be handled by this script. If you want to have tests
6e4d5d
+# for these cipher types, implement your own inner loop and add it to
6e4d5d
+# crypto_mct.
6e4d5d
+#
6e4d5d
+# the value $next_source in crypto_mct is NOT set by the standard implementation
6e4d5d
+# of this script. It would need to be set as follows for these two (code take
6e4d5d
+# from fipsdrv.c from libgcrypt - the value input at the end will contain the
6e4d5d
+# the value for $next_source:
6e4d5d
+#
6e4d5d
+# ... inner loop ...
6e4d5d
+# ...
6e4d5d
+# get_current_iv (hd, last_iv, blocklen);
6e4d5d
+# ... encrypt / decrypt (input is the data to be en/decrypted and output is the
6e4d5d
+#                        result of operation) ...
6e4d5d
+# if (encrypt_mode && (cipher_mode == GCRY_CIPHER_MODE_CFB))
6e4d5d
+#   memcpy (input, last_iv, blocklen);
6e4d5d
+# else if (cipher_mode == GCRY_CIPHER_MODE_OFB)
6e4d5d
+#   memcpy (input, last_iv, blocklen);
6e4d5d
+# else if (!encrypt_mode && cipher_mode == GCRY_CIPHER_MODE_CFB)
6e4d5d
+#   {
6e4d5d
+#      /* Reconstruct the output vector.  */
6e4d5d
+#      int i;
6e4d5d
+#      for (i=0; i < blocklen; i++)
6e4d5d
+#         input[i] ^= output[i];
6e4d5d
+#   }
6e4d5d
+# ... inner loop ends ...
6e4d5d
+# ==> now, the value of input is to be put into $next_source
6e4d5d
 
6e4d5d
 use strict;
6e4d5d
 use warnings;
6e4d5d
@@ -226,6 +261,8 @@ my $hmac;
6e4d5d
 # Generate the P, Q, G, Seed, counter, h (value used to generate g) values
6e4d5d
 # for DSA
6e4d5d
 # $1: modulus size
6e4d5d
+# $2: q size
6e4d5d
+# $3: seed (might be empty string)
6e4d5d
 # return: string with the calculated values in hex format, where each value
6e4d5d
 # 	  is separated from the previous with a \n in the following order:
6e4d5d
 #         P\n
6e4d5d
@@ -236,6 +273,19 @@ my $hmac;
6e4d5d
 #         h
6e4d5d
 my $dsa_pqggen;
6e4d5d
 
6e4d5d
+# Generate the G value from P and Q
6e4d5d
+# for DSA
6e4d5d
+# $1: modulus size
6e4d5d
+# $2: q size
6e4d5d
+# $3: P in hex form
6e4d5d
+# $4: Q in hex form
6e4d5d
+# return: string with the calculated values in hex format, where each value
6e4d5d
+#        is separated from the previous with a \n in the following order:
6e4d5d
+#         P\n
6e4d5d
+#         Q\n
6e4d5d
+#         G\n
6e4d5d
+my $dsa_ggen;
6e4d5d
+
6e4d5d
 #
6e4d5d
 # Generate an DSA public key from the provided parameters:
6e4d5d
 # $1: Name of file to create
f268f1
@@ -255,16 +305,30 @@ my $dsa_verify;
6e4d5d
 
6e4d5d
 # generate a new DSA key with the following properties:
6e4d5d
 #	PEM format
6e4d5d
-# $1 keyfile name
6e4d5d
-# return: file created, hash with keys of P, Q, G in hex format
6e4d5d
+# $1: modulus size
6e4d5d
+# $2: q size
6e4d5d
+# $3 keyfile name
6e4d5d
+# return: file created with key, string with values of P, Q, G in hex format
6e4d5d
 my $gen_dsakey;
6e4d5d
 
6e4d5d
+# generate a new DSA private key XY parameters in domain:
6e4d5d
+#      PEM format
6e4d5d
+# $1: P in hex form
6e4d5d
+# $2: Q in hex form
6e4d5d
+# $3: G in hex form
6e4d5d
+# return: string with values of X, Y in hex format
6e4d5d
+my $gen_dsakey_domain;
6e4d5d
+
6e4d5d
 # Sign a message with DSA
6e4d5d
 # $1: data to be signed in hex form
6e4d5d
 # $2: Key file in PEM format with the private key
f268f1
 # return: hash of digest information in hex format with Y, R, S as keys
f268f1
 my $dsa_sign;
f268f1
 
f268f1
+my $rsa_keygen;
f268f1
+
f268f1
+my $rsa_keygen_kat;
f268f1
+
f268f1
 ################################################################
f268f1
 ##### OpenSSL interface functions
f268f1
 ################################################################
f268f1
@@ -404,6 +468,35 @@ sub libgcrypt_rsa_derive($$$$$$$$) {
f268f1
 }
f268f1
 
f268f1
 
f268f1
+sub libgcrypt_rsa_keygen($) {
f268f1
+	my $n   = shift;
f268f1
+	my $sexp;
f268f1
+
f268f1
+	$n = sprintf ("%u", $n);
f268f1
+	$sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")))\n";
f268f1
+
f268f1
+	return pipe_through_program($sexp, "fipsdrv rsa-keygen");
f268f1
+}
f268f1
+
f268f1
+
f268f1
+sub libgcrypt_rsa_keygen_kat($$$$) {
f268f1
+	my $n   = shift;
f268f1
+	my $e   = shift;
f268f1
+	my $p   = shift;
f268f1
+	my $q   = shift;
f268f1
+	my $sexp;
f268f1
+
f268f1
+	$n = sprintf ("%u", $n);
f268f1
+	$sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")"
f268f1
+		. "(test-parms"
f268f1
+		. "(e #$e#)"
f268f1
+		. "(p #$p#)"
f268f1
+		. "(q #$q#))))\n";
f268f1
+
f268f1
+	return pipe_through_program($sexp, "fipsdrv rsa-keygen-kat");
f268f1
+}
f268f1
+
f268f1
+
f268f1
 sub libgcrypt_rsa_sign($$$) {
f268f1
 	my $data = shift;
f268f1
 	my $hashalgo = shift;
f268f1
@@ -500,17 +593,32 @@ sub libgcrypt_hmac($$$$) {
6e4d5d
 	return pipe_through_program($msg, $program);
6e4d5d
 }
6e4d5d
 
6e4d5d
-sub libgcrypt_dsa_pqggen($) {
6e4d5d
+sub libgcrypt_dsa_pqggen($$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $seed = shift;
6e4d5d
+
6e4d5d
+	my $program = "fipsdrv --keysize $mod --qsize $qsize dsa-pqg-gen";
6e4d5d
+	return pipe_through_program($seed, $program);
6e4d5d
+}
6e4d5d
+
6e4d5d
+sub libgcrypt_dsa_ggen($$$$) {
6e4d5d
 	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $p = shift;
6e4d5d
+	my $q = shift;
6e4d5d
+	my $domain = "(domain (p #$p#)(q #$q#))";
6e4d5d
 
6e4d5d
-	my $program = "fipsdrv --keysize $mod dsa-pqg-gen";
6e4d5d
+	my $program = "fipsdrv --keysize $mod --qsize $qsize --key \'$domain\' dsa-g-gen";
6e4d5d
 	return pipe_through_program("", $program);
6e4d5d
 }
6e4d5d
 
6e4d5d
-sub libgcrypt_gen_dsakey($) {
6e4d5d
+sub libgcrypt_gen_dsakey($$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
 	my $file = shift;
6e4d5d
 
6e4d5d
-	my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
6e4d5d
+	my $program = "fipsdrv --keysize $mod --qsize $qsize --key $file dsa-gen";
6e4d5d
 	my $tmp;
6e4d5d
 	my %ret;
6e4d5d
 
f268f1
@@ -519,10 +627,21 @@ sub libgcrypt_gen_dsakey($) {
6e4d5d
 	$tmp = pipe_through_program("", $program);
6e4d5d
 	die "dsa key gen failed: file $file not created" if (! -f $file);
6e4d5d
 
6e4d5d
-	@ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
6e4d5d
+	@ret{'P', 'Q', 'G'} = split(/\n/, $tmp);
6e4d5d
 	return %ret;
6e4d5d
 }
6e4d5d
 
6e4d5d
+sub libgcrypt_gen_dsakey_domain($$$) {
6e4d5d
+	my $p = shift;
6e4d5d
+	my $q = shift;
6e4d5d
+	my $g = shift;
6e4d5d
+	my $domain = "(domain (p #$p#)(q #$q#)(g #$g#))";
6e4d5d
+
6e4d5d
+	my $program = "fipsdrv --key '$domain' dsa-gen-key";
6e4d5d
+
6e4d5d
+	return pipe_through_program("", $program);
6e4d5d
+}
6e4d5d
+
6e4d5d
 sub libgcrypt_dsa_genpubkey($$$$$) {
6e4d5d
 	my $filename = shift;
6e4d5d
 	my $p = shift;
f268f1
@@ -1139,7 +1258,7 @@ sub hmac_kat($$$$) {
6e4d5d
 	$out .= "Tlen = $tlen\n";
6e4d5d
 	$out .= "Key = $key\n";
6e4d5d
 	$out .= "Msg = $msg\n";
6e4d5d
-	$out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n";
6e4d5d
+	$out .= "Mac = " . lc(&$hmac($key, $tlen, $msg, $hashtype{$tlen})) . "\n";
6e4d5d
 
6e4d5d
 	return $out;
6e4d5d
 }
f268f1
@@ -1205,7 +1324,7 @@ sub crypto_mct($$$$$$$$) {
6e4d5d
                 }
6e4d5d
                 my ($CO, $CI);
6e4d5d
 		my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
6e4d5d
-		$cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/);
6e4d5d
+		$cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/ && defined($state_cipher_des));
6e4d5d
                 my $pid = open2($CO, $CI, $cipher_imp);
6e4d5d
 
6e4d5d
                 my $calc_data = $iv; # CT[j]
f268f1
@@ -1213,8 +1332,8 @@ sub crypto_mct($$$$$$$$) {
6e4d5d
                 my $old_old_calc_data; # CT[j-2]
6e4d5d
 		my $next_source;
6e4d5d
 
6e4d5d
-		# TDES inner loop implements logic within driver
6e4d5d
-		if ($cipher =~ /des/) {
6e4d5d
+		# TDES inner loop implements logic within driver of libgcrypt
6e4d5d
+		if ($cipher =~ /des/ && $opt{'I'} && $opt{'I'} eq 'libgcrypt' ) {
6e4d5d
 			# Need to provide a dummy IV in case of ECB mode.
6e4d5d
 			my $iv_arg = (defined($iv) && $iv ne "")
6e4d5d
 					? bin2hex($iv)
f268f1
@@ -1238,6 +1357,10 @@ sub crypto_mct($$$$$$$$) {
6e4d5d
 			$line = <$CO>;
6e4d5d
 		} else {
6e4d5d
 	                for (my $j = 0; $j < $iloop; ++$j) {
6e4d5d
+				if ($cipher =~ /des-ede3-ofb/ ||
6e4d5d
+				    (!$enc && $cipher =~ /des-ede3-cfb/)) {
6e4d5d
+					die "Implementation lacks support for TDES OFB and TDES CFB in encryption mode - the problem is that we would need to extract the IV of the last round of encryption which would be the input for the next round - see comments in this script for implementation requirements"; 
6e4d5d
+				}
6e4d5d
 				$old_old_calc_data = $old_calc_data;
6e4d5d
                 	        $old_calc_data = $calc_data;
6e4d5d
 
f268f1
@@ -1429,7 +1552,7 @@ sub rsa_sigver($$$$$) {
f268f1
 # $7 xq2
f268f1
 # $8 Xq
f268f1
 # return: string formatted as expected by CAVS
f268f1
-sub rsa_keygen($$$$$$$$) {
f268f1
+sub rsa_keygen_x931($$$$$$$$) {
f268f1
 	my $modulus = shift;
f268f1
 	my $e = shift;
f268f1
 	my $xp1 = shift;
f268f1
@@ -1503,21 +1626,23 @@ sub rngx931($$$$) {
6e4d5d
 	return $out;
6e4d5d
 }
6e4d5d
 
6e4d5d
-# DSA PQGGen test
6e4d5d
+# DSA PQGen test
6e4d5d
 # $1 modulus size
6e4d5d
-# $2 number of rounds to perform the test
6e4d5d
+# $2 q size
6e4d5d
+# $3 number of rounds to perform the test
6e4d5d
 # return: string formatted as expected by CAVS
6e4d5d
-sub dsa_pqggen_driver($$) {
6e4d5d
+sub dsa_pqgen_driver($$$) {
6e4d5d
 	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
 	my $rounds = shift;
6e4d5d
 
6e4d5d
 	my $out = "";
6e4d5d
 	for(my $i=0; $i<$rounds; $i++) {
6e4d5d
-		my $ret = &$dsa_pqggen($mod);
6e4d5d
+		my $ret = &$dsa_pqggen($mod, $qsize, "");
6e4d5d
 		my ($P, $Q, $G, $Seed, $c, $H) = split(/\n/, $ret);
6e4d5d
-		die "Return value does not contain all expected values of P, Q, G, Seed, c, H for dsa_pqggen"
6e4d5d
-			if (!defined($P) || !defined($Q) || !defined($G) ||
6e4d5d
-			    !defined($Seed) || !defined($c) || !defined($H));
6e4d5d
+		die "Return value does not contain all expected values of P, Q, Seed, c for dsa_pqggen"
6e4d5d
+			if (!defined($P) || !defined($Q) ||
6e4d5d
+			    !defined($Seed) || !defined($c));
6e4d5d
 
6e4d5d
 		# now change the counter to decimal as CAVS wants decimal
6e4d5d
 		# counter value although all other is HEX
f268f1
@@ -1525,15 +1650,166 @@ sub dsa_pqggen_driver($$) {
6e4d5d
 
6e4d5d
 		$out .= "P = $P\n";
6e4d5d
 		$out .= "Q = $Q\n";
6e4d5d
-		$out .= "G = $G\n";
6e4d5d
-		$out .= "Seed = $Seed\n";
6e4d5d
-		$out .= "c = $c\n";
6e4d5d
-		$out .= "H = $H\n\n";
6e4d5d
+		$out .= "domain_parameter_seed = $Seed\n";
6e4d5d
+		$out .= "counter = $c\n\n";
6e4d5d
 	}
6e4d5d
 
6e4d5d
 	return $out;
6e4d5d
 }
6e4d5d
 
6e4d5d
+# DSA GGen test
6e4d5d
+# $1 modulus size
6e4d5d
+# $2 q size
6e4d5d
+# $3 p in hex form
6e4d5d
+# $4 q in hex form
6e4d5d
+# return: string formatted as expected by CAVS
6e4d5d
+sub dsa_ggen_driver($$$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $p = shift;
6e4d5d
+	my $q = shift;
6e4d5d
+
6e4d5d
+	my $out = "";
6e4d5d
+	my $ret = &$dsa_ggen($mod, $qsize, $p, $q);
6e4d5d
+	my ($P, $Q, $G) = split(/\n/, $ret);
6e4d5d
+	die "Return value does not contain all expected values of P, Q, G for dsa_ggen"
6e4d5d
+		if (!defined($P) || !defined($Q) || !defined($G));
6e4d5d
+
6e4d5d
+	$out .= "G = $G\n\n";
6e4d5d
+
6e4d5d
+	return $out;
6e4d5d
+}
6e4d5d
+
6e4d5d
+sub hexcomp($$) {
6e4d5d
+	my $a = lc shift;
6e4d5d
+	my $b = lc shift;
6e4d5d
+
6e4d5d
+	if (length $a < length $b) {
6e4d5d
+		my $c = $a;
6e4d5d
+		$a = $b;
6e4d5d
+		$b = $a;
6e4d5d
+	}
6e4d5d
+
6e4d5d
+	while (length $b < length $a) {
6e4d5d
+		$b = "00$b";
6e4d5d
+	}
6e4d5d
+
6e4d5d
+	return $a eq $b;
6e4d5d
+}
6e4d5d
+
6e4d5d
+# DSA PQVer test
6e4d5d
+# $1 modulus size
6e4d5d
+# $2 q size
6e4d5d
+# $3 p in hex form
6e4d5d
+# $4 q in hex form
6e4d5d
+# $5 seed in hex form
6e4d5d
+# $6 c decimal counter
6e4d5d
+# return: string formatted as expected by CAVS
6e4d5d
+sub dsa_pqver_driver($$$$$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $p = shift;
6e4d5d
+	my $q = shift;
6e4d5d
+	my $seed = shift;
6e4d5d
+	my $c = shift;
6e4d5d
+
6e4d5d
+	my $out = "";
6e4d5d
+	my $ret = &$dsa_pqggen($mod, $qsize, $seed);
6e4d5d
+	my ($P, $Q, $G, $seed2, $c2, $h2) = split(/\n/, $ret);
6e4d5d
+	die "Return value does not contain all expected values of P, Q, G, seed, c for dsa_pqggen"
6e4d5d
+		if (!defined($P) || !defined($Q) || !defined($G) ||
6e4d5d
+		    !defined($seed2) || !defined($c2));
6e4d5d
+
6e4d5d
+	$c2 = hex($c2);
6e4d5d
+
6e4d5d
+	$out .= "Seed = $seed\n";
6e4d5d
+	$out .= "c = $c\n";
6e4d5d
+
6e4d5d
+	if (hexcomp($P, $p) && hexcomp($Q, $q) && hexcomp($seed, $seed2) && $c == $c2) {
6e4d5d
+		$out .= "Result = P\n\n";
6e4d5d
+	}
6e4d5d
+	else {
6e4d5d
+		$out .= "Result = F\n\n";
6e4d5d
+	}
6e4d5d
+	return $out;
6e4d5d
+}
6e4d5d
+
6e4d5d
+# DSA PQGVer test
6e4d5d
+# $1 modulus size
6e4d5d
+# $2 q size
6e4d5d
+# $3 p in hex form
6e4d5d
+# $4 q in hex form
6e4d5d
+# $5 g in hex form
6e4d5d
+# $6 seed in hex form
6e4d5d
+# $7 c decimal counter
6e4d5d
+# $8 h in hex form
6e4d5d
+# return: string formatted as expected by CAVS
6e4d5d
+sub dsa_pqgver_driver($$$$$$$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $p = shift;
6e4d5d
+	my $q = shift;
6e4d5d
+	my $g = shift;
6e4d5d
+	my $seed = shift;
6e4d5d
+	my $c = shift;
6e4d5d
+	my $h = shift;
6e4d5d
+
6e4d5d
+	my $out = "";
6e4d5d
+	my $ret = &$dsa_pqggen($mod, $qsize, $seed);
6e4d5d
+	my ($P, $Q, $G, $seed2, $c2, $h2) = split(/\n/, $ret);
6e4d5d
+	die "Return value does not contain all expected values of P, Q, G, seed, c, H for dsa_pqggen"
6e4d5d
+		if (!defined($P) || !defined($Q) || !defined($G) ||
6e4d5d
+		    !defined($seed2) || !defined($c2) || !defined($h2));
6e4d5d
+
6e4d5d
+	
6e4d5d
+
6e4d5d
+	$out .= "Seed = $seed\n";
6e4d5d
+	$out .= "c = $c\n";
6e4d5d
+	$out .= "H = $h\n";
6e4d5d
+
6e4d5d
+	$c2 = hex($c2);
6e4d5d
+
6e4d5d
+	if (hexcomp($P, $p) && hexcomp($Q, $q) && hexcomp($G, $g) && hexcomp($seed, $seed2) && 
6e4d5d
+	    $c == $c2 && hex($h) == hex($h2)) {
6e4d5d
+		$out .= "Result = P\n\n";
6e4d5d
+	}
6e4d5d
+	else {
6e4d5d
+		$out .= "Result = F\n\n";
6e4d5d
+	}
6e4d5d
+
6e4d5d
+	return $out;
6e4d5d
+}
6e4d5d
+
6e4d5d
+# DSA Keypair test
6e4d5d
+# $1 modulus size
6e4d5d
+# $2 q size
6e4d5d
+# $3 number of rounds to perform the test
6e4d5d
+# return: string formatted as expected by CAVS
6e4d5d
+sub dsa_keypair_driver($$$) {
6e4d5d
+	my $mod = shift;
6e4d5d
+	my $qsize = shift;
6e4d5d
+	my $rounds = shift;
6e4d5d
+
6e4d5d
+	my $out = "";
6e4d5d
+	my $tmpkeyfile = "dsa_siggen.tmp.$$";
6e4d5d
+	my %pqg = &$gen_dsakey($mod, $qsize, $tmpkeyfile);
6e4d5d
+	$out .= "P = " . $pqg{'P'} . "\n";
6e4d5d
+	$out .= "Q = " . $pqg{'Q'} . "\n";
6e4d5d
+	$out .= "G = " . $pqg{'G'} . "\n\n";
6e4d5d
+	unlink($tmpkeyfile);
6e4d5d
+
6e4d5d
+	for(my $i=0; $i<$rounds; $i++) {
6e4d5d
+		my $ret = &$gen_dsakey_domain($pqg{'P'}, $pqg{'Q'}, $pqg{'G'});
6e4d5d
+		my ($X, $Y) = split(/\n/, $ret);
6e4d5d
+		die "Return value does not contain all expected values of X, Y for gen_dsakey_domain"
6e4d5d
+			if (!defined($X) || !defined($Y));
6e4d5d
+
6e4d5d
+		$out .= "X = $X\n";
6e4d5d
+		$out .= "Y = $Y\n\n";
6e4d5d
+	}
6e4d5d
+
6e4d5d
+	return $out;
6e4d5d
+}
6e4d5d
 
6e4d5d
 # DSA SigGen test
6e4d5d
 # $1: Message to be signed in hex form
f268f1
@@ -1598,6 +1874,53 @@ sub dsa_sigver($$$$$$$$) {
f268f1
 	return $out;
f268f1
 }
f268f1
 
f268f1
+# RSA Keygen RPP test
f268f1
+# $1 modulus size
f268f1
+# $2 number of rounds to perform the test
f268f1
+# return: string formatted as expected by CAVS
f268f1
+sub rsa_keygen_driver($$) {
f268f1
+	my $mod = shift;
f268f1
+	my $rounds = shift;
f268f1
+
f268f1
+	my $out = "";
f268f1
+
f268f1
+	for(my $i=0; $i<$rounds; $i++) {
f268f1
+		my $ret = &$rsa_keygen($mod);
f268f1
+		my ($e, $p, $q, $n, $d) = split(/\n/, $ret);
f268f1
+		die "Return value does not contain all expected values of e, p, q, n, d for rsa_keygen"
f268f1
+			if (!defined($e) || !defined($p) || !defined($q) || !defined($n) || !defined($d));
f268f1
+
f268f1
+		$out .= "e = $e\n";
f268f1
+		$out .= "p = $p\n";
f268f1
+		$out .= "q = $q\n";
f268f1
+		$out .= "n = $n\n";
f268f1
+		$out .= "d = $d\n\n";
f268f1
+	}
f268f1
+
f268f1
+	return $out;
f268f1
+}
f268f1
+
f268f1
+# RSA RPP Keygen KAT test
f268f1
+# $1 modulus size
f268f1
+# $2 p in hex form
f268f1
+# $3 q in hex form
f268f1
+# return: string formatted as expected by CAVS
f268f1
+sub rsa_keygen_kat_driver($$$) {
f268f1
+	my $mod = shift;
f268f1
+	my $p = shift;
f268f1
+	my $q = shift;
f268f1
+
f268f1
+	my $out = "";
f268f1
+	my $ret = &$rsa_keygen_kat($mod, $p, $q);
f268f1
+	my ($Result) = split(/\n/, $ret);
f268f1
+	die "Return value does not contain all expected values of Result for rsa_keygen_kat"
f268f1
+		if (!defined($Result));
f268f1
+
f268f1
+	$out .= "Result = $Result\n\n";
f268f1
+	return $out;
f268f1
+}
f268f1
+
f268f1
+
f268f1
 ##############################################################
f268f1
 # Parser of input file and generator of result file
f268f1
 #
f268f1
@@ -1658,12 +1981,18 @@ sub parse($$) {
6e4d5d
 	my $klen = "";
6e4d5d
 	my $tlen = "";
6e4d5d
 	my $modulus = "";
6e4d5d
+	my $qsize = "";
6e4d5d
 	my $capital_n = 0;
6e4d5d
+	my $num = 0;
6e4d5d
 	my $capital_p = "";
6e4d5d
 	my $capital_q = "";
6e4d5d
 	my $capital_g = "";
6e4d5d
 	my $capital_y = "";
6e4d5d
 	my $capital_r = "";
6e4d5d
+	my $capital_h = "";
6e4d5d
+	my $c = "";
f268f1
+	my $prandom = "";
f268f1
+	my $qrandom = "";
6e4d5d
 	my $xp1 = "";
6e4d5d
 	my $xp2 = "";
6e4d5d
 	my $Xp = "";
f268f1
@@ -1700,7 +2029,7 @@ sub parse($$) {
6e4d5d
 
6e4d5d
 		##### Extract cipher
6e4d5d
 		# XXX there may be more - to be added
6e4d5d
-		if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA)/) {
f268f1
+		if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA|KeyGen - Random Probably Prime|KeyPair|PQGVer)/) {
6e4d5d
 			if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
6e4d5d
 			elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
6e4d5d
 			elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
f268f1
@@ -1749,7 +2078,23 @@ sub parse($$) {
6e4d5d
 
6e4d5d
 			if ($tt == 0) {
6e4d5d
 			##### Identify the test type
6e4d5d
-				if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) {
f268f1
+				if ($tmpline =~ /KeyGen - Random Probably Prime Known Answer Test/) {
f268f1
+					$tt = 19;
f268f1
+					die "Interface function rsa_keygen_kat for RSA key generation KAT not defined for tested library"
f268f1
+						if (!defined($rsa_keygen_kat));
f268f1
+				} elsif ($tmpline =~ /KeyGen - Random Probably Prime Test/) {
f268f1
+					$tt = 18;
f268f1
+					die "Interface function rsa_keygen for RSA key generation not defined for tested library"
f268f1
+						if (!defined($rsa_keygen));
f268f1
+				} elsif ($tmpline =~ /PQGVer/) {
6e4d5d
+					$tt = 16;
6e4d5d
+					die "Interface function for DSA PQGVer testing not defined for tested library"
6e4d5d
+						if (!defined($dsa_pqggen));
6e4d5d
+				} elsif ($tmpline =~ /KeyPair/) {
6e4d5d
+					$tt = 14;
6e4d5d
+					die "Interface function dsa_keygen for DSA key generation not defined for tested library"
6e4d5d
+						if (!defined($gen_dsakey_domain));
6e4d5d
+				} elsif ($tmpline =~ /KeyGen RSA \(X9\.31\)/) {
6e4d5d
 					$tt = 13;
6e4d5d
 					die "Interface function rsa_derive for RSA key generation not defined for tested library"
6e4d5d
 						if (!defined($rsa_derive));
f268f1
@@ -1760,11 +2105,11 @@ sub parse($$) {
6e4d5d
 				} elsif ($tmpline =~ /SigGen/ && $opt{'D'}) {
6e4d5d
 					$tt = 11;
6e4d5d
 					die "Interface function dsa_sign or gen_dsakey for DSA sign not defined for tested library"
6e4d5d
-						if (!defined($dsa_sign) || !defined($gen_rsakey));
6e4d5d
+						if (!defined($dsa_sign) || !defined($gen_dsakey));
6e4d5d
 				} elsif ($tmpline =~ /PQGGen/) {
6e4d5d
 					$tt = 10;
6e4d5d
 					die "Interface function for DSA PQGGen testing not defined for tested library"
6e4d5d
-						if (!defined($dsa_pqggen));
6e4d5d
+						if (!defined($dsa_pqggen) || !defined($dsa_ggen));
6e4d5d
 				} elsif ($tmpline =~ /Hash sizes tested/) {
6e4d5d
 					$tt = 9;
6e4d5d
 					die "Interface function hmac for HMAC testing not defined for tested library"
f268f1
@@ -1792,7 +2137,7 @@ sub parse($$) {
6e4d5d
 				} elsif ($tmpline =~ /Monte|MCT|Carlo/) {
6e4d5d
 					$tt = 2;
6e4d5d
 					die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
6e4d5d
-						if (!defined($state_cipher) || !defined($state_cipher_des));
6e4d5d
+						if (!defined($state_cipher) && !defined($state_cipher_des));
6e4d5d
 				} elsif ($cipher =~ /^sha/) {
6e4d5d
 					$tt = 3;
6e4d5d
 					die "Interface function hash for Hashing not defined for tested library"
f268f1
@@ -1875,18 +2220,44 @@ sub parse($$) {
6e4d5d
 			die "Msg/Seed seen twice - input file crap" if ($pt ne "");
6e4d5d
 			$pt=$2;
6e4d5d
 		}
6e4d5d
-		elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
6e4d5d
+		elsif ($line =~ /^\[A.2.1\s.*\]$/) { # found in DSA2 PQGGen request
6e4d5d
+			$out .= $line . "\n"; # print it
6e4d5d
+			if ($tt == 10) {
6e4d5d
+				# now generate G from PQ
6e4d5d
+				$tt = 15;
6e4d5d
+			}
6e4d5d
+		}
6e4d5d
+		elsif ($line =~ /^\[A.2.2\s.*\]$/) { # found in DSA2 PQGVer request
6e4d5d
+			$out .= $line . "\n"; # print it
6e4d5d
+			if ($tt == 16) {
6e4d5d
+				# now verify PQG
6e4d5d
+				$tt = 17;
6e4d5d
+			}
6e4d5d
+		}
6e4d5d
+		elsif ($line =~ /^\[mod\s*=\s*L=([0-9]*),\s*N=([0-9]*).*\]$/) { # found in DSA2 requests
6e4d5d
 			$modulus = $1;
6e4d5d
+			$qsize = $2;
6e4d5d
 			$out .= $line . "\n\n"; # print it
6e4d5d
+			# clear eventual PQG
6e4d5d
+			$capital_p = "";
6e4d5d
+			$capital_q = "";
6e4d5d
+			$capital_g = "";
6e4d5d
 			# generate the private key with given bit length now
6e4d5d
 			# as we have the required key length in bit
6e4d5d
 			if ($tt == 11) {
6e4d5d
 				$dsa_keyfile = "dsa_siggen.tmp.$$";
6e4d5d
-				my %pqg = &$gen_dsakey($dsa_keyfile);
6e4d5d
+				my %pqg = &$gen_dsakey($modulus, $qsize, $dsa_keyfile);
6e4d5d
 				$out .= "P = " . $pqg{'P'} . "\n";
6e4d5d
 				$out .= "Q = " . $pqg{'Q'} . "\n";
6e4d5d
-				$out .= "G = " . $pqg{'G'} . "\n";
6e4d5d
-			} elsif ( $tt == 5 ) {
6e4d5d
+				$out .= "G = " . $pqg{'G'} . "\n\n";
6e4d5d
+                        }
6e4d5d
+                }
6e4d5d
+		elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
6e4d5d
+			$modulus = $1;
6e4d5d
+			$out .= $line . "\n\n"; # print it
6e4d5d
+			# generate the private key with given bit length now
6e4d5d
+			# as we have the required key length in bit
6e4d5d
+			if ( $tt == 5 ) {
6e4d5d
 				# XXX maybe a secure temp file name is better here
6e4d5d
 				# but since it is not run on a security sensitive
6e4d5d
 				# system, I hope that this is fine
f268f1
@@ -1907,6 +2278,9 @@ sub parse($$) {
f268f1
 		}
f268f1
 		elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests
f268f1
 			$e=$1;
f268f1
+			if ($tt == 19) {
f268f1
+				$out .= $line . "\n"; # print it
f268f1
+			}
f268f1
 		}
f268f1
 		elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests
f268f1
 			die "S seen twice - input file crap" if ($signature ne "");
f268f1
@@ -1932,11 +2306,16 @@ sub parse($$) {
6e4d5d
 				if ($tlen ne "");
6e4d5d
 			$tlen=$1;
6e4d5d
 		}
6e4d5d
-		elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA PQGGen
6e4d5d
+		elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA KeyPair
6e4d5d
 			die "N seen twice - check input file"
6e4d5d
 				if ($capital_n);
6e4d5d
 			$capital_n = $1;
6e4d5d
 		}
6e4d5d
+		elsif ($line =~ /^Num\s*=\s*(.*)/) { #DSA PQGGen
6e4d5d
+			die "Num seen twice - check input file"
6e4d5d
+				if ($num);
6e4d5d
+			$num = $1;
6e4d5d
+		}
6e4d5d
 		elsif ($line =~ /^P\s*=\s*(.*)/) { #DSA SigVer
6e4d5d
 			die "P seen twice - check input file"
6e4d5d
 				if ($capital_p);
f268f1
@@ -1965,6 +2344,16 @@ sub parse($$) {
6e4d5d
 				if ($capital_r);
6e4d5d
 			$capital_r = $1;
6e4d5d
 		}
6e4d5d
+		elsif ($line =~ /^H\s*=\s*(.*)/) { #DSA PQGVer
6e4d5d
+			die "H seen twice - check input file"
6e4d5d
+				if ($capital_h);
6e4d5d
+			$capital_h = $1;
6e4d5d
+		}
6e4d5d
+		elsif ($line =~ /^c\s*=\s*(.*)/) { #DSA PQGVer
6e4d5d
+			die "c seen twice - check input file"
6e4d5d
+				if ($c);
6e4d5d
+			$c = $1;
6e4d5d
+		}
6e4d5d
 		elsif ($line =~ /^xp1\s*=\s*(.*)/) { #RSA key gen
6e4d5d
 			die "xp1 seen twice - check input file"
6e4d5d
 				if ($xp1);
f268f1
@@ -1995,6 +2384,22 @@ sub parse($$) {
f268f1
 				if ($Xq);
f268f1
 			$Xq = $1;
f268f1
 		}
f268f1
+		elsif ($line =~ /^prandom\s*=\s*(.*)/) { #RSA key gen KAT
f268f1
+			die "prandom seen twice - check input file"
f268f1
+				if ($prandom);
f268f1
+			$prandom = $1;
f268f1
+			$out .= $line . "\n"; # print it
f268f1
+		}
f268f1
+		elsif ($line =~ /^qrandom\s*=\s*(.*)/) { #RSA key gen KAT
f268f1
+			die "qrandom seen twice - check input file"
f268f1
+				if ($qrandom);
f268f1
+			$qrandom = $1;
f268f1
+			$out .= $line . "\n"; # print it
f268f1
+		}
f268f1
+		elsif ($tt == 19 && $line =~ /^ / && $qrandom eq "") { #RSA key gen KAT
f268f1
+			$qrandom = "00";
f268f1
+			$out .= $line . "\n"; # print it
f268f1
+		}
f268f1
 		else {
f268f1
 			$out .= $line . "\n";
f268f1
 		}
f268f1
@@ -2074,11 +2479,10 @@ sub parse($$) {
6e4d5d
 			}
6e4d5d
 		}
6e4d5d
 		elsif ($tt == 10) {
6e4d5d
-			if ($modulus ne "" && $capital_n > 0) {
6e4d5d
-				$out .= dsa_pqggen_driver($modulus, $capital_n);
6e4d5d
-				#$mod is not resetted
6e4d5d
-				$capital_n = 0;
6e4d5d
-			}
6e4d5d
+			if ($modulus ne "" && $qsize ne "" && $num > 0) {
6e4d5d
+				$out .= dsa_pqgen_driver($modulus, $qsize, $num);
6e4d5d
+				$num = 0;
6e4d5d
+                        }
6e4d5d
 		}
6e4d5d
 		elsif ($tt == 11) {
6e4d5d
 			if ($pt ne "" && $dsa_keyfile ne "") {
f268f1
@@ -2124,7 +2528,7 @@ sub parse($$) {
f268f1
 			   $xq1 ne "" &&
f268f1
 			   $xq2 ne "" &&
f268f1
 			   $Xq ne "") {
f268f1
-				$out .= rsa_keygen($modulus,
f268f1
+				$out .= rsa_keygen_x931($modulus,
f268f1
 						   $e,
f268f1
 						   $xp1,
f268f1
 						   $xp2,
f268f1
@@ -2141,6 +2545,96 @@ sub parse($$) {
6e4d5d
 				$Xq = "";
6e4d5d
 			}
6e4d5d
 		}
6e4d5d
+		elsif ($tt == 14) {
6e4d5d
+			if ($modulus ne "" &&
6e4d5d
+			    $qsize ne "" &&
6e4d5d
+			    $capital_n > 0) {
6e4d5d
+				$out .= dsa_keypair_driver($modulus,
6e4d5d
+							   $qsize,
6e4d5d
+							   $capital_n);
6e4d5d
+				$capital_n = 0;
6e4d5d
+			}
6e4d5d
+		}
6e4d5d
+		elsif ($tt == 15) {
6e4d5d
+			if ($modulus ne "" &&
6e4d5d
+			    $qsize ne "" &&
6e4d5d
+			    $capital_p ne "" &&
6e4d5d
+			    $capital_q ne "") {
6e4d5d
+				$out .= dsa_ggen_driver($modulus,
6e4d5d
+							$qsize,
6e4d5d
+							$capital_p,
6e4d5d
+							$capital_q);
6e4d5d
+				$capital_p = "";
6e4d5d
+				$capital_q = "";
6e4d5d
+				$num--;
6e4d5d
+			}
6e4d5d
+		}
6e4d5d
+		elsif ($tt == 16) {
6e4d5d
+			if ($modulus ne "" &&
6e4d5d
+			    $qsize ne "" &&
6e4d5d
+			    $capital_p ne "" &&
6e4d5d
+			    $capital_q ne "" &&
6e4d5d
+			    $pt ne "" &&
6e4d5d
+			    $c ne "") {
6e4d5d
+				$out .= dsa_pqver_driver($modulus,
6e4d5d
+							$qsize,
6e4d5d
+							$capital_p,
6e4d5d
+							$capital_q,
6e4d5d
+							$pt,
6e4d5d
+							$c);
6e4d5d
+				$capital_p = "";
6e4d5d
+				$capital_q = "";
6e4d5d
+				$pt = "";
6e4d5d
+				$c = "";
6e4d5d
+			}
6e4d5d
+		}
6e4d5d
+		elsif ($tt == 17) {
6e4d5d
+			if ($modulus ne "" &&
6e4d5d
+			    $qsize ne "" &&
6e4d5d
+			    $capital_p ne "" &&
6e4d5d
+			    $capital_q ne "" &&
6e4d5d
+			    $capital_g ne "" &&
6e4d5d
+			    $pt ne "" &&
6e4d5d
+			    $c ne "" &&
6e4d5d
+			    $capital_h ne "") {
6e4d5d
+				$out .= dsa_pqgver_driver($modulus,
6e4d5d
+							$qsize,
6e4d5d
+							$capital_p,
6e4d5d
+							$capital_q,
6e4d5d
+							$capital_g,
6e4d5d
+							$pt,
6e4d5d
+							$c,
6e4d5d
+							$capital_h);
6e4d5d
+				$capital_p = "";
6e4d5d
+				$capital_q = "";
6e4d5d
+				$capital_g = "";
6e4d5d
+				$pt = "";
6e4d5d
+				$c = "";
6e4d5d
+				$capital_h = "";
6e4d5d
+			}
6e4d5d
+		}
f268f1
+		elsif ($tt == 18) {
f268f1
+			if ($modulus ne "" &&
f268f1
+			    $capital_n > 0) {
f268f1
+				$out .= rsa_keygen_driver($modulus,
f268f1
+						$capital_n);
f268f1
+				$capital_n = 0;
f268f1
+			}
f268f1
+		}
f268f1
+		elsif ($tt == 19) {
f268f1
+			if ($modulus ne "" &&
f268f1
+			    $e ne "" &&
f268f1
+			    $prandom ne "" &&
f268f1
+			    $qrandom ne "") {
f268f1
+				$out .= rsa_keygen_kat_driver($modulus,
f268f1
+						$e,
f268f1
+						$prandom,
f268f1
+						$qrandom);
f268f1
+				$prandom = "";
f268f1
+				$qrandom = "";
f268f1
+				$e = "";
f268f1
+			}
f268f1
+		}
6e4d5d
 		elsif ($tt > 0) {
6e4d5d
 			die "Test case $tt not defined";
6e4d5d
 		}
f268f1
@@ -2199,10 +2693,14 @@ sub main() {
6e4d5d
 		$state_rng =	\&libgcrypt_state_rng;
6e4d5d
 		$hmac =		\&libgcrypt_hmac;
6e4d5d
 		$dsa_pqggen = 	\&libgcrypt_dsa_pqggen;
6e4d5d
+		$dsa_ggen =	\&libgcrypt_dsa_ggen;
6e4d5d
 		$gen_dsakey =   \&libgcrypt_gen_dsakey;
6e4d5d
+		$gen_dsakey_domain =	\&libgcrypt_gen_dsakey_domain;
6e4d5d
 		$dsa_sign =     \&libgcrypt_dsa_sign;
6e4d5d
 		$dsa_verify =   \&libgcrypt_dsa_verify;
6e4d5d
 		$dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
f268f1
+		$rsa_keygen = \&libgcrypt_rsa_keygen;
f268f1
+		$rsa_keygen_kat = \&libgcrypt_rsa_keygen_kat;
f268f1
         } else {
f268f1
                 die "Invalid interface option given";
f268f1
         }
f268f1
diff -up libgcrypt-1.5.3/tests/cavs_tests.sh.cavs libgcrypt-1.5.3/tests/cavs_tests.sh
f268f1
--- libgcrypt-1.5.3/tests/cavs_tests.sh.cavs	2013-05-22 18:02:55.000000000 +0200
f268f1
+++ libgcrypt-1.5.3/tests/cavs_tests.sh	2014-09-26 17:45:38.434674884 +0200
6e4d5d
@@ -55,7 +55,7 @@ function run_one_test () {
6e4d5d
     [ -d "$respdir" ] || mkdir "$respdir"
6e4d5d
     [ -f "$rspfile" ] &&  rm "$rspfile"
6e4d5d
 
6e4d5d
-    if echo "$reqfile" | grep '/DSA/req/' >/dev/null 2>/dev/null; then
6e4d5d
+    if echo "$reqfile" | grep '/DSA.\?/req/' >/dev/null 2>/dev/null; then
6e4d5d
         dflag="-D"
6e4d5d
     fi
6e4d5d
 
f268f1
diff -up libgcrypt-1.5.3/tests/fipsdrv.c.cavs libgcrypt-1.5.3/tests/fipsdrv.c
f268f1
--- libgcrypt-1.5.3/tests/fipsdrv.c.cavs	2013-07-25 11:10:04.000000000 +0200
f268f1
+++ libgcrypt-1.5.3/tests/fipsdrv.c	2014-10-21 09:30:30.796777225 +0200
6e4d5d
@@ -893,6 +893,9 @@ print_mpi_line (gcry_mpi_t a, int no_lz)
6e4d5d
     die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err));
6e4d5d
 
6e4d5d
   p = buf;
6e4d5d
+  while (*p)
6e4d5d
+     *p++ = tolower(*p);
6e4d5d
+  p = buf;
6e4d5d
   if (no_lz && p[0] == '0' && p[1] == '0' && p[2])
6e4d5d
     p += 2;
6e4d5d
 
f268f1
@@ -1346,6 +1349,69 @@ run_rsa_derive (const void *data, size_t
f268f1
 }
f268f1
 
f268f1
 
f268f1
+/* Generate RSA key using the S-expression in (DATA,DATALEN).  This
f268f1
+   S-expression is used directly as input to gcry_pk_genkey.  The
f268f1
+   result is printed to stdout with one parameter per line in hex
f268f1
+   format and in this order: e, p, q, n, d.  */
f268f1
+static void
f268f1
+run_rsa_keygen (const void *data, size_t datalen, int test)
f268f1
+{
f268f1
+  gpg_error_t err;
f268f1
+  gcry_sexp_t s_keyspec, s_key, s_top, l1;
f268f1
+  gcry_mpi_t mpi;
f268f1
+  const char *parmlist;
f268f1
+  int idx;
f268f1
+
f268f1
+  if (!datalen)
f268f1
+    err = gpg_error (GPG_ERR_NO_DATA);
f268f1
+  else
f268f1
+    err = gcry_sexp_new (&s_keyspec, data, datalen, 1);
f268f1
+  if (err)
f268f1
+    die ("gcry_sexp_new failed for RSA key generation: %s\n",
f268f1
+         gpg_strerror (err));
f268f1
+
f268f1
+  err = gcry_pk_genkey (&s_key, s_keyspec);
f268f1
+
f268f1
+  gcry_sexp_release (s_keyspec);
f268f1
+
f268f1
+  if (test) {
f268f1
+	if (err)
f268f1
+		printf("F\n");
f268f1
+	else {
f268f1
+		gcry_sexp_release (s_key);
f268f1
+		printf("P\n");
f268f1
+	}
f268f1
+	return;
f268f1
+  }
f268f1
+
f268f1
+  if (err)
f268f1
+    die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
f268f1
+
f268f1
+  parmlist = "epqnd";
f268f1
+
f268f1
+  /* Parse and print the parameters.  */
f268f1
+  l1 = gcry_sexp_find_token (s_key, "private-key", 0);
f268f1
+  s_top = gcry_sexp_find_token (l1, "rsa", 0);
f268f1
+  gcry_sexp_release (l1);
f268f1
+  if (!s_top)
f268f1
+    die ("private-key part not found in result\n");
f268f1
+
f268f1
+  for (idx=0; parmlist[idx]; idx++)
f268f1
+    {
f268f1
+      l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1);
f268f1
+      mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
f268f1
+      gcry_sexp_release (l1);
f268f1
+      if (!mpi)
f268f1
+        die ("parameter %c missing in private-key\n", parmlist[idx]);
f268f1
+      print_mpi_line (mpi, 1);
f268f1
+      gcry_mpi_release (mpi);
f268f1
+    }
f268f1
+
f268f1
+  gcry_sexp_release (s_top);
f268f1
+  gcry_sexp_release (s_key);
f268f1
+}
f268f1
+
f268f1
+
f268f1
 
f268f1
 static size_t
f268f1
 compute_tag_length (size_t n)
f268f1
@@ -1675,14 +1741,14 @@ run_rsa_verify (const void *data, size_t
6e4d5d
 /* Generate a DSA key of size KEYSIZE and return the complete
6e4d5d
    S-expression.  */
6e4d5d
 static gcry_sexp_t
6e4d5d
-dsa_gen (int keysize)
6e4d5d
+dsa_gen (int keysize, int qsize)
6e4d5d
 {
6e4d5d
   gpg_error_t err;
6e4d5d
   gcry_sexp_t keyspec, key;
6e4d5d
 
6e4d5d
   err = gcry_sexp_build (&keyspec, NULL,
6e4d5d
-                         "(genkey (dsa (nbits %d)(use-fips186-2)))",
6e4d5d
-                         keysize);
6e4d5d
+                         "(genkey (dsa (nbits %d)(qbits %d)(use-fips186)))",
6e4d5d
+                         keysize, qsize);
6e4d5d
   if (err)
6e4d5d
     die ("gcry_sexp_build failed for DSA key generation: %s\n",
6e4d5d
          gpg_strerror (err));
f268f1
@@ -1700,7 +1766,7 @@ dsa_gen (int keysize)
6e4d5d
 /* Generate a DSA key of size KEYSIZE and return the complete
6e4d5d
    S-expression.  */
6e4d5d
 static gcry_sexp_t
6e4d5d
-dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
6e4d5d
+dsa_gen_with_seed (int keysize, int qsize, const void *seed, size_t seedlen)
6e4d5d
 {
6e4d5d
   gpg_error_t err;
6e4d5d
   gcry_sexp_t keyspec, key;
f268f1
@@ -1709,10 +1775,11 @@ dsa_gen_with_seed (int keysize, const vo
6e4d5d
                          "(genkey"
6e4d5d
                          "  (dsa"
6e4d5d
                          "    (nbits %d)"
6e4d5d
-                         "    (use-fips186-2)"
6e4d5d
+                         "    (qbits %d)"
6e4d5d
+                         "    (use-fips186)"
6e4d5d
                          "    (derive-parms"
6e4d5d
                          "      (seed %b))))",
6e4d5d
-                         keysize, (int)seedlen, seed);
6e4d5d
+                         keysize, qsize, (int)seedlen, seed);
6e4d5d
   if (err)
6e4d5d
     die ("gcry_sexp_build failed for DSA key generation: %s\n",
6e4d5d
          gpg_strerror (err));
f268f1
@@ -1720,6 +1787,37 @@ dsa_gen_with_seed (int keysize, const vo
6e4d5d
   err = gcry_pk_genkey (&key, keyspec);
6e4d5d
   if (err)
6e4d5d
     die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
6e4d5d
+  
6e4d5d
+  gcry_sexp_release (keyspec);
6e4d5d
+
6e4d5d
+  return key;
6e4d5d
+}
6e4d5d
+
6e4d5d
+/* Generate a DSA key with specified domain parameters and return the complete
6e4d5d
+   S-expression.  */
6e4d5d
+static gcry_sexp_t
6e4d5d
+dsa_gen_key (const char *domain)
6e4d5d
+{
6e4d5d
+  gpg_error_t err;
6e4d5d
+  gcry_sexp_t keyspec, key, domspec;
6e4d5d
+
6e4d5d
+  err = gcry_sexp_new (&domspec, domain, strlen(domain), 0);
6e4d5d
+  if (err)
6e4d5d
+    die ("gcry_sexp_build failed for domain spec: %s\n",
6e4d5d
+         gpg_strerror (err));
6e4d5d
+
6e4d5d
+  err = gcry_sexp_build (&keyspec, NULL,
6e4d5d
+                         "(genkey"
6e4d5d
+                         "  (dsa"
6e4d5d
+                         "    (use-fips186)"
6e4d5d
+                         "    %S))",
6e4d5d
+                         domspec);
6e4d5d
+  if (err)
6e4d5d
+    die ("gcry_sexp_build failed for DSA key generation: %s\n",
6e4d5d
+         gpg_strerror (err));
6e4d5d
+  err = gcry_pk_genkey (&key, keyspec);
6e4d5d
+  if (err)
6e4d5d
+    die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
6e4d5d
 
6e4d5d
   gcry_sexp_release (keyspec);
6e4d5d
 
f268f1
@@ -1732,7 +1830,7 @@ dsa_gen_with_seed (int keysize, const vo
6e4d5d
    with one parameter per line in hex format using this order: p, q,
6e4d5d
    g, seed, counter, h. */
6e4d5d
 static void
6e4d5d
-print_dsa_domain_parameters (gcry_sexp_t key)
6e4d5d
+print_dsa_domain_parameters (gcry_sexp_t key, int print_misc)
6e4d5d
 {
6e4d5d
   gcry_sexp_t l1, l2;
6e4d5d
   gcry_mpi_t mpi;
f268f1
@@ -1768,6 +1866,9 @@ print_dsa_domain_parameters (gcry_sexp_t
6e4d5d
     }
6e4d5d
   gcry_sexp_release (l1);
6e4d5d
 
6e4d5d
+  if (!print_misc)
6e4d5d
+	return;
6e4d5d
+
6e4d5d
   /* Extract the seed values.  */
6e4d5d
   l1 = gcry_sexp_find_token (key, "misc-key-info", 0);
6e4d5d
   if (!l1)
f268f1
@@ -1819,38 +1920,106 @@ print_dsa_domain_parameters (gcry_sexp_t
6e4d5d
 }
6e4d5d
 
6e4d5d
 
6e4d5d
-/* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
6e4d5d
+/* Print just the XY private key parameters.  KEY
6e4d5d
+   is the complete key as returned by dsa_gen.  We print to stdout
6e4d5d
+   with one parameter per line in hex format using this order: x, y. */
6e4d5d
+static void 
6e4d5d
+print_dsa_xy (gcry_sexp_t key)
6e4d5d
+{
6e4d5d
+  gcry_sexp_t l1, l2;
6e4d5d
+  gcry_mpi_t mpi;
6e4d5d
+  int idx;
6e4d5d
+
6e4d5d
+  l1 = gcry_sexp_find_token (key, "private-key", 0);
6e4d5d
+  if (!l1)
6e4d5d
+    die ("private key not found in genkey result\n");
6e4d5d
+
6e4d5d
+  l2 = gcry_sexp_find_token (l1, "dsa", 0);
6e4d5d
+  if (!l2)
6e4d5d
+    die ("returned private key not formed as expected\n");
6e4d5d
+  gcry_sexp_release (l1);
6e4d5d
+  l1 = l2;
6e4d5d
+
6e4d5d
+  /* Extract the parameters from the S-expression and print them to stdout.  */
6e4d5d
+  for (idx=0; "xy"[idx]; idx++) 
6e4d5d
+    {
6e4d5d
+      l2 = gcry_sexp_find_token (l1, "xy"+idx, 1);
6e4d5d
+      if (!l2)
6e4d5d
+        die ("no %c parameter in returned public key\n", "xy"[idx]);
6e4d5d
+      mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
6e4d5d
+      if (!mpi)
6e4d5d
+        die ("no value for %c parameter in returned private key\n","xy"[idx]);
6e4d5d
+      gcry_sexp_release (l2);
6e4d5d
+      if (standalone_mode)
6e4d5d
+        printf ("%c = ", "XY"[idx]);
6e4d5d
+      print_mpi_line (mpi, 1);
6e4d5d
+      gcry_mpi_release (mpi);
6e4d5d
+    }
6e4d5d
+
6e4d5d
+  gcry_sexp_release (l1);
6e4d5d
+}
6e4d5d
+
6e4d5d
+
6e4d5d
+/* Generate DSA pq domain parameters for a modulus size of KEYSIZE.  The
6e4d5d
    result is printed to stdout with one parameter per line in hex
6e4d5d
-   format and in this order: p, q, g, seed, counter, h.  If SEED is
6e4d5d
+   format and in this order: p, q, seed, counter.  If SEED is
6e4d5d
    not NULL this seed value will be used for the generation.  */
6e4d5d
 static void
6e4d5d
-run_dsa_pqg_gen (int keysize, const void *seed, size_t seedlen)
6e4d5d
+run_dsa_pqg_gen (int keysize, int qsize, const void *seed, size_t seedlen)
6e4d5d
 {
6e4d5d
   gcry_sexp_t key;
6e4d5d
 
6e4d5d
   if (seed)
6e4d5d
-    key = dsa_gen_with_seed (keysize, seed, seedlen);
6e4d5d
+    key = dsa_gen_with_seed (keysize, qsize, seed, seedlen);
6e4d5d
   else
6e4d5d
-    key = dsa_gen (keysize);
6e4d5d
-  print_dsa_domain_parameters (key);
6e4d5d
+    key = dsa_gen (keysize, qsize);
6e4d5d
+  print_dsa_domain_parameters (key, 1);
6e4d5d
+  gcry_sexp_release (key);
6e4d5d
+}
6e4d5d
+
6e4d5d
+
6e4d5d
+/* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
6e4d5d
+   result is printed to stdout with one parameter per line in hex
6e4d5d
+   format and in this order: p, q, g, seed, counter, h.  If SEED is
6e4d5d
+   not NULL this seed value will be used for the generation.  */
6e4d5d
+static void
6e4d5d
+run_dsa_g_gen (int keysize, int qsize, const char *domain)
6e4d5d
+{
6e4d5d
+  gcry_sexp_t key;
6e4d5d
+
6e4d5d
+  key = dsa_gen_key (domain);
6e4d5d
+  print_dsa_domain_parameters (key, 0);
6e4d5d
+  gcry_sexp_release (key);
6e4d5d
+}
6e4d5d
+
6e4d5d
+/* Generate a DSA key with specified domain parameters
6e4d5d
+   and print the XY values. */
6e4d5d
+static void
6e4d5d
+run_dsa_gen_key (const char *domain)
6e4d5d
+{
6e4d5d
+  gcry_sexp_t key;
6e4d5d
+
6e4d5d
+  key = dsa_gen_key (domain);
6e4d5d
+  print_dsa_xy (key);
6e4d5d
+
6e4d5d
   gcry_sexp_release (key);
6e4d5d
 }
6e4d5d
 
6e4d5d
 
6e4d5d
 /* Generate a DSA key of size of KEYSIZE and write the private key to
6e4d5d
    FILENAME.  Also write the parameters to stdout in the same way as
6e4d5d
-   run_dsa_pqg_gen.  */
6e4d5d
+   run_dsa_g_gen.  */
6e4d5d
 static void
6e4d5d
-run_dsa_gen (int keysize, const char *filename)
6e4d5d
+run_dsa_gen (int keysize, int qsize, const char *filename)
6e4d5d
 {
6e4d5d
   gcry_sexp_t key, private_key;
6e4d5d
   FILE *fp;
6e4d5d
 
6e4d5d
-  key = dsa_gen (keysize);
6e4d5d
+  key = dsa_gen (keysize, qsize);
6e4d5d
   private_key = gcry_sexp_find_token (key, "private-key", 0);
6e4d5d
   if (!private_key)
6e4d5d
     die ("private key not found in genkey result\n");
6e4d5d
-  print_dsa_domain_parameters (key);
6e4d5d
+  print_dsa_domain_parameters (key, 1);
6e4d5d
 
6e4d5d
   fp = fopen (filename, "wb");
6e4d5d
   if (!fp)
f268f1
@@ -1863,6 +2032,53 @@ run_dsa_gen (int keysize, const char *fi
6e4d5d
 }
6e4d5d
 
6e4d5d
 
6e4d5d
+static int
6e4d5d
+dsa_hash_from_key(gcry_sexp_t s_key)
6e4d5d
+{
6e4d5d
+  gcry_sexp_t l1, l2;
6e4d5d
+  gcry_mpi_t q;
6e4d5d
+  unsigned int qbits;
6e4d5d
+
6e4d5d
+  l1 = gcry_sexp_find_token (s_key, "public-key", 0);
6e4d5d
+  if (!l1)
6e4d5d
+    {
6e4d5d
+      l1 = gcry_sexp_find_token (s_key, "private-key", 0);
6e4d5d
+      if (!l1)
6e4d5d
+        die ("neither private nor public key found in the loaded key\n");
6e4d5d
+    }
6e4d5d
+
6e4d5d
+  l2 = gcry_sexp_find_token (l1, "dsa", 0);
6e4d5d
+  if (!l2)
6e4d5d
+    die ("public key not formed as expected - no dsa\n");
6e4d5d
+  gcry_sexp_release (l1);
6e4d5d
+  l1 = l2;
6e4d5d
+
6e4d5d
+  l2 = gcry_sexp_find_token (l1, "q", 0);
6e4d5d
+  if (!l2)
6e4d5d
+    die ("public key not formed as expected - no q\n");
6e4d5d
+  gcry_sexp_release (l1);
6e4d5d
+  l1 = l2;
6e4d5d
+
6e4d5d
+  q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
6e4d5d
+  if (!q)
6e4d5d
+    die ("public key not formed as expected - no mpi in q\n");
6e4d5d
+  qbits = gcry_mpi_get_nbits(q);
6e4d5d
+  gcry_sexp_release(l1);
6e4d5d
+  gcry_mpi_release(q);
6e4d5d
+  switch(qbits)
6e4d5d
+    {
6e4d5d
+    case 160:
6e4d5d
+	return GCRY_MD_SHA1;
6e4d5d
+    case 224:
6e4d5d
+	return GCRY_MD_SHA224;
6e4d5d
+    case 256:
6e4d5d
+        return GCRY_MD_SHA256;
6e4d5d
+    default:
6e4d5d
+        die("bad number bits (%d) of q in key\n", qbits);
6e4d5d
+    }
6e4d5d
+  return GCRY_MD_NONE;
6e4d5d
+}
6e4d5d
+
6e4d5d
 
6e4d5d
 /* Sign DATA of length DATALEN using the key taken from the S-expression
6e4d5d
    encoded KEYFILE. */
f268f1
@@ -1872,11 +2088,16 @@ run_dsa_sign (const void *data, size_t d
6e4d5d
 {
6e4d5d
   gpg_error_t err;
6e4d5d
   gcry_sexp_t s_data, s_key, s_sig, s_tmp, s_tmp2;
6e4d5d
-  char hash[20];
6e4d5d
+  char hash[128];
6e4d5d
   gcry_mpi_t tmpmpi;
6e4d5d
+  int algo;
6e4d5d
 
6e4d5d
-  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
6e4d5d
-  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
f268f1
+  s_key = read_sexp_from_file (keyfile);
f268f1
+  algo = dsa_hash_from_key(s_key);
f268f1
+
6e4d5d
+  gcry_md_hash_buffer (algo, hash, data, datalen);
6e4d5d
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
6e4d5d
+                       gcry_md_get_algo_dlen(algo), NULL);
6e4d5d
   if (!err)
6e4d5d
     {
6e4d5d
       err = gcry_sexp_build (&s_data, NULL,
f268f1
@@ -1887,8 +2108,6 @@ run_dsa_sign (const void *data, size_t d
6e4d5d
     die ("gcry_sexp_build failed for DSA data input: %s\n",
6e4d5d
          gpg_strerror (err));
6e4d5d
 
6e4d5d
-  s_key = read_sexp_from_file (keyfile);
6e4d5d
-
6e4d5d
   err = gcry_pk_sign (&s_sig, s_data, s_key);
6e4d5d
   if (err)
6e4d5d
     {
f268f1
@@ -1964,13 +2183,18 @@ run_dsa_verify (const void *data, size_t
6e4d5d
 {
6e4d5d
   gpg_error_t err;
6e4d5d
   gcry_sexp_t s_data, s_key, s_sig;
6e4d5d
-  char hash[20];
6e4d5d
+  char hash[128];
6e4d5d
   gcry_mpi_t tmpmpi;
6e4d5d
+  int algo;
6e4d5d
+
6e4d5d
+  s_key = read_sexp_from_file (keyfile);
6e4d5d
+  algo = dsa_hash_from_key(s_key);
6e4d5d
 
6e4d5d
-  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
6e4d5d
+  gcry_md_hash_buffer (algo, hash, data, datalen);
6e4d5d
   /* Note that we can't simply use %b with HASH to build the
6e4d5d
      S-expression, because that might yield a negative value.  */
6e4d5d
-  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
6e4d5d
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
6e4d5d
+                       gcry_md_get_algo_dlen(algo), NULL);
6e4d5d
   if (!err)
6e4d5d
     {
6e4d5d
       err = gcry_sexp_build (&s_data, NULL,
f268f1
@@ -1981,7 +2205,6 @@ run_dsa_verify (const void *data, size_t
6e4d5d
     die ("gcry_sexp_build failed for DSA data input: %s\n",
6e4d5d
          gpg_strerror (err));
6e4d5d
 
6e4d5d
-  s_key = read_sexp_from_file (keyfile);
6e4d5d
   s_sig = read_sexp_from_file (sigfile);
6e4d5d
 
6e4d5d
   err = gcry_pk_verify (s_sig, s_data, s_key);
f268f1
@@ -2014,7 +2237,7 @@ usage (int show_help)
6e4d5d
      "Run a crypto operation using hex encoded input and output.\n"
6e4d5d
      "MODE:\n"
6e4d5d
      "  encrypt, decrypt, digest, random, hmac-sha,\n"
6e4d5d
-     "  rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n"
6e4d5d
+     "  rsa-{derive,gen,sign,verify}, dsa-{pq-gen,g-gen,gen,sign,verify}\n"
6e4d5d
      "OPTIONS:\n"
6e4d5d
      "  --verbose        Print additional information\n"
6e4d5d
      "  --binary         Input and output is in binary form\n"
f268f1
@@ -2024,6 +2247,7 @@ usage (int show_help)
6e4d5d
      "  --dt DT          Use the hex encoded DT for the RNG\n"
6e4d5d
      "  --algo NAME      Use algorithm NAME\n"
6e4d5d
      "  --keysize N      Use a keysize of N bits\n"
6e4d5d
+     "  --qize N         Use a DSA q parameter size of N bits\n"
6e4d5d
      "  --signature NAME Take signature from file NAME\n"
6e4d5d
      "  --chunk N        Read in chunks of N bytes (implies --binary)\n"
6e4d5d
      "  --pkcs1          Use PKCS#1 encoding\n"
f268f1
@@ -2050,6 +2274,7 @@ main (int argc, char **argv)
6e4d5d
   const char *dt_string = NULL;
6e4d5d
   const char *algo_string = NULL;
6e4d5d
   const char *keysize_string = NULL;
6e4d5d
+  const char *qsize_string = NULL;
6e4d5d
   const char *signature_string = NULL;
6e4d5d
   FILE *input;
6e4d5d
   void *data;
f268f1
@@ -2143,6 +2368,14 @@ main (int argc, char **argv)
6e4d5d
           keysize_string = *argv;
6e4d5d
           argc--; argv++;
6e4d5d
         }
6e4d5d
+      else if (!strcmp (*argv, "--qsize"))
6e4d5d
+        {
6e4d5d
+          argc--; argv++;
6e4d5d
+          if (!argc)
6e4d5d
+            usage (0);
6e4d5d
+          qsize_string = *argv;
6e4d5d
+          argc--; argv++;
6e4d5d
+        }
6e4d5d
       else if (!strcmp (*argv, "--signature"))
6e4d5d
         {
6e4d5d
           argc--; argv++;
f268f1
@@ -2406,6 +2639,18 @@ main (int argc, char **argv)
f268f1
         die ("no data available (do not use --chunk)\n");
f268f1
       run_rsa_derive (data, datalen);
f268f1
     }
f268f1
+  else if (!strcmp (mode_string, "rsa-keygen"))
f268f1
+    {
f268f1
+      if (!data)
f268f1
+        die ("no data available (do not use --chunk)\n");
f268f1
+      run_rsa_keygen (data, datalen, 0);
f268f1
+    }
f268f1
+  else if (!strcmp (mode_string, "rsa-keygen-kat"))
f268f1
+    {
f268f1
+      if (!data)
f268f1
+        die ("no data available (do not use --chunk)\n");
f268f1
+      run_rsa_keygen (data, datalen, 1);
f268f1
+    }
f268f1
   else if (!strcmp (mode_string, "rsa-gen"))
f268f1
     {
f268f1
       int keysize;
f268f1
@@ -2463,23 +2708,49 @@ main (int argc, char **argv)
6e4d5d
     }
6e4d5d
   else if (!strcmp (mode_string, "dsa-pqg-gen"))
6e4d5d
     {
6e4d5d
-      int keysize;
6e4d5d
+      int keysize, qsize;
6e4d5d
 
6e4d5d
       keysize = keysize_string? atoi (keysize_string) : 0;
6e4d5d
       if (keysize < 1024 || keysize > 3072)
6e4d5d
         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
6e4d5d
-      run_dsa_pqg_gen (keysize, datalen? data:NULL, datalen);
6e4d5d
+      qsize = qsize_string? atoi (qsize_string) : 0;
6e4d5d
+      if (qsize < 160 || qsize > 256)
6e4d5d
+        die ("invalid qsize specified; needs to be 160 .. 256\n");
6e4d5d
+      run_dsa_pqg_gen (keysize, qsize, datalen? data:NULL, datalen);
6e4d5d
+    }
6e4d5d
+  else if (!strcmp (mode_string, "dsa-g-gen"))
6e4d5d
+    {
6e4d5d
+      int keysize, qsize;
6e4d5d
+
6e4d5d
+      keysize = keysize_string? atoi (keysize_string) : 0;
6e4d5d
+      if (keysize < 1024 || keysize > 3072)
6e4d5d
+        die ("invalid keysize specified; needs to be 1024 .. 3072\n");
6e4d5d
+      qsize = qsize_string? atoi (qsize_string) : 0;
6e4d5d
+      if (qsize < 160 || qsize > 256)
6e4d5d
+        die ("invalid qsize specified; needs to be 160 .. 256\n");
6e4d5d
+      if (!key_string)
6e4d5d
+        die ("option --key containing pq domain parameters is required in this mode\n");
6e4d5d
+      run_dsa_g_gen (keysize, qsize, key_string);
6e4d5d
+    }
6e4d5d
+  else if (!strcmp (mode_string, "dsa-gen-key"))
6e4d5d
+    {
6e4d5d
+      if (!key_string)
6e4d5d
+        die ("option --key containing pqg domain parameters is required in this mode\n");
6e4d5d
+      run_dsa_gen_key (key_string);
6e4d5d
     }
6e4d5d
   else if (!strcmp (mode_string, "dsa-gen"))
6e4d5d
     {
6e4d5d
-      int keysize;
6e4d5d
+      int keysize, qsize;
6e4d5d
 
6e4d5d
       keysize = keysize_string? atoi (keysize_string) : 0;
6e4d5d
       if (keysize < 1024 || keysize > 3072)
6e4d5d
         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
6e4d5d
+      qsize = qsize_string? atoi (qsize_string) : 0;
6e4d5d
+      if (qsize < 160 || qsize > 256)
6e4d5d
+        die ("invalid qsize specified; needs to be 160 .. 256\n");
6e4d5d
       if (!key_string)
6e4d5d
         die ("option --key is required in this mode\n");
6e4d5d
-      run_dsa_gen (keysize, key_string);
6e4d5d
+      run_dsa_gen (keysize, qsize, key_string);
6e4d5d
     }
6e4d5d
   else if (!strcmp (mode_string, "dsa-sign"))
6e4d5d
     {