From c25b02784b31eeff42a43faad63bf559e4db1d0e6824a392f0f16af9ab0df7c3 Mon Sep 17 00:00:00 2001 From: Sascha Peilicke Date: Mon, 31 Mar 2014 07:35:35 +0000 Subject: [PATCH 1/4] Accepting request 227791 from home:msmeissn:branches:devel:libraries:c_c++ - FIPS changes (from Fedora): - replaced libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff by libgcrypt-1.6.1-fips-cfgrandom.patch - libgcrypt-fixed-sizet.patch: fixed an int type for -flto - libgcrypt-1.6.1-use-fipscheck.patch: use the fipscheck binary - libgcrypt-1.6.1-fips-cavs.patch: add CAVS tests OBS-URL: https://build.opensuse.org/request/show/227791 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=46 --- ...rypt-1.5.0-etc_gcrypt_rngseed-symlink.diff | 185 --- libgcrypt-1.6.1-fips-cavs.patch | 1123 +++++++++++++++++ libgcrypt-1.6.1-fips-cfgrandom.patch | 134 ++ libgcrypt-1.6.1-use-fipscheck.patch | 89 ++ libgcrypt-fips-allow-legacy.patch | 216 ++++ libgcrypt-fixed-sizet.patch | 13 + libgcrypt.changes | 10 + libgcrypt.spec | 27 +- 8 files changed, 1603 insertions(+), 194 deletions(-) delete mode 100644 libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff create mode 100644 libgcrypt-1.6.1-fips-cavs.patch create mode 100644 libgcrypt-1.6.1-fips-cfgrandom.patch create mode 100644 libgcrypt-1.6.1-use-fipscheck.patch create mode 100644 libgcrypt-fips-allow-legacy.patch create mode 100644 libgcrypt-fixed-sizet.patch diff --git a/libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff b/libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff deleted file mode 100644 index 6e1a05e..0000000 --- a/libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff +++ /dev/null @@ -1,185 +0,0 @@ -From: draht@suse.com -Subject: /etc/gcrypt/rngseed symlink - -logic error in evaluation of routine to open /dev/{u,}random or -/etc/gcrypt/rngseed (open_device()) causes abort() in cases where -do_randomize(nbytes, level) is called with level == 1 -(GCRY_STRONG_RANDOM). - -References: bnc#724841 -https://bugzilla.novell.com/show_bug.cgi?id=724841 - ---- - random/random-csprng.c | 2 - - random/random-fips.c | 10 ++++---- - random/rndlinux.c | 58 ++++++++++++++++++++++++++++++++++++++++--------- - 3 files changed, 54 insertions(+), 16 deletions(-) - -Index: libgcrypt-1.6.0/random/random-csprng.c -=================================================================== ---- libgcrypt-1.6.0.orig/random/random-csprng.c -+++ libgcrypt-1.6.0/random/random-csprng.c -@@ -832,7 +832,7 @@ read_seed_file (void) - * entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read too much as we - * want to be friendly to the scare system entropy resource. */ -- read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM ); -+ read_random_source ( RANDOM_ORIGIN_INIT, 16, -1 ); - - allow_seed_file_update = 1; - return 1; -Index: libgcrypt-1.6.0/random/random-fips.c -=================================================================== ---- libgcrypt-1.6.0.orig/random/random-fips.c -+++ libgcrypt-1.6.0/random/random-fips.c -@@ -27,10 +27,10 @@ - There are 3 random context which map to the different levels of - random quality: - -- Generator Seed and Key Kernel entropy (init/reseed) -- ------------------------------------------------------------ -- GCRY_VERY_STRONG_RANDOM /dev/random 256/128 bits -- GCRY_STRONG_RANDOM /dev/random 256/128 bits -+ Generator Seed and Key Kernel entropy (init/reseed) -+ --------------------------------------------------------------------------------------- -+ GCRY_VERY_STRONG_RANDOM /etc/gcrypt/rngseed+/dev/urandom 256/128 bits -+ GCRY_STRONG_RANDOM /etc/gcrypt/rngseed+/dev/urandom 256/128 bits - gcry_create_nonce GCRY_STRONG_RANDOM n/a - - All random generators return their data in 128 bit blocks. If the -@@ -562,7 +562,7 @@ get_entropy (size_t nbytes) - #if USE_RNDLINUX - rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0, - X931_AES_KEYLEN, -- GCRY_VERY_STRONG_RANDOM); -+ -1); - #elif USE_RNDW32 - do - { -Index: libgcrypt-1.6.0/random/rndlinux.c -=================================================================== ---- libgcrypt-1.6.0.orig/random/rndlinux.c -+++ libgcrypt-1.6.0/random/rndlinux.c -@@ -36,7 +36,8 @@ - #include "g10lib.h" - #include "rand-internal.h" - --static int open_device (const char *name, int retry); -+static int open_device (const char *name, int retry, int fatal); -+#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed" - - - static int -@@ -59,7 +60,7 @@ set_cloexec_flag (int fd) - * a fatal error but retries until it is able to reopen the device. - */ - static int --open_device (const char *name, int retry) -+open_device (const char *name, int retry, int fatal) - { - int fd; - -@@ -67,8 +68,9 @@ open_device (const char *name, int retry - _gcry_random_progress ("open_dev_random", 'X', 1, 0); - again: - fd = open (name, O_RDONLY); -- if (fd == -1 && retry) -- { -+ if (fd == -1) { -+ if (retry) -+ { - struct timeval tv; - - tv.tv_sec = 5; -@@ -76,9 +78,14 @@ open_device (const char *name, int retry - _gcry_random_progress ("wait_dev_random", 'X', 0, (int)tv.tv_sec); - select (0, NULL, NULL, NULL, &tv); - goto again; -- } -- if (fd == -1) -- log_fatal ("can't open %s: %s\n", name, strerror(errno) ); -+ } -+ else -+ { -+ if (fatal) -+ log_fatal ("can't open %s: %s\n", name, strerror(errno) ); -+ return fd; -+ } -+ } - - if (set_cloexec_flag (fd)) - log_error ("error setting FD_CLOEXEC on fd %d: %s\n", -@@ -111,11 +118,13 @@ _gcry_rndlinux_gather_random (void (*add - { - static int fd_urandom = -1; - static int fd_random = -1; -+ static int fd_configured = -1; - static unsigned char ever_opened; - int fd; - int n; - byte buffer[768]; - size_t n_hw; -+ size_t orig_length = length; - size_t want = length; - size_t last_so_far = 0; - int any_need_entropy = 0; -@@ -153,20 +162,46 @@ _gcry_rndlinux_gather_random (void (*add - that we always require the device to be existent but want a more - graceful behaviour if the rarely needed close operation has been - used and the device needs to be re-opened later. */ -+ -+ /* Clarification: path how "level == -1" comes about: -+ gcry_random_bytes( ... , GCRY_STRONG_RANDOM) (public) -> -+ do_randomize(buffer, nbytes, level) -> -+ _gcry_rngcsprng_randomize(buffer, length, level) -> -+ read_pool (p, n, level) -> -+ read_seed_file(), -+ random_poll() -> -+ read_random_source(..., ..., GCRY_STRONG_RANDOM), -+ read_random_source(... , ..., , -1 ) (note: -1) -> -+ slow_gather_fnc(..., ..., ..., level) -+ function pointer set by getfnc_gather_random() to -+ _gcry_rndlinux_gather_random() , which is here. -+ */ -+ -+ -+ if (level == -1) -+ { -+ if (fd_configured == -1) -+ fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0, 0); -+ fd = fd_configured; -+ if (fd == -1) -+ level = 1; -+ } -+ -+ - if (level >= 2) - { - if (fd_random == -1) - { -- fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1)); -+ fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1), 1); - ever_opened |= 1; - } - fd = fd_random; - } -- else -+ else if (level != -1) - { - if (fd_urandom == -1) - { -- fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2)); -+ fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2), 1); - ever_opened |= 2; - } - fd = fd_urandom; -@@ -242,6 +277,9 @@ _gcry_rndlinux_gather_random (void (*add - } - memset(buffer, 0, sizeof(buffer) ); - -+ if (level == -1) -+ _gcry_rndlinux_gather_random(add, origin, orig_length, 1); -+ - if (any_need_entropy) - _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want); - diff --git a/libgcrypt-1.6.1-fips-cavs.patch b/libgcrypt-1.6.1-fips-cavs.patch new file mode 100644 index 0000000..b3d0cd9 --- /dev/null +++ b/libgcrypt-1.6.1-fips-cavs.patch @@ -0,0 +1,1123 @@ +diff -up libgcrypt-1.6.1/tests/cavs_driver.pl.cavs libgcrypt-1.6.1/tests/cavs_driver.pl +--- libgcrypt-1.6.1/tests/cavs_driver.pl.cavs 2013-03-15 20:25:38.000000000 +0100 ++++ libgcrypt-1.6.1/tests/cavs_driver.pl 2014-02-28 14:46:16.436544639 +0100 +@@ -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 ++# Werner Koch (libgcrypt interface) ++# Tomas Mraz (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); ++} ++ ++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 dsa-pqg-gen"; ++ 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,166 @@ 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; ++} ++ ++sub hexcomp($$) { ++ my $a = lc shift; ++ my $b = lc shift; ++ ++ if (length $a < length $b) { ++ my $c = $a; ++ $a = $b; ++ $b = $a; ++ } ++ ++ while (length $b < length $a) { ++ $b = "00$b"; ++ } ++ ++ return $a eq $b; ++} ++ ++# 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 (hexcomp($P, $p) && hexcomp($Q, $q) && hexcomp($seed, $seed2) && $c == $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 (hexcomp($P, $p) && hexcomp($Q, $q) && hexcomp($G, $g) && hexcomp($seed, $seed2) && ++ $c == $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 +1901,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 +1947,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 +1996,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 +2015,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 +2047,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 +2130,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 +2213,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 +2251,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 +2370,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 +2436,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 +2562,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.6.1/tests/cavs_tests.sh.cavs libgcrypt-1.6.1/tests/cavs_tests.sh +--- libgcrypt-1.6.1/tests/cavs_tests.sh.cavs 2013-03-15 20:25:38.000000000 +0100 ++++ libgcrypt-1.6.1/tests/cavs_tests.sh 2014-02-28 14:46:16.437544662 +0100 +@@ -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.6.1/tests/fipsdrv.c.cavs libgcrypt-1.6.1/tests/fipsdrv.c +--- libgcrypt-1.6.1/tests/fipsdrv.c.cavs 2013-12-16 18:44:32.000000000 +0100 ++++ libgcrypt-1.6.1/tests/fipsdrv.c 2014-02-28 14:46:16.437544662 +0100 +@@ -893,6 +893,9 @@ 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; + +@@ -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)); +@@ -1720,6 +1724,37 @@ dsa_gen_with_seed (int keysize, const vo + 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; ++} ++ ++/* 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); + +@@ -1732,7 +1767,7 @@ dsa_gen_with_seed (int keysize, const vo + 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-1.6.1-fips-cfgrandom.patch b/libgcrypt-1.6.1-fips-cfgrandom.patch new file mode 100644 index 0000000..e96c0ae --- /dev/null +++ b/libgcrypt-1.6.1-fips-cfgrandom.patch @@ -0,0 +1,134 @@ +Index: libgcrypt-1.6.1/random/random-fips.c +=================================================================== +--- libgcrypt-1.6.1.orig/random/random-fips.c ++++ libgcrypt-1.6.1/random/random-fips.c +@@ -27,10 +27,10 @@ + There are 3 random context which map to the different levels of + random quality: + +- Generator Seed and Key Kernel entropy (init/reseed) +- ------------------------------------------------------------ +- GCRY_VERY_STRONG_RANDOM /dev/random 256/128 bits +- GCRY_STRONG_RANDOM /dev/random 256/128 bits ++ Generator Seed and Key Kernel entropy (init/reseed) ++ --------------------------------------------------------------------------------------- ++ GCRY_VERY_STRONG_RANDOM /etc/gcrypt/rngseed+/dev/urandom 256/128 bits ++ GCRY_STRONG_RANDOM /etc/gcrypt/rngseed+/dev/urandom 256/128 bits + gcry_create_nonce GCRY_STRONG_RANDOM n/a + + All random generators return their data in 128 bit blocks. If the +@@ -40,8 +40,10 @@ + (SEED_TTL) output blocks; the re-seeding is disabled in test mode. + + The GCRY_VERY_STRONG_RANDOM and GCRY_STRONG_RANDOM generators are +- keyed and seeded from the /dev/random device. Thus these +- generators may block until the kernel has collected enough entropy. ++ keyed and seeded with data that is loaded from the /etc/gcrypt/rngseed ++ if the device or symlink to device exists xored with the data ++ from the /dev/urandom device. This allows the system administrator ++ to always seed the RNGs from /dev/random if it is required. + + The gcry_create_nonce generator is keyed and seeded from the + GCRY_STRONG_RANDOM generator. It may also block if the +@@ -560,9 +562,13 @@ get_entropy (size_t nbytes) + entropy_collect_buffer_len = 0; + + #if USE_RNDLINUX ++ _gcry_rndlinux_gather_random (entropy_collect_cb, 0, ++ X931_AES_KEYLEN, ++ -1); ++ entropy_collect_buffer_len = 0; + rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0, + X931_AES_KEYLEN, +- GCRY_VERY_STRONG_RANDOM); ++ GCRY_STRONG_RANDOM); + #elif USE_RNDW32 + do + { +Index: libgcrypt-1.6.1/random/rndlinux.c +=================================================================== +--- libgcrypt-1.6.1.orig/random/rndlinux.c ++++ libgcrypt-1.6.1/random/rndlinux.c +@@ -36,7 +36,9 @@ + #include "g10lib.h" + #include "rand-internal.h" + +-static int open_device (const char *name, int retry); ++#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed" ++ ++static int open_device (const char *name, int retry, int fatal); + + + static int +@@ -59,7 +61,7 @@ set_cloexec_flag (int fd) + * a fatal error but retries until it is able to reopen the device. + */ + static int +-open_device (const char *name, int retry) ++open_device (const char *name, int retry, int fatal) + { + int fd; + +@@ -67,6 +69,8 @@ open_device (const char *name, int retry + _gcry_random_progress ("open_dev_random", 'X', 1, 0); + again: + fd = open (name, O_RDONLY); ++ if (fd == -1 && !fatal) ++ return fd; + if (fd == -1 && retry) + { + struct timeval tv; +@@ -111,6 +115,7 @@ _gcry_rndlinux_gather_random (void (*add + { + static int fd_urandom = -1; + static int fd_random = -1; ++ static int fd_configured = -1; + static unsigned char ever_opened; + int fd; + int n; +@@ -134,6 +139,11 @@ _gcry_rndlinux_gather_random (void (*add + close (fd_urandom); + fd_urandom = -1; + } ++ if (fd_configured != -1) ++ { ++ close (fd_configured); ++ fd_configured = -1; ++ } + return 0; + } + +@@ -153,20 +163,30 @@ _gcry_rndlinux_gather_random (void (*add + that we always require the device to be existent but want a more + graceful behaviour if the rarely needed close operation has been + used and the device needs to be re-opened later. */ ++ ++ if (level == -1) ++ { ++ if (fd_configured == -1) ++ fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0, 0 ); ++ fd = fd_configured; ++ if (fd == -1) ++ return -1; ++ } ++ + if (level >= 2) + { + if (fd_random == -1) + { +- fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1)); ++ fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1), 1); + ever_opened |= 1; + } + fd = fd_random; + } +- else ++ else if (level != -1) + { + if (fd_urandom == -1) + { +- fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2)); ++ fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2), 1); + ever_opened |= 2; + } + fd = fd_urandom; diff --git a/libgcrypt-1.6.1-use-fipscheck.patch b/libgcrypt-1.6.1-use-fipscheck.patch new file mode 100644 index 0000000..bdf924c --- /dev/null +++ b/libgcrypt-1.6.1-use-fipscheck.patch @@ -0,0 +1,89 @@ +Index: libgcrypt-1.6.1/src/fips.c +=================================================================== +--- libgcrypt-1.6.1.orig/src/fips.c ++++ libgcrypt-1.6.1/src/fips.c +@@ -589,23 +589,48 @@ run_random_selftests (void) + return !!err; + } + ++static int ++get_library_path(const char *libname, const char *symbolname, char *path, size_t pathlen) ++{ ++ Dl_info info; ++ void *dl, *sym; ++ int rv = -1; ++ ++ dl = dlopen(libname, RTLD_LAZY); ++ if (dl == NULL) { ++ return -1; ++ } ++ ++ sym = dlsym(dl, symbolname); ++ ++ if (sym != NULL && dladdr(sym, &info)) { ++ strncpy(path, info.dli_fname, pathlen-1); ++ path[pathlen-1] = '\0'; ++ rv = 0; ++ } ++ ++ dlclose(dl); ++ ++ return rv; ++} ++ + /* Run an integrity check on the binary. Returns 0 on success. */ + static int + check_binary_integrity (void) + { + #ifdef ENABLE_HMAC_BINARY_CHECK + gpg_error_t err; +- Dl_info info; ++ char libpath[4096]; + unsigned char digest[32]; + int dlen; + char *fname = NULL; +- const char key[] = "What am I, a doctor or a moonshuttle conductor?"; +- +- if (!dladdr ("gcry_check_version", &info)) ++ const char key[] = "orboDeJITITejsirpADONivirpUkvarP"; ++ ++ if (get_library_path ("libgcrypt.so.11", "gcry_check_version", libpath, sizeof(libpath))) + err = gpg_error_from_syserror (); + else + { +- dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname, ++ dlen = _gcry_hmac256_file (digest, sizeof digest, libpath, + key, strlen (key)); + if (dlen < 0) + err = gpg_error_from_syserror (); +@@ -613,7 +638,7 @@ check_binary_integrity (void) + err = gpg_error (GPG_ERR_INTERNAL); + else + { +- fname = _gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 ); ++ fname = _gcry_malloc (strlen (libpath) + 1 + 5 + 1 ); + if (!fname) + err = gpg_error_from_syserror (); + else +@@ -622,7 +647,7 @@ check_binary_integrity (void) + char *p; + + /* Prefix the basename with a dot. */ +- strcpy (fname, info.dli_fname); ++ strcpy (fname, libpath); + p = strrchr (fname, '/'); + if (p) + p++; +Index: libgcrypt-1.6.1/src/Makefile.in +=================================================================== +--- libgcrypt-1.6.1.orig/src/Makefile.in ++++ libgcrypt-1.6.1/src/Makefile.in +@@ -449,7 +449,7 @@ libgcrypt_la_LIBADD = $(gcrypt_res) \ + ../cipher/libcipher.la \ + ../random/librandom.la \ + ../mpi/libmpi.la \ +- ../compat/libcompat.la $(GPG_ERROR_LIBS) ++ ../compat/libcompat.la $(GPG_ERROR_LIBS) -ldl + + dumpsexp_SOURCES = dumpsexp.c + dumpsexp_CFLAGS = $(arch_gpg_error_cflags) diff --git a/libgcrypt-fips-allow-legacy.patch b/libgcrypt-fips-allow-legacy.patch new file mode 100644 index 0000000..5674710 --- /dev/null +++ b/libgcrypt-fips-allow-legacy.patch @@ -0,0 +1,216 @@ +diff -urNp libgcrypt-1.5.3.orig/cipher/cipher.c libgcrypt-1.5.3/cipher/cipher.c +--- libgcrypt-1.5.3.orig/cipher/cipher.c 2013-08-14 02:41:07.967316255 +0200 ++++ libgcrypt-1.5.3/cipher/cipher.c 2013-08-14 03:11:19.403611811 +0200 +@@ -293,6 +293,15 @@ dummy_decrypt_stream (void *c, + BUG(); + } + ++/* Re-Register default cipher listing */ ++void ++cipher_reregister_default(void) ++{ ++ ath_mutex_lock (&ciphers_registered_lock); ++ default_ciphers_registered = 0; ++ ath_mutex_unlock (&ciphers_registered_lock); ++} ++ + + /* Internal function. Register all the ciphers included in + CIPHER_TABLE. Note, that this function gets only used by the macro +@@ -316,7 +325,8 @@ cipher_register_default (void) + if (! cipher_table[i].cipher->stdecrypt) + cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream; + +- if ( fips_mode () && !cipher_table[i].fips_allowed ) ++ if ( !_gcry_is_fips_mode_inactive() && ++ fips_mode () && !cipher_table[i].fips_allowed ) + continue; + + err = _gcry_module_add (&ciphers_registered, +diff -urNp libgcrypt-1.5.3.orig/cipher/md.c libgcrypt-1.5.3/cipher/md.c +--- libgcrypt-1.5.3.orig/cipher/md.c 2013-08-14 02:41:07.968316245 +0200 ++++ libgcrypt-1.5.3/cipher/md.c 2013-08-14 03:20:04.269937326 +0200 +@@ -168,7 +168,14 @@ static void md_start_debug ( gcry_md_hd_ + static void md_stop_debug ( gcry_md_hd_t a ); + + +- ++/* Re-Register default digest listing */ ++void ++digest_reregister_default(void) ++{ ++ ath_mutex_lock (&digests_registered_lock); ++ default_digests_registered = 0; ++ ath_mutex_unlock (&digests_registered_lock); ++} + + /* Internal function. Register all the ciphers included in + CIPHER_TABLE. Returns zero on success or an error code. */ +@@ -180,7 +187,8 @@ md_register_default (void) + + for (i = 0; !err && digest_table[i].digest; i++) + { +- if ( fips_mode ()) ++ if ( !_gcry_is_fips_mode_inactive() && ++ fips_mode ()) + { + if (!digest_table[i].fips_allowed) + continue; +diff -urNp libgcrypt-1.5.3.orig/cipher/pubkey.c libgcrypt-1.5.3/cipher/pubkey.c +--- libgcrypt-1.5.3.orig/cipher/pubkey.c 2013-08-14 02:41:07.969316234 +0200 ++++ libgcrypt-1.5.3/cipher/pubkey.c 2013-08-14 03:22:07.227878253 +0200 +@@ -192,6 +192,15 @@ dummy_get_nbits (int algorithm, gcry_mpi + return 0; + } + ++/* Re-Register default digest listing */ ++void ++pk_reregister_default(void) ++{ ++ ath_mutex_lock (&pubkeys_registered_lock); ++ default_pubkeys_registered = 0; ++ ath_mutex_unlock (&pubkeys_registered_lock); ++} ++ + /* Internal function. Register all the pubkeys included in + PUBKEY_TABLE. Returns zero on success or an error code. */ + static void +@@ -202,6 +211,10 @@ pk_register_default (void) + + for (i = 0; (! err) && pubkey_table[i].pubkey; i++) + { ++ if ( !_gcry_is_fips_mode_inactive() && ++ fips_mode () && !pubkey_table[i].fips_allowed ) ++ continue; ++ + #define pubkey_use_dummy(func) \ + if (! pubkey_table[i].pubkey->func) \ + pubkey_table[i].pubkey->func = dummy_##func; +diff -urNp libgcrypt-1.5.3.orig/doc/gcrypt.texi libgcrypt-1.5.3/doc/gcrypt.texi +--- libgcrypt-1.5.3.orig/doc/gcrypt.texi 2013-08-14 02:41:07.908316872 +0200 ++++ libgcrypt-1.5.3/doc/gcrypt.texi 2013-08-14 03:43:51.808257657 +0200 +@@ -844,6 +844,25 @@ This option may be used to disabale a ce + behaves as if this feature has not been detected. Note that the + detection code might be run if the feature has been disabled. This + command must be used at initialization time; i.e. before calling ++ ++@item GCRYCTL_INACTIVATE_FIPS_FLAG; Arguments: const char *log ++Suspend FIPS mode which implies that all ciphers are again allowed to be used. ++Still, all operations around the FIPS 140-2 mode, such as the finite ++state model enforcement are still enforced. The idea of this mode ++is to allow the caller to implement legacy operations, such as ++decryption or signature verification of data that is already present ++using non-approved ciphers. After the legacy operation is completed, ++GCRYCTL_REACTIVATE_FIPS_FLAG should be invoked to limit the ciphers ++again. The argument allows the caller to provide a string that is logged. ++ ++@item GCRYCTL_REACTIVATE_FIPS_FLAG; Arguments: const char *log ++Re-activate FIPS mode by limiting the allowed cipher listing to the ++approved ciphers. This call should be called immediately after the ++legacy operations that are made possible with ++@code{GCRYCTL_INACTIVATE_FIPS_FLAG} are completed. FIPS 140-2 self ++tests are invoked. The argument allows the caller to provide a ++string that is logged. ++ + @code{gcry_check_version}. + + @end table +Binärdateien libgcrypt-1.5.3.orig/doc/.gcrypt.texi.swp und libgcrypt-1.5.3/doc/.gcrypt.texi.swp sind verschieden. +diff -urNp libgcrypt-1.5.3.orig/src/fips.c libgcrypt-1.5.3/src/fips.c +--- libgcrypt-1.5.3.orig/src/fips.c 2013-08-14 02:41:07.943316506 +0200 ++++ libgcrypt-1.5.3/src/fips.c 2013-08-14 03:33:47.600705208 +0200 +@@ -307,6 +307,10 @@ _gcry_inactivate_fips_mode (const char * + { + inactive_fips_mode = 1; + unlock_fsm (); ++ /* enforce reloading of cipher list to allow use of all ciphers */ ++ cipher_reregister_default(); ++ digest_reregister_default(); ++ pk_reregister_default(); + #ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s - FIPS mode inactivated", text); +@@ -316,6 +320,33 @@ _gcry_inactivate_fips_mode (const char * + unlock_fsm (); + } + ++void ++_gcry_reactivate_fips_mode (const char *text) ++{ ++ gcry_assert (_gcry_fips_mode ()); ++ ++ lock_fsm (); ++ if (inactive_fips_mode) ++ { ++ inactive_fips_mode = 0; ++ unlock_fsm (); ++ /* execute self test as there have been non-approved ciphers allowed ++ * to execute */ ++ _gcry_fips_run_selftests(0); ++ /* enforce reloading of cipher list to only use FIPS ciphers */ ++ cipher_reregister_default(); ++ digest_reregister_default(); ++ pk_reregister_default(); ++#ifdef HAVE_SYSLOG ++ syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " ++ "%s - FIPS mode activated", text); ++#endif /*HAVE_SYSLOG*/ ++ } ++ else ++ unlock_fsm (); ++ ++} ++ + + /* Return the FIPS mode inactive flag. If it is true the FIPS mode is + not anymore active. */ +diff -urNp libgcrypt-1.5.3.orig/src/g10lib.h libgcrypt-1.5.3/src/g10lib.h +--- libgcrypt-1.5.3.orig/src/g10lib.h 2013-08-14 02:41:07.941316527 +0200 ++++ libgcrypt-1.5.3/src/g10lib.h 2013-08-14 03:25:29.836347533 +0200 +@@ -329,8 +329,11 @@ int _gcry_enforced_fips_mode (void); + void _gcry_set_enforced_fips_mode (void); + + void _gcry_inactivate_fips_mode (const char *text); ++void _gcry_reactivate_fips_mode (const char *text); + int _gcry_is_fips_mode_inactive (void); +- ++void cipher_reregister_default(void); ++void digest_reregister_default(void); ++void pk_reregister_default(void); + + void _gcry_fips_signal_error (const char *srcfile, + int srcline, +diff -urNp libgcrypt-1.5.3.orig/src/gcrypt.h libgcrypt-1.5.3/src/gcrypt.h +--- libgcrypt-1.5.3.orig/src/gcrypt.h.in 2013-08-14 02:41:07.942316516 +0200 ++++ libgcrypt-1.5.3/src/gcrypt.h.in 2013-08-14 02:58:13.304374921 +0200 +@@ -423,7 +423,9 @@ enum gcry_ctl_cmds + GCRYCTL_SELFTEST = 57, + /* Note: 58 .. 62 are used internally. */ + GCRYCTL_DISABLE_HWF = 63, +- GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64 ++ GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64, ++ GCRYCTL_INACTIVATE_FIPS_FLAG = 65, ++ GCRYCTL_REACTIVATE_FIPS_FLAG = 66 + }; + + /* Perform various operations defined by CMD. */ +diff -urNp libgcrypt-1.5.3.orig/src/global.c libgcrypt-1.5.3/src/global.c +--- libgcrypt-1.5.3.orig/src/global.c 2013-08-14 02:41:07.943316506 +0200 ++++ libgcrypt-1.5.3/src/global.c 2013-08-15 23:40:34.233497710 +0200 +@@ -609,6 +609,16 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + err = GPG_ERR_GENERAL; + break; + ++ case GCRYCTL_INACTIVATE_FIPS_FLAG: ++ log_info ("FIPS mode enabled but allow all approved and non-approved ciphers\n"); ++ _gcry_inactivate_fips_mode (va_arg (arg_ptr, const char *)); ++ break; ++ ++ case GCRYCTL_REACTIVATE_FIPS_FLAG: ++ log_info ("FIPS mode enabled and limit ciphers to approved ciphers\n"); ++ _gcry_reactivate_fips_mode (va_arg (arg_ptr, const char *)); ++ break; ++ + default: + err = GPG_ERR_INV_OP; + } diff --git a/libgcrypt-fixed-sizet.patch b/libgcrypt-fixed-sizet.patch new file mode 100644 index 0000000..e20d755 --- /dev/null +++ b/libgcrypt-fixed-sizet.patch @@ -0,0 +1,13 @@ +Index: libgcrypt-1.6.1/random/rndlinux.c +=================================================================== +--- libgcrypt-1.6.1.orig/random/rndlinux.c ++++ libgcrypt-1.6.1/random/rndlinux.c +@@ -261,7 +261,7 @@ _gcry_rndlinux_gather_random (void (*add + + do + { +- int nbytes = length < sizeof(buffer)? length : sizeof(buffer); ++ size_t nbytes = length < sizeof(buffer)? length : sizeof(buffer); + n = read(fd, buffer, nbytes ); + if( n >= 0 && n > nbytes ) + { diff --git a/libgcrypt.changes b/libgcrypt.changes index 2d46582..0aae135 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Thu Mar 27 14:57:22 UTC 2014 - meissner@suse.com + +- FIPS changes (from Fedora): + - replaced libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff by + libgcrypt-1.6.1-fips-cfgrandom.patch + - libgcrypt-fixed-sizet.patch: fixed an int type for -flto + - libgcrypt-1.6.1-use-fipscheck.patch: use the fipscheck binary + - libgcrypt-1.6.1-fips-cavs.patch: add CAVS tests + ------------------------------------------------------------------- Thu Jan 30 13:29:49 UTC 2014 - idonmez@suse.com diff --git a/libgcrypt.spec b/libgcrypt.spec index 0b68a30..1bfc997 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -41,14 +41,22 @@ Patch4: %{name}-sparcv9.diff #PATCH-FIX-UPSTREAM: bnc#701267, explicitly link with $(DL_LIBS) #was: libgcrypt-1.5.0-as-needed.patch Patch5: libgcrypt-unresolved-dladdr.patch -#PATCH-FIX-SUSE: bnc#724841, fix a random device opening routine -Patch6: libgcrypt-1.5.0-etc_gcrypt_rngseed-symlink.diff #PATCH-FIX-SUSE: N/A + Patch7: libgcrypt-1.5.0-LIBGCRYPT_FORCE_FIPS_MODE-env.diff + #PATCH-FIX-UPSTREAM: internal functions are supposed to be used inside libgcrypt, mvyskocil@suse.com Patch8: libgcrypt-1.6.0-use-intenal-functions.patch +Patch10: libgcrypt-fips-allow-legacy.patch +Patch11: libgcrypt-fixed-sizet.patch + +Patch12: libgcrypt-1.6.1-use-fipscheck.patch +Patch13: libgcrypt-1.6.1-fips-cavs.patch +#PATCH-FIX-SUSE: bnc#724841, fix a random device opening routine +Patch14: libgcrypt-1.6.1-fips-cfgrandom.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: automake >= 1.11 +BuildRequires: fipscheck BuildRequires: libgpg-error-devel >= 1.11 BuildRequires: libtool # not for base packages to avoid huge cycles @@ -107,14 +115,17 @@ understanding of applied cryptography is required to use Libgcrypt. %prep %setup -q -n %{name}-%{version} -%patch0 -p1 %patch1 %patch3 -p1 %patch4 -p1 %patch5 -p1 -%patch6 -p1 %patch7 -p1 %patch8 -p1 +#%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 %build echo building with build_hmac256 set to %{build_hmac256} @@ -141,15 +152,13 @@ make %{?_smp_mflags} # this shows up earlier because otherwise the %expand of # the macro is too late. %{expand:%%global __os_install_post {%__os_install_post - -%{buildroot}/%{_bindir}/hmac256 "What am I, a doctor or a moonshuttle conductor?" \ - < %{buildroot}/%{_bindir}/hmac256 > %{buildroot}/%{_bindir}/.hmac256.hmac -%{buildroot}/%{_bindir}/hmac256 "What am I, a doctor or a moonshuttle conductor?" \ - < %{buildroot}/%{_libdir}/libgcrypt.so.%{sosuffix} > %{buildroot}/%{_libdir}/.libgcrypt.so.20.hmac + fipshmac %{buildroot}/%{_bindir}/hmac256 + fipshmac %{buildroot}/%{_libdir}/*.so.?? }} %endif %check +fipshmac src/.libs/libgcrypt.so.?? # Nice idea. however this uses /dev/random, which hangs # on hardware without random feeds. # so lets not run it inside OBS From 07bdae674c0d4572a60d2354a4db8d3b4c5679b3c2b5fb42356c74cc3d24c6f2 Mon Sep 17 00:00:00 2001 From: Stephan Kulow Date: Mon, 31 Mar 2014 18:49:01 +0000 Subject: [PATCH 2/4] Accepting request 228287 from home:msmeissn:branches:devel:libraries:c_c++ - use fipscheck only after 13.1 OBS-URL: https://build.opensuse.org/request/show/228287 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=47 --- libgcrypt.changes | 1 + libgcrypt.spec | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libgcrypt.changes b/libgcrypt.changes index 0aae135..e9000a2 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -7,6 +7,7 @@ Thu Mar 27 14:57:22 UTC 2014 - meissner@suse.com - libgcrypt-fixed-sizet.patch: fixed an int type for -flto - libgcrypt-1.6.1-use-fipscheck.patch: use the fipscheck binary - libgcrypt-1.6.1-fips-cavs.patch: add CAVS tests +- use fipscheck only after 13.1 ------------------------------------------------------------------- Thu Jan 30 13:29:49 UTC 2014 - idonmez@suse.com diff --git a/libgcrypt.spec b/libgcrypt.spec index 1bfc997..b83ae86 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -56,7 +56,9 @@ Patch13: libgcrypt-1.6.1-fips-cavs.patch Patch14: libgcrypt-1.6.1-fips-cfgrandom.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: automake >= 1.11 +%if 0%{?suse_version} > 1310 BuildRequires: fipscheck +%endif BuildRequires: libgpg-error-devel >= 1.11 BuildRequires: libtool # not for base packages to avoid huge cycles @@ -123,7 +125,9 @@ understanding of applied cryptography is required to use Libgcrypt. %patch8 -p1 #%patch10 -p1 %patch11 -p1 +%if 0%{?suse_version} > 1310 %patch12 -p1 +%endif %patch13 -p1 %patch14 -p1 @@ -151,14 +155,26 @@ make %{?_smp_mflags} # # this shows up earlier because otherwise the %expand of # the macro is too late. +%if 0%{?suse_version} > 1310 %{expand:%%global __os_install_post {%__os_install_post fipshmac %{buildroot}/%{_bindir}/hmac256 fipshmac %{buildroot}/%{_libdir}/*.so.?? }} +%else +%{expand:%%global __os_install_post {%__os_install_post + +%{buildroot}/%{_bindir}/hmac256 "What am I, a doctor or a moonshuttle conductor?" \ + < %{buildroot}/%{_bindir}/hmac256 > %{buildroot}/%{_bindir}/.hmac256.hmac +%{buildroot}/%{_bindir}/hmac256 "What am I, a doctor or a moonshuttle conductor?" \ + < %{buildroot}/%{_libdir}/libgcrypt.so.%{sosuffix} > %{buildroot}/%{_libdir}/.libgcrypt.so.20.hmac +}} +%endif %endif %check +%if 0%{?suse_version} > 1310 fipshmac src/.libs/libgcrypt.so.?? +%endif # Nice idea. however this uses /dev/random, which hangs # on hardware without random feeds. # so lets not run it inside OBS From 62320f7e7e5a9803e6c033072c497a99e17452f2e3526fd72dbdef044d321c81 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 2 Apr 2014 12:04:17 +0000 Subject: [PATCH 3/4] - libgcrypt-fips-allow-legacy.patch: attempt to allow some legacy algorithms for gpg2 usage even in FIPS mode. (currently not applied) OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=48 --- libgcrypt.changes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgcrypt.changes b/libgcrypt.changes index e9000a2..7edb063 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -8,6 +8,9 @@ Thu Mar 27 14:57:22 UTC 2014 - meissner@suse.com - libgcrypt-1.6.1-use-fipscheck.patch: use the fipscheck binary - libgcrypt-1.6.1-fips-cavs.patch: add CAVS tests - use fipscheck only after 13.1 +- libgcrypt-fips-allow-legacy.patch: attempt to allow some + legacy algorithms for gpg2 usage even in FIPS mode. + (currently not applied) ------------------------------------------------------------------- Thu Jan 30 13:29:49 UTC 2014 - idonmez@suse.com From 1cf0e051172b47e5b48c8e5b4d1cf57837a87912fa9ac4fd104c0c8b8b5711e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Thu, 3 Apr 2014 12:08:53 +0000 Subject: [PATCH 4/4] - Cleanup with spec-cleaner to sort out. - Really apply ppc64 patch as it was ommited probably by mistake. OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=49 --- libgcrypt.changes | 6 ++++++ libgcrypt.spec | 42 +++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/libgcrypt.changes b/libgcrypt.changes index 7edb063..a15264b 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Apr 3 12:04:46 UTC 2014 - tchvatal@suse.com + +- Cleanup with spec-cleaner to sort out. +- Really apply ppc64 patch as it was ommited probably by mistake. + ------------------------------------------------------------------- Thu Mar 27 14:57:22 UTC 2014 - meissner@suse.com diff --git a/libgcrypt.spec b/libgcrypt.spec index b83ae86..cd154c1 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -18,17 +18,15 @@ %define build_hmac256 1 %define separate_hmac256_binary 0 - %define libsoname %{name}20 %define sosuffix 20.0.1 - Name: libgcrypt -Url: http://directory.fsf.org/wiki/Libgcrypt Version: 1.6.1 Release: 0 Summary: The GNU Crypto Library License: GPL-2.0+ and LGPL-2.1+ and GPL-3.0+ Group: Development/Libraries/C and C++ +Url: http://directory.fsf.org/wiki/Libgcrypt Source: ftp://ftp.gnupg.org/gcrypt/libgcrypt/%{name}-%{version}.tar.bz2 Source1: ftp://ftp.gnupg.org/gcrypt/libgcrypt/%{name}-%{version}.tar.bz2.sig Source2: baselibs.conf @@ -42,25 +40,22 @@ Patch4: %{name}-sparcv9.diff #was: libgcrypt-1.5.0-as-needed.patch Patch5: libgcrypt-unresolved-dladdr.patch #PATCH-FIX-SUSE: N/A - Patch7: libgcrypt-1.5.0-LIBGCRYPT_FORCE_FIPS_MODE-env.diff - #PATCH-FIX-UPSTREAM: internal functions are supposed to be used inside libgcrypt, mvyskocil@suse.com Patch8: libgcrypt-1.6.0-use-intenal-functions.patch Patch10: libgcrypt-fips-allow-legacy.patch Patch11: libgcrypt-fixed-sizet.patch - Patch12: libgcrypt-1.6.1-use-fipscheck.patch Patch13: libgcrypt-1.6.1-fips-cavs.patch #PATCH-FIX-SUSE: bnc#724841, fix a random device opening routine Patch14: libgcrypt-1.6.1-fips-cfgrandom.patch -BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: automake >= 1.11 +BuildRequires: libgpg-error-devel >= 1.11 +BuildRequires: libtool +BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} > 1310 BuildRequires: fipscheck %endif -BuildRequires: libgpg-error-devel >= 1.11 -BuildRequires: libtool # not for base packages to avoid huge cycles #BuildRequires: gpg-offline @@ -86,7 +81,7 @@ Group: Development/Libraries/C and C++ Requires: %{libsoname} = %{version} Requires: glibc-devel Requires: libgpg-error-devel >= 1.8 -PreReq: %install_info_prereq +Requires(post): %{install_info_prereq} %description devel Libgcrypt is a general purpose library of cryptographic building @@ -103,9 +98,9 @@ library. Summary: The GNU Crypto Library License: GPL-2.0+ and LGPL-2.1+ Group: Development/Libraries/C and C++ -Requires: %{libsoname} = %version +Requires: %{libsoname} = %{version} Requires: libgpg-error-devel -PreReq: %install_info_prereq +Requires(post): %{install_info_prereq} %description hmac256 Libgcrypt is a general purpose library of cryptographic building @@ -116,7 +111,8 @@ understanding of applied cryptography is required to use Libgcrypt. %endif # #if separate_hmac256_binary %prep -%setup -q -n %{name}-%{version} +%setup -q +%patch0 -p1 %patch1 %patch3 -p1 %patch4 -p1 @@ -135,13 +131,13 @@ understanding of applied cryptography is required to use Libgcrypt. echo building with build_hmac256 set to %{build_hmac256} %{?suse_update_config} autoreconf -fi -export CFLAGS="%optflags $(getconf LFS_CFLAGS)" +export CFLAGS="%{optflags} $(getconf LFS_CFLAGS)" %configure --with-pic \ - --enable-noexecstack \ - --disable-static \ + --enable-noexecstack \ + --disable-static \ --enable-m-guard \ -%ifarch %sparc - --disable-asm \ +%ifarch %{sparc} + --disable-asm \ %endif --enable-hmac-binary-check \ --enable-random=linux @@ -181,7 +177,7 @@ fipshmac src/.libs/libgcrypt.so.?? # make check %install -make DESTDIR=$RPM_BUILD_ROOT install +make DESTDIR=%{buildroot} install %{?_smp_mflags} rm %{buildroot}%{_libdir}/%{name}.la @@ -201,15 +197,15 @@ rm %{buildroot}%{_libdir}/%{name}.la %files -n %{libsoname} %defattr(-,root,root) -%doc COPYING.LIB +%doc COPYING.LIB %{_libdir}/%{name}.so.* %if 0%{?build_hmac256} %{_libdir}/.libgcrypt.so.*.hmac -%endif # %if 0%{?build_hmac256} +%endif # %if 0%{?build_hmac256} %files devel %defattr(-,root,root) -%doc AUTHORS COPYING COPYING.LIB ChangeLog NEWS README THANKS TODO +%doc AUTHORS COPYING COPYING.LIB ChangeLog NEWS README THANKS TODO %{_infodir}/gcrypt.info.gz %{_infodir}/gcrypt.info-1.gz %{_infodir}/gcrypt.info-2.gz @@ -223,7 +219,7 @@ rm %{buildroot}%{_libdir}/%{name}.la %if 0%{?separate_hmac256_binary} %files hmac256 %defattr(-,root,root) -%endif # %if 0%{?separate_hmac256_binary} +%endif # %if 0%{?separate_hmac256_binary} %{_bindir}/hmac256 %{_bindir}/.hmac256.hmac %doc %{_mandir}/man1/hmac256.1*