[libgcrypt] Make the FIPS-186-3 DSA implementation CAVS testable

Tomáš Mráz tmraz at fedoraproject.org
Mon May 30 12:23:26 UTC 2011


commit db9fb5d2e7ad8b1850deba0a0c36b711deaf1f10
Author: Tomas Mraz <tmraz at fedoraproject.org>
Date:   Mon May 30 14:23:11 2011 +0200

    Make the FIPS-186-3 DSA implementation CAVS testable

 libgcrypt-1.4.6-cavs.patch | 1160 ++++++++++++++++++++++++++++++++++++++++++++
 libgcrypt.spec             |    7 +-
 2 files changed, 1166 insertions(+), 1 deletions(-)
---
diff --git a/libgcrypt-1.4.6-cavs.patch b/libgcrypt-1.4.6-cavs.patch
new file mode 100644
index 0000000..c41e900
--- /dev/null
+++ b/libgcrypt-1.4.6-cavs.patch
@@ -0,0 +1,1160 @@
+diff -up libgcrypt-1.4.6/cipher/dsa.c.cavs libgcrypt-1.4.6/cipher/dsa.c
+--- libgcrypt-1.4.6/cipher/dsa.c.cavs	2011-05-26 22:03:17.000000000 +0200
++++ libgcrypt-1.4.6/cipher/dsa.c	2011-05-26 22:03:18.000000000 +0200
+@@ -467,7 +467,6 @@ generate_fips186 (DSA_secret_key *sk, un
+             initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1,
+                                                     &initial_seed.seedlen);
+         }
+-      
+       if (use_fips186_2)
+         ec = _gcry_generate_fips186_2_prime (nbits, qbits, 
+                                            initial_seed.seed, 
+@@ -475,13 +474,22 @@ generate_fips186 (DSA_secret_key *sk, un
+                                            &prime_q, &prime_p, 
+                                            r_counter,
+                                            r_seed, r_seedlen);
+-      else
++      else if (!domain->p || !domain->q)
+         ec = _gcry_generate_fips186_3_prime (nbits, qbits,
+                                           initial_seed.seed,
+                                           initial_seed.seedlen,
+                                           &prime_q, &prime_p,
+                                           r_counter,
+                                           r_seed, r_seedlen, NULL);
++      else
++        {
++          /* Domain parameters p and q are given; use them.  */
++          prime_p = mpi_copy (domain->p);
++          prime_q = mpi_copy (domain->q);
++          gcry_assert (mpi_get_nbits (prime_p) == nbits);
++          gcry_assert (mpi_get_nbits (prime_q) == qbits);
++          ec = 0;
++        }
+       gcry_sexp_release (initial_seed.sexp);
+       if (ec)
+         goto leave;
+@@ -772,13 +780,12 @@ dsa_generate_ext (int algo, unsigned int
+           gcry_sexp_release (l1);
+           gcry_sexp_release (domainsexp);
+ 
+-          /* Check that all domain parameters are available.  */
+-          if (!domain.p || !domain.q || !domain.g)
++          /* Check that p and q domain parameters are available.  */
++          if (!domain.p || !domain.q || (!domain.g && !use_fips186))
+             {
+               gcry_mpi_release (domain.p);
+               gcry_mpi_release (domain.q);
+               gcry_mpi_release (domain.g);
+-              gcry_sexp_release (deriveparms);
+               return GPG_ERR_MISSING_VALUE;
+             }
+ 
+diff -up libgcrypt-1.4.6/tests/cavs_driver.pl.cavs libgcrypt-1.4.6/tests/cavs_driver.pl
+--- libgcrypt-1.4.6/tests/cavs_driver.pl.cavs	2009-04-02 11:25:34.000000000 +0200
++++ libgcrypt-1.4.6/tests/cavs_driver.pl	2011-05-27 21:32:14.000000000 +0200
+@@ -1,9 +1,11 @@
+ #!/usr/bin/env perl
+ #
+-# $Id: cavs_driver.pl 1497 2009-01-22 14:01:29Z smueller $
++# $Id: cavs_driver.pl 2124 2010-12-20 07:56:30Z smueller $
+ #
+ # CAVS test driver (based on the OpenSSL driver)
+ # Written by: Stephan Müller <sm at atsec.com>
++#	      Werner Koch <wk at g10code.com> (libgcrypt interface)
++#	      Tomas Mraz <tmraz at redhat.com> (addition of DSA2)
+ # Copyright (c) atsec information security corporation
+ #
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -85,13 +87,16 @@
+ #	T[CBC|CFB??|ECB|OFB]varkey
+ #	T[CBC|CFB??|ECB|OFB]invperm
+ #	T[CBC|CFB??|ECB|OFB]vartext
++# WARNING: TDES in CFB and OFB mode problems see below
+ #
+ # ANSI X9.31 RNG
+ # 	ANSI931_AES128MCT
+ # 	ANSI931_AES128VST
+ #
+-# DSA
++# DSA2
+ # 	PQGGen
++#	PQGVer
++#	KeyPair
+ # 	SigGen
+ # 	SigVer
+ #
+@@ -101,6 +106,36 @@
+ # 	RC4PltBD
+ # 	RC4REGT
+ #
++#
++# TDES MCT for CFB and OFB:
++# -------------------------
++# The inner loop cannot be handled by this script. If you want to have tests
++# for these cipher types, implement your own inner loop and add it to
++# crypto_mct.
++#
++# the value $next_source in crypto_mct is NOT set by the standard implementation
++# of this script. It would need to be set as follows for these two (code take
++# from fipsdrv.c from libgcrypt - the value input at the end will contain the
++# the value for $next_source:
++#
++# ... inner loop ...
++# ...
++# get_current_iv (hd, last_iv, blocklen);
++# ... encrypt / decrypt (input is the data to be en/decrypted and output is the
++#                        result of operation) ...
++# if (encrypt_mode && (cipher_mode == GCRY_CIPHER_MODE_CFB))
++#   memcpy (input, last_iv, blocklen);
++# else if (cipher_mode == GCRY_CIPHER_MODE_OFB)
++#   memcpy (input, last_iv, blocklen);
++# else if (!encrypt_mode && cipher_mode == GCRY_CIPHER_MODE_CFB)
++#   {
++#      /* Reconstruct the output vector.  */
++#      int i;
++#      for (i=0; i < blocklen; i++)
++#         input[i] ^= output[i];
++#   }
++# ... inner loop ends ...
++# ==> now, the value of input is to be put into $next_source
+ 
+ use strict;
+ use warnings;
+@@ -226,6 +261,8 @@ my $hmac;
+ # Generate the P, Q, G, Seed, counter, h (value used to generate g) values
+ # for DSA
+ # $1: modulus size
++# $2: q size
++# $3: seed (might be empty string)
+ # 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
+@@ -236,6 +273,19 @@ my $hmac;
+ #         h
+ my $dsa_pqggen;
+ 
++# Generate the G value from P and Q
++# for DSA
++# $1: modulus size
++# $2: q size
++# $3: P in hex form
++# $4: Q 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
++#         G\n
++my $dsa_ggen;
++
+ #
+ # Generate an DSA public key from the provided parameters:
+ # $1: Name of file to create
+@@ -255,10 +305,20 @@ 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
++# $1: modulus size
++# $2: q size
++# $3 keyfile name 
++# return: file created with key, string with values of P, Q, G in hex format
+ my $gen_dsakey;
+ 
++# generate a new DSA private key XY parameters in domain:
++#      PEM format
++# $1: P in hex form
++# $2: Q in hex form
++# $3: G in hex form 
++# return: string with values of X, Y in hex format
++my $gen_dsakey_domain;
++
+ # Sign a message with DSA
+ # $1: data to be signed in hex form
+ # $2: Key file in PEM format with the private key
+@@ -500,17 +560,32 @@ sub libgcrypt_hmac($$$$) {
+ 	return pipe_through_program($msg, $program);	
+ }
+ 
+-sub libgcrypt_dsa_pqggen($) {
++sub libgcrypt_dsa_pqggen($$$) {
+ 	my $mod = shift;
++	my $qsize = shift;
++	my $seed = shift;
++
++	my $program = "fipsdrv --keysize $mod --qsize $qsize dsa-pqg-gen";
++	return pipe_through_program($seed, $program);
++}
+ 
+-	my $program = "fipsdrv --keysize $mod dsa-pqg-gen";
++sub libgcrypt_dsa_ggen($$$$) {
++	my $mod = shift;
++	my $qsize = shift;
++	my $p = shift;
++	my $q = shift;
++	my $domain = "(domain (p #$p#)(q #$q#))";
++
++	my $program = "fipsdrv --keysize $mod --qsize $qsize --key \'$domain\' dsa-g-gen";
+ 	return pipe_through_program("", $program);
+ }
+ 
+-sub libgcrypt_gen_dsakey($) {
++sub libgcrypt_gen_dsakey($$$) {
++	my $mod = shift;
++	my $qsize = shift;
+ 	my $file = shift;
+ 
+-	my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
++	my $program = "fipsdrv --keysize $mod --qsize $qsize --key $file dsa-gen";
+ 	my $tmp;
+ 	my %ret;
+ 
+@@ -519,10 +594,21 @@ sub libgcrypt_gen_dsakey($) {
+ 	$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);
++	@ret{'P', 'Q', 'G'} = split(/\n/, $tmp);
+ 	return %ret;
+ }
+ 
++sub libgcrypt_gen_dsakey_domain($$$) {
++	my $p = shift;
++	my $q = shift;
++	my $g = shift;
++	my $domain = "(domain (p #$p#)(q #$q#)(g #$g#))";
++
++	my $program = "fipsdrv --key '$domain' dsa-gen-key";
++
++	return pipe_through_program("", $program);
++}
++
+ sub libgcrypt_dsa_genpubkey($$$$$) {
+ 	my $filename = shift;
+ 	my $p = shift;
+@@ -1139,7 +1225,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";
++	$out .= "Mac = " . lc(&$hmac($key, $tlen, $msg, $hashtype{$tlen})) . "\n";
+ 
+ 	return $out;
+ }
+@@ -1205,7 +1291,7 @@ 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/);
++		$cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/ && defined($state_cipher_des));
+                 my $pid = open2($CO, $CI, $cipher_imp);
+ 
+                 my $calc_data = $iv; # CT[j]
+@@ -1213,8 +1299,8 @@ sub crypto_mct($$$$$$$$) {
+                 my $old_old_calc_data; # CT[j-2]
+ 		my $next_source;
+ 
+-		# TDES inner loop implements logic within driver
+-		if ($cipher =~ /des/) {
++		# TDES inner loop implements logic within driver of libgcrypt
++		if ($cipher =~ /des/ && $opt{'I'} && $opt{'I'} eq 'libgcrypt' ) {
+ 			# Need to provide a dummy IV in case of ECB mode.
+ 			my $iv_arg = (defined($iv) && $iv ne "")
+ 					? bin2hex($iv)
+@@ -1238,6 +1324,10 @@ sub crypto_mct($$$$$$$$) {
+ 			$line = <$CO>;
+ 		} else {
+ 	                for (my $j = 0; $j < $iloop; ++$j) {
++				if ($cipher =~ /des-ede3-ofb/ ||
++				    (!$enc && $cipher =~ /des-ede3-cfb/)) {
++					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"; 
++				}
+ 				$old_old_calc_data = $old_calc_data;
+                 	        $old_calc_data = $calc_data;
+ 
+@@ -1503,21 +1593,23 @@ sub rngx931($$$$) {
+ 	return $out;
+ }
+ 
+-# DSA PQGGen test
++# DSA PQGen test
+ # $1 modulus size
+-# $2 number of rounds to perform the test
++# $2 q size
++# $3 number of rounds to perform the test
+ # return: string formatted as expected by CAVS
+-sub dsa_pqggen_driver($$) {
++sub dsa_pqgen_driver($$$) {
+ 	my $mod = shift;
++	my $qsize = shift;
+ 	my $rounds = shift;
+ 
+ 	my $out = "";
+ 	for(my $i=0; $i<$rounds; $i++) {
+-		my $ret = &$dsa_pqggen($mod);
++		my $ret = &$dsa_pqggen($mod, $qsize, "");
+ 		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));
++		die "Return value does not contain all expected values of P, Q, Seed, c for dsa_pqggen"
++			if (!defined($P) || !defined($Q) ||
++			    !defined($Seed) || !defined($c));
+ 
+ 		# now change the counter to decimal as CAVS wants decimal
+ 		# counter value although all other is HEX
+@@ -1525,15 +1617,149 @@ sub dsa_pqggen_driver($$) {
+ 
+ 		$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";
++		$out .= "domain_parameter_seed = $Seed\n";
++		$out .= "counter = $c\n\n";
++	}
++
++	return $out;
++}
++
++# DSA GGen test
++# $1 modulus size
++# $2 q size
++# $3 p in hex form
++# $4 q in hex form
++# return: string formatted as expected by CAVS
++sub dsa_ggen_driver($$$$) {
++	my $mod = shift;
++	my $qsize = shift;
++	my $p = shift;
++	my $q = shift;
++
++	my $out = "";
++	my $ret = &$dsa_ggen($mod, $qsize, $p, $q);
++	my ($P, $Q, $G) = split(/\n/, $ret);
++	die "Return value does not contain all expected values of P, Q, G for dsa_ggen"
++		if (!defined($P) || !defined($Q) || !defined($G));
++
++	$out .= "G = $G\n\n";
++
++	return $out;
++}
++
++# DSA PQVer test
++# $1 modulus size
++# $2 q size
++# $3 p in hex form
++# $4 q in hex form
++# $5 seed in hex form
++# $6 c decimal counter
++# return: string formatted as expected by CAVS
++sub dsa_pqver_driver($$$$$$) {
++	my $mod = shift;
++	my $qsize = shift;
++	my $p = shift;
++	my $q = shift;
++	my $seed = shift;
++	my $c = shift;
++
++	my $out = "";
++	my $ret = &$dsa_pqggen($mod, $qsize, $seed);
++	my ($P, $Q, $G, $seed2, $c2, $h2) = split(/\n/, $ret);
++	die "Return value does not contain all expected values of P, Q, G, seed, c for dsa_pqggen"
++		if (!defined($P) || !defined($Q) || !defined($G) ||
++		    !defined($seed2) || !defined($c2));
++
++	$c2 = hex($c2);
++
++	$out .= "Seed = $seed\n";
++	$out .= "c = $c\n";
++
++	if ($P eq $p && $Q eq $q && $seed eq lc $seed2 && $c eq $c2) {
++		$out .= "Result = P\n\n";
++	}
++	else {
++		$out .= "Result = F\n\n";
++	}
++	return $out;
++}
++
++# DSA PQGVer test
++# $1 modulus size
++# $2 q size
++# $3 p in hex form
++# $4 q in hex form
++# $5 g in hex form
++# $6 seed in hex form
++# $7 c decimal counter
++# $8 h in hex form
++# return: string formatted as expected by CAVS
++sub dsa_pqgver_driver($$$$$$$$) {
++	my $mod = shift;
++	my $qsize = shift;
++	my $p = shift;
++	my $q = shift;
++	my $g = shift;
++	my $seed = shift;
++	my $c = shift;
++	my $h = shift;
++
++	my $out = "";
++	my $ret = &$dsa_pqggen($mod, $qsize, $seed);
++	my ($P, $Q, $G, $seed2, $c2, $h2) = 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($seed2) || !defined($c2) || !defined($h2));
++
++	
++
++	$out .= "Seed = $seed\n";
++	$out .= "c = $c\n";
++	$out .= "H = $h\n";
++
++	$c2 = hex($c2);
++
++	if ($P eq $p && $Q eq $q && $G eq $g && $seed eq lc $seed2 && 
++	    $c eq $c2 && hex($h) == hex($h2)) {
++		$out .= "Result = P\n\n";
++	}
++	else {
++		$out .= "Result = F\n\n";
+ 	}
+ 
+ 	return $out;
+ }
+ 
++# DSA Keypair test
++# $1 modulus size
++# $2 q size
++# $3 number of rounds to perform the test
++# return: string formatted as expected by CAVS
++sub dsa_keypair_driver($$$) {
++	my $mod = shift;
++	my $qsize = shift;
++	my $rounds = shift;
++
++	my $out = "";
++	my $tmpkeyfile = "dsa_siggen.tmp.$$";
++	my %pqg = &$gen_dsakey($mod, $qsize, $tmpkeyfile);
++	$out .= "P = " . $pqg{'P'} . "\n";
++	$out .= "Q = " . $pqg{'Q'} . "\n";
++	$out .= "G = " . $pqg{'G'} . "\n\n";
++	unlink($tmpkeyfile);
++
++	for(my $i=0; $i<$rounds; $i++) {
++		my $ret = &$gen_dsakey_domain($pqg{'P'}, $pqg{'Q'}, $pqg{'G'});
++		my ($X, $Y) = split(/\n/, $ret);
++		die "Return value does not contain all expected values of X, Y for gen_dsakey_domain"
++			if (!defined($X) || !defined($Y));
++
++		$out .= "X = $X\n";
++		$out .= "Y = $Y\n\n";
++	}
++
++	return $out;
++}
+ 
+ # DSA SigGen test
+ # $1: Message to be signed in hex form
+@@ -1658,12 +1884,16 @@ sub parse($$) {
+ 	my $klen = "";
+ 	my $tlen = "";
+ 	my $modulus = "";
++	my $qsize = "";
+ 	my $capital_n = 0;
++	my $num = 0;
+ 	my $capital_p = "";
+ 	my $capital_q = "";
+ 	my $capital_g = "";
+ 	my $capital_y = "";
+ 	my $capital_r = "";
++	my $capital_h = "";
++	my $c = "";
+ 	my $xp1 = "";
+ 	my $xp2 = "";
+ 	my $Xp = "";
+@@ -1700,7 +1930,7 @@ sub parse($$) {
+ 
+ 		##### 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|PQGGen|KeyGen RSA)/) {
++		if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA|KeyPair|PQGVer)/) {
+ 			if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
+ 			elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
+ 			elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
+@@ -1749,7 +1979,15 @@ sub parse($$) {
+ 
+ 			if ($tt == 0) {
+ 			##### Identify the test type
+-				if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) {
++				if ($tmpline =~ /PQGVer/) {
++					$tt = 16;
++					die "Interface function for DSA PQGVer testing not defined for tested library"
++						if (!defined($dsa_pqggen));
++				} elsif ($tmpline =~ /KeyPair/) {
++					$tt = 14;
++					die "Interface function dsa_keygen for DSA key generation not defined for tested library"
++						if (!defined($gen_dsakey_domain));
++				} elsif ($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));
+@@ -1760,11 +1998,11 @@ sub parse($$) {
+ 				} 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));
++						if (!defined($dsa_sign) || !defined($gen_dsakey));
+ 				} elsif ($tmpline =~ /PQGGen/) {
+ 					$tt = 10;
+ 					die "Interface function for DSA PQGGen testing not defined for tested library"
+-						if (!defined($dsa_pqggen));
++						if (!defined($dsa_pqggen) || !defined($dsa_ggen));
+ 				} elsif ($tmpline =~ /Hash sizes tested/) {
+ 					$tt = 9;
+ 					die "Interface function hmac for HMAC testing not defined for tested library"
+@@ -1792,7 +2030,7 @@ sub parse($$) {
+ 				} 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));
++						if (!defined($state_cipher) && !defined($state_cipher_des));
+ 				} elsif ($cipher =~ /^sha/) {
+ 					$tt = 3;
+ 					die "Interface function hash for Hashing not defined for tested library"
+@@ -1875,18 +2113,44 @@ sub parse($$) {
+ 			die "Msg/Seed seen twice - input file crap" if ($pt ne "");
+ 			$pt=$2;
+ 		}
+-		elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
++		elsif ($line =~ /^\[A.2.1\s.*\]$/) { # found in DSA2 PQGGen request
++			$out .= $line . "\n"; # print it
++			if ($tt == 10) {
++				# now generate G from PQ
++				$tt = 15;
++			}
++		}
++		elsif ($line =~ /^\[A.2.2\s.*\]$/) { # found in DSA2 PQGVer request
++			$out .= $line . "\n"; # print it
++			if ($tt == 16) {
++				# now verify PQG
++				$tt = 17;
++			}
++		}
++		elsif ($line =~ /^\[mod\s*=\s*L=([0-9]*),\s*N=([0-9]*).*\]$/) { # found in DSA2 requests
+ 			$modulus = $1;
++			$qsize = $2;
+ 			$out .= $line . "\n\n"; # print it
++			# clear eventual PQG
++			$capital_p = "";
++			$capital_q = "";
++			$capital_g = "";
+ 			# generate the private key with given bit length now
+ 			# as we have the required key length in bit
+ 			if ($tt == 11) {
+ 				$dsa_keyfile = "dsa_siggen.tmp.$$";
+-				my %pqg = &$gen_dsakey($dsa_keyfile);
++				my %pqg = &$gen_dsakey($modulus, $qsize, $dsa_keyfile);
+ 				$out .= "P = " . $pqg{'P'} . "\n";
+ 				$out .= "Q = " . $pqg{'Q'} . "\n";
+-				$out .= "G = " . $pqg{'G'} . "\n";
+-			} elsif ( $tt == 5 ) {
++				$out .= "G = " . $pqg{'G'} . "\n\n";
++                        }
++                }
++		elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
++			$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 ) {
+ 				# 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
+@@ -1932,11 +2196,16 @@ sub parse($$) {
+ 				if ($tlen ne "");
+ 			$tlen=$1;
+ 		}
+-		elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA PQGGen
++		elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA KeyPair
+ 			die "N seen twice - check input file"
+ 				if ($capital_n);
+ 			$capital_n = $1;
+ 		}
++		elsif ($line =~ /^Num\s*=\s*(.*)/) { #DSA PQGGen
++			die "Num seen twice - check input file"
++				if ($num);
++			$num = $1;
++		}
+ 		elsif ($line =~ /^P\s*=\s*(.*)/) { #DSA SigVer
+ 			die "P seen twice - check input file"
+ 				if ($capital_p);
+@@ -1965,6 +2234,16 @@ sub parse($$) {
+ 				if ($capital_r);
+ 			$capital_r = $1;
+ 		}
++		elsif ($line =~ /^H\s*=\s*(.*)/) { #DSA PQGVer
++			die "H seen twice - check input file"
++				if ($capital_h);
++			$capital_h = $1;
++		}
++		elsif ($line =~ /^c\s*=\s*(.*)/) { #DSA PQGVer
++			die "c seen twice - check input file"
++				if ($c);
++			$c = $1;
++		}
+ 		elsif ($line =~ /^xp1\s*=\s*(.*)/) { #RSA key gen
+ 			die "xp1 seen twice - check input file"
+ 				if ($xp1);
+@@ -2074,11 +2353,10 @@ sub parse($$) {
+ 			}
+ 		}
+ 		elsif ($tt == 10) {
+-			if ($modulus ne "" && $capital_n > 0) {
+-				$out .= dsa_pqggen_driver($modulus, $capital_n);
+-				#$mod is not resetted
+-				$capital_n = 0;
+-			}
++			if ($modulus ne "" && $qsize ne "" && $num > 0) {
++				$out .= dsa_pqgen_driver($modulus, $qsize, $num);
++				$num = 0;
++                        }
+ 		}
+ 		elsif ($tt == 11) {
+ 			if ($pt ne "" && $dsa_keyfile ne "") {
+@@ -2141,6 +2419,74 @@ sub parse($$) {
+ 				$Xq = "";
+ 			}
+ 		}
++		elsif ($tt == 14) {
++			if ($modulus ne "" &&
++			    $qsize ne "" &&
++			    $capital_n > 0) {
++				$out .= dsa_keypair_driver($modulus,
++							   $qsize,
++							   $capital_n);
++				$capital_n = 0;
++			}
++		}
++		elsif ($tt == 15) {
++			if ($modulus ne "" &&
++			    $qsize ne "" &&
++			    $capital_p ne "" &&
++			    $capital_q ne "") {
++				$out .= dsa_ggen_driver($modulus,
++							$qsize,
++							$capital_p,
++							$capital_q);
++				$capital_p = "";
++				$capital_q = "";
++				$num--;
++			}
++		}
++		elsif ($tt == 16) {
++			if ($modulus ne "" &&
++			    $qsize ne "" &&
++			    $capital_p ne "" &&
++			    $capital_q ne "" &&
++			    $pt ne "" &&
++			    $c ne "") {
++				$out .= dsa_pqver_driver($modulus,
++							$qsize,
++							$capital_p,
++							$capital_q,
++							$pt,
++							$c);
++				$capital_p = "";
++				$capital_q = "";
++				$pt = "";
++				$c = "";
++			}
++		}
++		elsif ($tt == 17) {
++			if ($modulus ne "" &&
++			    $qsize ne "" &&
++			    $capital_p ne "" &&
++			    $capital_q ne "" &&
++			    $capital_g ne "" &&
++			    $pt ne "" &&
++			    $c ne "" &&
++			    $capital_h ne "") {
++				$out .= dsa_pqgver_driver($modulus,
++							$qsize,
++							$capital_p,
++							$capital_q,
++							$capital_g,
++							$pt,
++							$c,
++							$capital_h);
++				$capital_p = "";
++				$capital_q = "";
++				$capital_g = "";
++				$pt = "";
++				$c = "";
++				$capital_h = "";
++			}
++		}
+ 		elsif ($tt > 0) {
+ 			die "Test case $tt not defined";
+ 		}
+@@ -2199,7 +2545,9 @@ sub main() {
+ 		$state_rng =	\&libgcrypt_state_rng;
+ 		$hmac =		\&libgcrypt_hmac;
+ 		$dsa_pqggen = 	\&libgcrypt_dsa_pqggen;
++		$dsa_ggen =	\&libgcrypt_dsa_ggen;
+ 		$gen_dsakey =   \&libgcrypt_gen_dsakey;
++		$gen_dsakey_domain =	\&libgcrypt_gen_dsakey_domain;
+ 		$dsa_sign =     \&libgcrypt_dsa_sign;
+ 		$dsa_verify =   \&libgcrypt_dsa_verify;
+ 		$dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
+diff -up libgcrypt-1.4.6/tests/cavs_tests.sh.cavs libgcrypt-1.4.6/tests/cavs_tests.sh
+--- libgcrypt-1.4.6/tests/cavs_tests.sh.cavs	2011-05-26 21:02:02.000000000 +0200
++++ libgcrypt-1.4.6/tests/cavs_tests.sh	2011-05-26 22:20:20.000000000 +0200
+@@ -55,7 +55,7 @@ function run_one_test () {
+     [ -d "$respdir" ] || mkdir "$respdir"
+     [ -f "$rspfile" ] &&  rm "$rspfile"
+ 
+-    if echo "$reqfile" | grep '/DSA/req/' >/dev/null 2>/dev/null; then
++    if echo "$reqfile" | grep '/DSA.\?/req/' >/dev/null 2>/dev/null; then
+         dflag="-D"
+     fi 
+     
+diff -up libgcrypt-1.4.6/tests/fipsdrv.c.cavs libgcrypt-1.4.6/tests/fipsdrv.c
+--- libgcrypt-1.4.6/tests/fipsdrv.c.cavs	2009-04-02 11:25:34.000000000 +0200
++++ libgcrypt-1.4.6/tests/fipsdrv.c	2011-05-27 18:03:11.000000000 +0200
+@@ -893,9 +893,12 @@ print_mpi_line (gcry_mpi_t a, int no_lz)
+     die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err));
+ 
+   p = buf;
++  while (*p)
++     *p++ = tolower(*p);
++  p = buf;
+   if (no_lz && p[0] == '0' && p[1] == '0' && p[2])
+     p += 2;
+-    
++
+   printf ("%s\n", p);
+   if (ferror (stdout))
+     writerr++;
+@@ -1675,14 +1678,14 @@ run_rsa_verify (const void *data, size_t
+ /* Generate a DSA key of size KEYSIZE and return the complete
+    S-expression.  */
+ static gcry_sexp_t
+-dsa_gen (int keysize)
++dsa_gen (int keysize, int qsize)
+ {
+   gpg_error_t err;
+   gcry_sexp_t keyspec, key;
+ 
+   err = gcry_sexp_build (&keyspec, NULL, 
+-                         "(genkey (dsa (nbits %d)(use-fips186-2)))",
+-                         keysize);
++                         "(genkey (dsa (nbits %d)(qbits %d)(use-fips186)))",
++                         keysize, qsize);
+   if (err)
+     die ("gcry_sexp_build failed for DSA key generation: %s\n",
+          gpg_strerror (err));
+@@ -1700,7 +1703,7 @@ dsa_gen (int keysize)
+ /* Generate a DSA key of size KEYSIZE and return the complete
+    S-expression.  */
+ static gcry_sexp_t
+-dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
++dsa_gen_with_seed (int keysize, int qsize, const void *seed, size_t seedlen)
+ {
+   gpg_error_t err;
+   gcry_sexp_t keyspec, key;
+@@ -1709,10 +1712,11 @@ dsa_gen_with_seed (int keysize, const vo
+                          "(genkey"
+                          "  (dsa"
+                          "    (nbits %d)"
+-                         "    (use-fips186-2)"
++                         "    (qbits %d)"
++                         "    (use-fips186)"
+                          "    (derive-parms"
+                          "      (seed %b))))",
+-                         keysize, (int)seedlen, seed);
++                         keysize, qsize, (int)seedlen, seed);
+   if (err)
+     die ("gcry_sexp_build failed for DSA key generation: %s\n",
+          gpg_strerror (err));
+@@ -1726,13 +1730,44 @@ dsa_gen_with_seed (int keysize, const vo
+   return key;
+ }
+ 
++/* Generate a DSA key with specified domain parameters and return the complete
++   S-expression.  */
++static gcry_sexp_t
++dsa_gen_key (const char *domain)
++{
++  gpg_error_t err;
++  gcry_sexp_t keyspec, key, domspec;
++
++  err = gcry_sexp_new (&domspec, domain, strlen(domain), 0);
++  if (err)
++    die ("gcry_sexp_build failed for domain spec: %s\n",
++         gpg_strerror (err));
++
++  err = gcry_sexp_build (&keyspec, NULL, 
++                         "(genkey"
++                         "  (dsa"
++                         "    (use-fips186)"
++                         "    %S))",
++                         domspec);
++  if (err)
++    die ("gcry_sexp_build failed for DSA key generation: %s\n",
++         gpg_strerror (err));
++  err = gcry_pk_genkey (&key, keyspec);
++  if (err)
++    die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
++  
++  gcry_sexp_release (keyspec);
++
++  return key;
++}
++
+ 
+ /* Print the domain parameter as well as the derive information.  KEY
+    is the complete key as returned by dsa_gen.  We print to stdout
+    with one parameter per line in hex format using this order: p, q,
+    g, seed, counter, h. */
+ static void 
+-print_dsa_domain_parameters (gcry_sexp_t key)
++print_dsa_domain_parameters (gcry_sexp_t key, int print_misc)
+ {
+   gcry_sexp_t l1, l2;
+   gcry_mpi_t mpi;
+@@ -1768,6 +1803,9 @@ print_dsa_domain_parameters (gcry_sexp_t
+     }
+   gcry_sexp_release (l1);
+ 
++  if (!print_misc)
++	return;
++
+   /* Extract the seed values.  */
+   l1 = gcry_sexp_find_token (key, "misc-key-info", 0);
+   if (!l1)
+@@ -1819,38 +1857,106 @@ print_dsa_domain_parameters (gcry_sexp_t
+ }
+ 
+ 
+-/* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
++/* Print just the XY private key parameters.  KEY
++   is the complete key as returned by dsa_gen.  We print to stdout
++   with one parameter per line in hex format using this order: x, y. */
++static void 
++print_dsa_xy (gcry_sexp_t key)
++{
++  gcry_sexp_t l1, l2;
++  gcry_mpi_t mpi;
++  int idx;
++
++  l1 = gcry_sexp_find_token (key, "private-key", 0);
++  if (!l1)
++    die ("private key not found in genkey result\n");
++
++  l2 = gcry_sexp_find_token (l1, "dsa", 0);
++  if (!l2)
++    die ("returned private key not formed as expected\n");
++  gcry_sexp_release (l1);
++  l1 = l2;
++
++  /* Extract the parameters from the S-expression and print them to stdout.  */
++  for (idx=0; "xy"[idx]; idx++) 
++    {
++      l2 = gcry_sexp_find_token (l1, "xy"+idx, 1);
++      if (!l2)
++        die ("no %c parameter in returned public key\n", "xy"[idx]);
++      mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
++      if (!mpi)
++        die ("no value for %c parameter in returned private key\n","xy"[idx]);
++      gcry_sexp_release (l2);
++      if (standalone_mode)
++        printf ("%c = ", "XY"[idx]);
++      print_mpi_line (mpi, 1);
++      gcry_mpi_release (mpi);
++    }
++
++  gcry_sexp_release (l1);
++}
++
++
++/* Generate DSA pq domain parameters for a modulus size of KEYSIZE.  The
+    result is printed to stdout with one parameter per line in hex
+-   format and in this order: p, q, g, seed, counter, h.  If SEED is
++   format and in this order: p, q, seed, counter.  If SEED is
+    not NULL this seed value will be used for the generation.  */
+ static void
+-run_dsa_pqg_gen (int keysize, const void *seed, size_t seedlen)
++run_dsa_pqg_gen (int keysize, int qsize, const void *seed, size_t seedlen)
+ {
+   gcry_sexp_t key;
+ 
+   if (seed)
+-    key = dsa_gen_with_seed (keysize, seed, seedlen);
++    key = dsa_gen_with_seed (keysize, qsize, seed, seedlen);
+   else
+-    key = dsa_gen (keysize);
+-  print_dsa_domain_parameters (key);
++    key = dsa_gen (keysize, qsize);
++  print_dsa_domain_parameters (key, 1);
++  gcry_sexp_release (key);
++}
++
++
++/* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
++   result is printed to stdout with one parameter per line in hex
++   format and in this order: p, q, g, seed, counter, h.  If SEED is
++   not NULL this seed value will be used for the generation.  */
++static void
++run_dsa_g_gen (int keysize, int qsize, const char *domain)
++{
++  gcry_sexp_t key;
++
++  key = dsa_gen_key (domain);
++  print_dsa_domain_parameters (key, 0);
++  gcry_sexp_release (key);
++}
++
++/* Generate a DSA key with specified domain parameters
++   and print the XY values. */
++static void
++run_dsa_gen_key (const char *domain)
++{
++  gcry_sexp_t key;
++
++  key = dsa_gen_key (domain);
++  print_dsa_xy (key);
++
+   gcry_sexp_release (key);
+ }
+ 
+ 
+ /* Generate a DSA key of size of KEYSIZE and write the private key to
+    FILENAME.  Also write the parameters to stdout in the same way as
+-   run_dsa_pqg_gen.  */
++   run_dsa_g_gen.  */
+ static void
+-run_dsa_gen (int keysize, const char *filename)
++run_dsa_gen (int keysize, int qsize, const char *filename)
+ {
+   gcry_sexp_t key, private_key;
+   FILE *fp;
+ 
+-  key = dsa_gen (keysize);
++  key = dsa_gen (keysize, qsize);
+   private_key = gcry_sexp_find_token (key, "private-key", 0);
+   if (!private_key)
+     die ("private key not found in genkey result\n");
+-  print_dsa_domain_parameters (key);
++  print_dsa_domain_parameters (key, 1);
+ 
+   fp = fopen (filename, "wb");
+   if (!fp)
+@@ -1863,6 +1969,53 @@ run_dsa_gen (int keysize, const char *fi
+ }
+ 
+ 
++static int
++dsa_hash_from_key(gcry_sexp_t s_key)
++{
++  gcry_sexp_t l1, l2;
++  gcry_mpi_t q;
++  unsigned int qbits;
++
++  l1 = gcry_sexp_find_token (s_key, "public-key", 0);
++  if (!l1)
++    {
++      l1 = gcry_sexp_find_token (s_key, "private-key", 0);
++      if (!l1)
++        die ("neither private nor public key found in the loaded key\n");
++    }
++
++  l2 = gcry_sexp_find_token (l1, "dsa", 0);
++  if (!l2)
++    die ("public key not formed as expected - no dsa\n");
++  gcry_sexp_release (l1);
++  l1 = l2;
++
++  l2 = gcry_sexp_find_token (l1, "q", 0);
++  if (!l2)
++    die ("public key not formed as expected - no q\n");
++  gcry_sexp_release (l1);
++  l1 = l2;
++
++  q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
++  if (!q)
++    die ("public key not formed as expected - no mpi in q\n");
++  qbits = gcry_mpi_get_nbits(q);
++  gcry_sexp_release(l1);
++  gcry_mpi_release(q);
++  switch(qbits)
++    {
++    case 160:
++	return GCRY_MD_SHA1;
++    case 224:
++	return GCRY_MD_SHA224;
++    case 256:
++        return GCRY_MD_SHA256;
++    default:
++        die("bad number bits (%d) of q in key\n", qbits);
++    }
++  return GCRY_MD_NONE;
++}
++
+ 
+ /* Sign DATA of length DATALEN using the key taken from the S-expression
+    encoded KEYFILE. */
+@@ -1872,11 +2025,16 @@ run_dsa_sign (const void *data, size_t d
+ {
+   gpg_error_t err;
+   gcry_sexp_t s_data, s_key, s_sig, s_tmp, s_tmp2;
+-  char hash[20];
++  char hash[128];
+   gcry_mpi_t tmpmpi;
++  int algo;
++
++  s_key = read_sexp_from_file (keyfile);
++  algo = dsa_hash_from_key(s_key);
+ 
+-  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
+-  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
++  gcry_md_hash_buffer (algo, hash, data, datalen);
++  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
++                       gcry_md_get_algo_dlen(algo), NULL);
+   if (!err)
+     {
+       err = gcry_sexp_build (&s_data, NULL,
+@@ -1887,8 +2045,6 @@ run_dsa_sign (const void *data, size_t d
+     die ("gcry_sexp_build failed for DSA data input: %s\n",
+          gpg_strerror (err));
+ 
+-  s_key = read_sexp_from_file (keyfile);
+-
+   err = gcry_pk_sign (&s_sig, s_data, s_key);
+   if (err)
+     {
+@@ -1964,13 +2120,18 @@ run_dsa_verify (const void *data, size_t
+ {
+   gpg_error_t err;
+   gcry_sexp_t s_data, s_key, s_sig;
+-  char hash[20];
++  char hash[128];
+   gcry_mpi_t tmpmpi;
++  int algo;
++
++  s_key = read_sexp_from_file (keyfile);
++  algo = dsa_hash_from_key(s_key);
+ 
+-  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
++  gcry_md_hash_buffer (algo, hash, data, datalen);
+   /* Note that we can't simply use %b with HASH to build the
+      S-expression, because that might yield a negative value.  */
+-  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
++  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
++                       gcry_md_get_algo_dlen(algo), NULL);
+   if (!err)
+     {
+       err = gcry_sexp_build (&s_data, NULL,
+@@ -1981,7 +2142,6 @@ run_dsa_verify (const void *data, size_t
+     die ("gcry_sexp_build failed for DSA data input: %s\n",
+          gpg_strerror (err));
+ 
+-  s_key = read_sexp_from_file (keyfile);
+   s_sig = read_sexp_from_file (sigfile);
+ 
+   err = gcry_pk_verify (s_sig, s_data, s_key);
+@@ -2014,7 +2174,7 @@ usage (int show_help)
+      "Run a crypto operation using hex encoded input and output.\n"
+      "MODE:\n"
+      "  encrypt, decrypt, digest, random, hmac-sha,\n"
+-     "  rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n"
++     "  rsa-{derive,gen,sign,verify}, dsa-{pq-gen,g-gen,gen,sign,verify}\n"
+      "OPTIONS:\n"
+      "  --verbose        Print additional information\n"
+      "  --binary         Input and output is in binary form\n"
+@@ -2024,6 +2184,7 @@ usage (int show_help)
+      "  --dt DT          Use the hex encoded DT for the RNG\n"
+      "  --algo NAME      Use algorithm NAME\n"
+      "  --keysize N      Use a keysize of N bits\n"
++     "  --qize N         Use a DSA q parameter size of N bits\n"
+      "  --signature NAME Take signature from file NAME\n"
+      "  --chunk N        Read in chunks of N bytes (implies --binary)\n"
+      "  --pkcs1          Use PKCS#1 encoding\n"
+@@ -2050,6 +2211,7 @@ main (int argc, char **argv)
+   const char *dt_string = NULL;
+   const char *algo_string = NULL;
+   const char *keysize_string = NULL;
++  const char *qsize_string = NULL;
+   const char *signature_string = NULL;
+   FILE *input;
+   void *data;
+@@ -2143,6 +2305,14 @@ main (int argc, char **argv)
+           keysize_string = *argv;
+           argc--; argv++;
+         }
++      else if (!strcmp (*argv, "--qsize"))
++        {
++          argc--; argv++;
++          if (!argc)
++            usage (0);
++          qsize_string = *argv;
++          argc--; argv++;
++        }
+       else if (!strcmp (*argv, "--signature"))
+         {
+           argc--; argv++;
+@@ -2463,23 +2633,49 @@ main (int argc, char **argv)
+     }
+   else if (!strcmp (mode_string, "dsa-pqg-gen"))
+     {
+-      int keysize;
++      int keysize, qsize;
+       
+       keysize = keysize_string? atoi (keysize_string) : 0;
+       if (keysize < 1024 || keysize > 3072)
+         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
+-      run_dsa_pqg_gen (keysize, datalen? data:NULL, datalen);
++      qsize = qsize_string? atoi (qsize_string) : 0;
++      if (qsize < 160 || qsize > 256)
++        die ("invalid qsize specified; needs to be 160 .. 256\n");
++      run_dsa_pqg_gen (keysize, qsize, datalen? data:NULL, datalen);
++    }
++  else if (!strcmp (mode_string, "dsa-g-gen"))
++    {
++      int keysize, qsize;
++      
++      keysize = keysize_string? atoi (keysize_string) : 0;
++      if (keysize < 1024 || keysize > 3072)
++        die ("invalid keysize specified; needs to be 1024 .. 3072\n");
++      qsize = qsize_string? atoi (qsize_string) : 0;
++      if (qsize < 160 || qsize > 256)
++        die ("invalid qsize specified; needs to be 160 .. 256\n");
++      if (!key_string)
++        die ("option --key containing pq domain parameters is required in this mode\n");
++      run_dsa_g_gen (keysize, qsize, key_string);
++    }
++  else if (!strcmp (mode_string, "dsa-gen-key"))
++    {
++      if (!key_string)
++        die ("option --key containing pqg domain parameters is required in this mode\n");
++      run_dsa_gen_key (key_string);
+     }
+   else if (!strcmp (mode_string, "dsa-gen"))
+     {
+-      int keysize;
++      int keysize, qsize;
+       
+       keysize = keysize_string? atoi (keysize_string) : 0;
+       if (keysize < 1024 || keysize > 3072)
+         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
++      qsize = qsize_string? atoi (qsize_string) : 0;
++      if (qsize < 160 || qsize > 256)
++        die ("invalid qsize specified; needs to be 160 .. 256\n");
+       if (!key_string)
+         die ("option --key is required in this mode\n");
+-      run_dsa_gen (keysize, key_string);
++      run_dsa_gen (keysize, qsize, key_string);
+     }
+   else if (!strcmp (mode_string, "dsa-sign"))
+     {
diff --git a/libgcrypt.spec b/libgcrypt.spec
index 8a4cd73..59ef62a 100644
--- a/libgcrypt.spec
+++ b/libgcrypt.spec
@@ -1,6 +1,6 @@
 Name: libgcrypt
 Version: 1.4.6
-Release: 1%{?dist}
+Release: 2%{?dist}
 URL: http://www.gnupg.org/
 Source0: libgcrypt-%{version}-hobbled.tar.bz2
 # The original libgcrypt sources now contain potentially patented ECC
@@ -18,6 +18,8 @@ Patch3: libgcrypt-1.4.5-ImplicitDSOLinking.patch
 Patch4: libgcrypt-1.4.5-urandom.patch
 # fix tests in the FIPS mode, fix the FIPS-186-3 DSA keygen
 Patch5: libgcrypt-1.4.5-tests.patch
+# make the FIPS-186-3 DSA CAVS testable
+Patch6: libgcrypt-1.4.6-cavs.patch
 
 # Technically LGPLv2.1+, but Fedora's table doesn't draw a distinction.
 # Documentation and some utilities are GPLv2+ licensed. These files
@@ -165,6 +167,9 @@ exit 0
 %doc COPYING
 
 %changelog
+* Mon May 30 2011 Tomas Mraz <tmraz at redhat.com> 1.4.6-2
+- Make the FIPS-186-3 DSA implementation CAVS testable
+
 * Fri Feb 11 2011 Tomas Mraz <tmraz at redhat.com> 1.4.6-1
 - new upstream version with minor changes
 


More information about the scm-commits mailing list