diff --git a/SOURCES/libgcrypt-1.5.0-fips-cavs.patch b/SOURCES/libgcrypt-1.5.0-fips-cavs.patch deleted file mode 100644 index ac999f9..0000000 --- a/SOURCES/libgcrypt-1.5.0-fips-cavs.patch +++ /dev/null @@ -1,1174 +0,0 @@ -diff -up libgcrypt-1.5.0/cipher/dsa.c.cavs libgcrypt-1.5.0/cipher/dsa.c ---- libgcrypt-1.5.0/cipher/dsa.c.cavs 2011-07-21 14:56:35.000000000 +0200 -+++ libgcrypt-1.5.0/cipher/dsa.c 2011-07-21 14:58:06.000000000 +0200 -@@ -479,7 +479,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, -@@ -487,13 +486,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; -@@ -784,13 +792,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.5.0/tests/cavs_driver.pl.cavs libgcrypt-1.5.0/tests/cavs_driver.pl ---- libgcrypt-1.5.0/tests/cavs_driver.pl.cavs 2011-02-04 20:18:20.000000000 +0100 -+++ libgcrypt-1.5.0/tests/cavs_driver.pl 2011-07-21 15:01:47.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 -+# 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.5.0/tests/cavs_tests.sh.cavs libgcrypt-1.5.0/tests/cavs_tests.sh ---- libgcrypt-1.5.0/tests/cavs_tests.sh.cavs 2011-02-04 20:18:20.000000000 +0100 -+++ libgcrypt-1.5.0/tests/cavs_tests.sh 2011-07-21 15:02:16.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.5.0/tests/fipsdrv.c.cavs libgcrypt-1.5.0/tests/fipsdrv.c ---- libgcrypt-1.5.0/tests/fipsdrv.c.cavs 2011-02-04 20:18:20.000000000 +0100 -+++ libgcrypt-1.5.0/tests/fipsdrv.c 2011-07-21 15:06:44.000000000 +0200 -@@ -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/SOURCES/libgcrypt-1.5.0-fips-cfgrandom.patch b/SOURCES/libgcrypt-1.5.0-fips-cfgrandom.patch deleted file mode 100644 index 1384c25..0000000 --- a/SOURCES/libgcrypt-1.5.0-fips-cfgrandom.patch +++ /dev/null @@ -1,126 +0,0 @@ -diff -up libgcrypt-1.5.0/random/random-fips.c.cfgrandom libgcrypt-1.5.0/random/random-fips.c ---- libgcrypt-1.5.0/random/random-fips.c.cfgrandom 2011-07-21 14:50:34.000000000 +0200 -+++ libgcrypt-1.5.0/random/random-fips.c 2011-07-21 14:50:34.000000000 +0200 -@@ -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 - { -diff -up libgcrypt-1.5.0/random/rndlinux.c.cfgrandom libgcrypt-1.5.0/random/rndlinux.c ---- libgcrypt-1.5.0/random/rndlinux.c.cfgrandom 2011-02-04 20:16:03.000000000 +0100 -+++ libgcrypt-1.5.0/random/rndlinux.c 2011-07-21 14:50:34.000000000 +0200 -@@ -36,7 +36,9 @@ - #include "g10lib.h" - #include "rand-internal.h" - --static int open_device ( const char *name ); -+#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed" -+ -+static int open_device ( const char *name, int fatal ); - - - static int -@@ -57,13 +59,17 @@ set_cloexec_flag (int fd) - * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)). - */ - static int --open_device ( const char *name ) -+open_device ( const char *name, int fatal ) - { - int fd; - - fd = open ( name, O_RDONLY ); - if ( fd == -1 ) -- log_fatal ("can't open %s: %s\n", name, strerror(errno) ); -+ { -+ if (! fatal) -+ return fd; -+ log_fatal ("can't open %s: %s\n", name, strerror(errno) ); -+ } - - if (set_cloexec_flag (fd)) - log_error ("error setting FD_CLOEXEC on fd %d: %s\n", -@@ -92,6 +98,7 @@ _gcry_rndlinux_gather_random (void (*add - { - static int fd_urandom = -1; - static int fd_random = -1; -+ static int fd_configured = -1; - int fd; - int n; - byte buffer[768]; -@@ -100,6 +107,7 @@ _gcry_rndlinux_gather_random (void (*add - size_t last_so_far = 0; - int any_need_entropy = 0; - int delay; -+ size_t orig_length = length; - - /* First read from a hardware source. However let it account only - for up to 50% of the requested bytes. */ -@@ -110,16 +118,26 @@ _gcry_rndlinux_gather_random (void (*add - length -= n_hw; - - /* Open the requested device. */ -+ -+ if (level == -1) -+ { -+ if (fd_configured == -1) -+ fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0 ); -+ fd = fd_configured; -+ if (fd == -1) -+ return -1; -+ } -+ - if (level >= 2) - { - if( fd_random == -1 ) -- fd_random = open_device ( NAME_OF_DEV_RANDOM ); -+ fd_random = open_device ( NAME_OF_DEV_RANDOM, 1 ); - fd = fd_random; - } -- else -+ else if (level != -1) - { - if( fd_urandom == -1 ) -- fd_urandom = open_device ( NAME_OF_DEV_URANDOM ); -+ fd_urandom = open_device ( NAME_OF_DEV_URANDOM, 1 ); - fd = fd_urandom; - } - diff --git a/SOURCES/libgcrypt-1.5.3-drbg.patch b/SOURCES/libgcrypt-1.5.3-drbg.patch new file mode 100644 index 0000000..e75f7bf --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-drbg.patch @@ -0,0 +1,2699 @@ +diff -up libgcrypt-1.5.3/random/drbg.c.drbg libgcrypt-1.5.3/random/drbg.c +--- libgcrypt-1.5.3/random/drbg.c.drbg 2014-09-26 17:00:16.050215868 +0200 ++++ libgcrypt-1.5.3/random/drbg.c 2014-09-26 17:15:41.576110018 +0200 +@@ -0,0 +1,2352 @@ ++/* ++ * DRBG: Deterministic Random Bits Generator ++ * Based on NIST Recommended DRBG from NIST SP800-90A with the following ++ * properties: ++ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores ++ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores ++ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores ++ * * with and without prediction resistance ++ * ++ * Copyright Stephan Mueller , 2014 ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * LGPLv2+, in which case the provisions of the LGPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the LGPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF ++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ++ * ++ * gcry_control GCRYCTL_DRBG_REINIT ++ * ================================ ++ * This control request re-initializes the DRBG completely, i.e. the entire ++ * state of the DRBG is zeroized (with two exceptions listed in ++ * GCRYCTL_DRBG_SET_ENTROPY). ++ * ++ * The control request takes the following values which influences how the DRBG ++ * is re-initialized: ++ * * u32 flags: This variable specifies the DRBG type to be used for the ++ * next initialization. If set to 0, the previous DRBG type is ++ * used for the initialization. The DRBG type is an OR of the ++ * mandatory flags of the requested DRBG strength and DRBG ++ * cipher type. Optionally, the prediction resistance flag ++ * can be ORed into the flags variable. For example: ++ * - CTR-DRBG with AES-128 without prediction resistance: ++ * DRBG_CTRAES128 ++ * - HMAC-DRBG with SHA-512 with prediction resistance: ++ * DRBG_HMACSHA512 | DRBG_PREDICTION_RESIST ++ * * struct gcry_drbg_string *pers: personalization string to be used for ++ * initialization. ++ * The variable of flags is independent from the pers/perslen variables. If ++ * flags is set to 0 and perslen is set to 0, the current DRBG type is ++ * completely reset without using a personalization string. ++ * ++ * DRBG Usage ++ * ========== ++ * The SP 800-90A DRBG allows the user to specify a personalization string ++ * for initialization as well as an additional information string for each ++ * random number request. The following code fragments show how a caller ++ * uses the kernel crypto API to use the full functionality of the DRBG. ++ * ++ * Usage without any additional data ++ * --------------------------------- ++ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); ++ * ++ * ++ * Usage with personalization string during initialization ++ * ------------------------------------------------------- ++ * struct gcry_drbg_string pers; ++ * char personalization[11] = "some-string"; ++ * ++ * gcry_drbg_string_fill(&pers, personalization, strlen(personalization)); ++ * // The reset completely re-initializes the DRBG with the provided ++ * // personalization string without changing the DRBG type ++ * ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers); ++ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); ++ * ++ * ++ * Usage with additional information string during random number request ++ * --------------------------------------------------------------------- ++ * struct gcry_drbg_string addtl; ++ * char addtl_string[11] = "some-string"; ++ * ++ * gcry_drbg_string_fill(&addtl, addtl_string, strlen(addtl_string)); ++ * // The following call is a wrapper to gcry_randomize() and returns ++ * // the same error codes. ++ * gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl); ++ * ++ * ++ * Usage with personalization and additional information strings ++ * ------------------------------------------------------------- ++ * Just mix both scenarios above. ++ * ++ * ++ * Switch the DRBG type to some other type ++ * --------------------------------------- ++ * // Switch to CTR DRBG AES-128 without prediction resistance ++ * ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL); ++ * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM); ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "g10lib.h" ++#include "random.h" ++#include "rand-internal.h" ++#include "../cipher/bithelp.h" ++#include "ath.h" ++ ++/****************************************************************** ++ * Common data structures ++ ******************************************************************/ ++ ++struct gcry_drbg_state; ++ ++struct gcry_drbg_core ++{ ++ u32 flags; /* flags for the cipher */ ++ ushort statelen; /* maximum state length */ ++ ushort blocklen_bytes; /* block size of output in bytes */ ++ int backend_cipher; /* libgcrypt backend cipher */ ++}; ++ ++struct gcry_drbg_state_ops ++{ ++ gpg_err_code_t (*update) (struct gcry_drbg_state * drbg, ++ struct gcry_drbg_string * seed, int reseed); ++ gpg_err_code_t (*generate) (struct gcry_drbg_state * drbg, ++ unsigned char *buf, unsigned int buflen, ++ struct gcry_drbg_string * addtl); ++}; ++ ++/* DRBG test data */ ++struct gcry_drbg_test_data ++{ ++ struct gcry_drbg_string *testentropy; /* TEST PARAMETER: test entropy */ ++ int fail_seed_source:1; /* if set, the seed function will return an error */ ++}; ++ ++ ++struct gcry_drbg_state ++{ ++ unsigned char *V; /* internal state 10.1.1.1 1a) */ ++ unsigned char *C; /* hash: static value 10.1.1.1 1b) ++ * hmac / ctr: key */ ++ size_t reseed_ctr; /* Number of RNG requests since last reseed -- ++ * 10.1.1.1 1c) */ ++ unsigned char *scratchpad; /* some memory the DRBG can use for its ++ * operation -- allocated during init */ ++ int seeded:1; /* DRBG fully seeded? */ ++ int pr:1; /* Prediction resistance enabled? */ ++ int fips_primed:1; /* Continuous test primed? */ ++ unsigned char *prev; /* previous output value of gcry_drbg_blocklen ++ * for FIPS 140-2 continuous test */ ++ /* Taken from libgcrypt ANSI X9.31 DRNG: We need to keep track of the ++ * process which did the initialization so that we can detect a fork. ++ * The volatile modifier is required so that the compiler does not ++ * optimize it away in case the getpid function is badly attributed. */ ++ pid_t seed_init_pid; ++ const struct gcry_drbg_state_ops *d_ops; ++ const struct gcry_drbg_core *core; ++ struct gcry_drbg_test_data *test_data; ++}; ++ ++enum gcry_drbg_prefixes ++{ ++ DRBG_PREFIX0 = 0x00, ++ DRBG_PREFIX1, ++ DRBG_PREFIX2, ++ DRBG_PREFIX3 ++}; ++ ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++ ++/*************************************************************** ++ * Backend cipher definitions available to DRBG ++ ***************************************************************/ ++ ++static const struct gcry_drbg_core gcry_drbg_cores[] = { ++ /* Hash DRBGs */ ++ {GCRY_DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1}, ++ {GCRY_DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256}, ++ {GCRY_DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384}, ++ {GCRY_DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512}, ++ /* HMAC DRBGs */ ++ {GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC, 20, 20, GCRY_MD_SHA1}, ++ {GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC, 32, 32, GCRY_MD_SHA256}, ++ {GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC, 48, 48, GCRY_MD_SHA384}, ++ {GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC, 64, 64, GCRY_MD_SHA512}, ++ /* block ciphers */ ++ {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128}, ++ {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192}, ++ {GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256}, ++}; ++ ++static gpg_err_code_t gcry_drbg_sym (struct gcry_drbg_state *drbg, ++ const unsigned char *key, ++ unsigned char *outval, ++ const struct gcry_drbg_string *buf); ++static gpg_err_code_t gcry_drbg_hmac (struct gcry_drbg_state *drbg, ++ const unsigned char *key, ++ unsigned char *outval, ++ const struct gcry_drbg_string *buf); ++ ++/****************************************************************** ++ ****************************************************************** ++ ****************************************************************** ++ * Generic DRBG code ++ ****************************************************************** ++ ****************************************************************** ++ ******************************************************************/ ++ ++/****************************************************************** ++ * Generic helper functions ++ ******************************************************************/ ++ ++/* Byte swap for 32-bit and 64-bit integers. */ ++static inline u32 ++_gcry_bswap32(u32 x) ++{ ++ return ((rol(x, 8) & 0x00ff00ffL) | (ror(x, 8) & 0xff00ff00L)); ++} ++ ++#ifdef HAVE_U64_TYPEDEF ++static inline u64 ++_gcry_bswap64(u64 x) ++{ ++ return ((u64)_gcry_bswap32(x) << 32) | (_gcry_bswap32(x >> 32)); ++} ++#endif ++ ++/* Endian dependent byte swap operations. */ ++#ifdef WORDS_BIGENDIAN ++# define le_bswap32(x) _gcry_bswap32(x) ++# define be_bswap32(x) ((u32)(x)) ++# ifdef HAVE_U64_TYPEDEF ++# define le_bswap64(x) _gcry_bswap64(x) ++# define be_bswap64(x) ((u64)(x)) ++# endif ++#else ++# define le_bswap32(x) ((u32)(x)) ++# define be_bswap32(x) _gcry_bswap32(x) ++# ifdef HAVE_U64_TYPEDEF ++# define le_bswap64(x) ((u64)(x)) ++# define be_bswap64(x) _gcry_bswap64(x) ++# endif ++#endif ++ ++#define xcalloc_secure(a,b) gcry_xcalloc_secure((a),(b)) ++#define xfree(a) _gcry_free(a) ++ ++#if 0 ++#define dbg(x) do { log_debug x; } while(0) ++#else ++#define dbg(x) ++#endif ++ ++static inline ushort ++gcry_drbg_statelen (struct gcry_drbg_state *drbg) ++{ ++ if (drbg && drbg->core) ++ return drbg->core->statelen; ++ return 0; ++} ++ ++static inline ushort ++gcry_drbg_blocklen (struct gcry_drbg_state *drbg) ++{ ++ if (drbg && drbg->core) ++ return drbg->core->blocklen_bytes; ++ return 0; ++} ++ ++static inline ushort ++gcry_drbg_keylen (struct gcry_drbg_state *drbg) ++{ ++ if (drbg && drbg->core) ++ return (drbg->core->statelen - drbg->core->blocklen_bytes); ++ return 0; ++} ++ ++static inline size_t ++gcry_drbg_max_request_bytes (void) ++{ ++ /* SP800-90A requires the limit 2**19 bits, but we return bytes */ ++ return (1 << 16); ++} ++ ++static inline size_t ++gcry_drbg_max_addtl (void) ++{ ++ /* SP800-90A requires 2**35 bytes additional info str / pers str */ ++#ifdef __LP64__ ++ return (1UL << 35); ++#else ++ /* ++ * SP800-90A allows smaller maximum numbers to be returned -- we ++ * return SIZE_MAX - 1 to allow the verification of the enforcement ++ * of this value in gcry_drbg_healthcheck_sanity. ++ */ ++ return (SIZE_MAX - 1); ++#endif ++} ++ ++static inline size_t ++gcry_drbg_max_requests (void) ++{ ++ /* SP800-90A requires 2**48 maximum requests before reseeding */ ++#ifdef __LP64__ ++ return (1UL << 48); ++#else ++ return SIZE_MAX; ++#endif ++} ++ ++/* ++ * Return strength of DRBG according to SP800-90A section 8.4 ++ * ++ * flags: DRBG flags reference ++ * ++ * Return: normalized strength value or 32 as a default to counter ++ * programming errors ++ */ ++static inline unsigned short ++gcry_drbg_sec_strength (u32 flags) ++{ ++ if ((flags & GCRY_DRBG_HASHSHA1) || (flags & GCRY_DRBG_SYM128)) ++ return 16; ++ else if (flags & GCRY_DRBG_SYM192) ++ return 24; ++ else if ((flags & GCRY_DRBG_SYM256) || (flags & GCRY_DRBG_HASHSHA256) || ++ (flags & GCRY_DRBG_HASHSHA384) || (flags & GCRY_DRBG_HASHSHA512)) ++ return 32; ++ else ++ return 32; ++} ++ ++/* ++ * FIPS 140-2 continuous self test ++ * The test is performed on the result of one round of the output ++ * function. Thus, the function implicitly knows the size of the ++ * buffer. ++ * ++ * @drbg DRBG handle ++ * @buf output buffer of random data to be checked ++ * ++ * return: ++ * false on error ++ * true on success ++ */ ++static gpg_err_code_t ++gcry_drbg_fips_continuous_test (struct gcry_drbg_state *drbg, ++ const unsigned char *buf) ++{ ++ gpg_err_code_t ret = 0; ++ /* skip test if we test the overall system */ ++ if (drbg->test_data) ++ return 1; ++ /* only perform test in FIPS mode */ ++ if (0 == fips_mode ()) ++ return 1; ++ if (!drbg->fips_primed) ++ { ++ /* Priming of FIPS test */ ++ memcpy (drbg->prev, buf, gcry_drbg_blocklen (drbg)); ++ drbg->fips_primed = 1; ++ /* return false due to priming, i.e. another round is needed */ ++ return 0; ++ } ++ ret = memcmp (drbg->prev, buf, gcry_drbg_blocklen (drbg)); ++ memcpy (drbg->prev, buf, gcry_drbg_blocklen (drbg)); ++ /* the test shall pass when the two compared values are not equal */ ++ return ret != 0; ++} ++ ++/* ++ * Convert an integer into a byte representation of this integer. ++ * The byte representation is big-endian ++ * ++ * @val value to be converted ++ * @buf buffer holding the converted integer -- caller must ensure that ++ * buffer size is at least 32 bit ++ */ ++static inline void ++gcry_drbg_cpu_to_be32 (u32 val, unsigned char *buf) ++{ ++ struct s ++ { ++ u32 conv; ++ }; ++ struct s *conversion = (struct s *) buf; ++ ++ conversion->conv = be_bswap32 (val); ++} ++ ++static void ++gcry_drbg_add_buf (unsigned char *dst, size_t dstlen, ++ unsigned char *add, size_t addlen) ++{ ++ /* implied: dstlen > addlen */ ++ unsigned char *dstptr, *addptr; ++ unsigned int remainder = 0; ++ size_t len = addlen; ++ ++ dstptr = dst + (dstlen - 1); ++ addptr = add + (addlen - 1); ++ while (len) ++ { ++ remainder += *dstptr + *addptr; ++ *dstptr = remainder & 0xff; ++ remainder >>= 8; ++ len--; ++ dstptr--; ++ addptr--; ++ } ++ len = dstlen - addlen; ++ while (len && remainder > 0) ++ { ++ remainder = *dstptr + 1; ++ *dstptr = remainder & 0xff; ++ remainder >>= 8; ++ len--; ++ dstptr--; ++ } ++} ++ ++/* Helper variables for read_cb(). ++ * ++ * The _gcry_rnd*_gather_random interface does not allow to provide a ++ * data pointer. Thus we need to use a global variable for ++ * communication. However, the then required locking is anyway a good ++ * idea because it does not make sense to have several readers of (say ++ * /dev/random). It is easier to serve them one after the other. */ ++static unsigned char *read_cb_buffer; /* The buffer. */ ++static size_t read_cb_size; /* Size of the buffer. */ ++static size_t read_cb_len; /* Used length. */ ++ ++/* Callback for generating seed from kernel device. */ ++static void ++gcry_drbg_read_cb (const void *buffer, size_t length, ++ enum random_origins origin) ++{ ++ const unsigned char *p = buffer; ++ ++ (void) origin; ++ gcry_assert (read_cb_buffer); ++ ++ /* Note that we need to protect against gatherers returning more ++ * than the requested bytes (e.g. rndw32). */ ++ while (length-- && read_cb_len < read_cb_size) ++ read_cb_buffer[read_cb_len++] = *p++; ++} ++ ++static inline int ++gcry_drbg_get_entropy (struct gcry_drbg_state *drbg, unsigned char *buffer, ++ size_t len) ++{ ++ int rc = 0; ++ ++ /* Perform testing as defined in 11.3.2 */ ++ if (drbg->test_data && drbg->test_data->fail_seed_source) ++ return -1; ++ ++ read_cb_buffer = buffer; ++ read_cb_size = len; ++ read_cb_len = 0; ++#if USE_RNDLINUX ++ rc = _gcry_rndlinux_gather_random (gcry_drbg_read_cb, 0, len, ++ GCRY_VERY_STRONG_RANDOM); ++#elif USE_RNDUNIX ++ rc = _gcry_rndunix_gather_random (read_cb, 0, length, ++ GCRY_VERY_STRONG_RANDOM); ++#elif USE_RNDW32 ++ do ++ { ++ rc = _gcry_rndw32_gather_random (read_cb, 0, length, ++ GCRY_VERY_STRONG_RANDOM); ++ } ++ while (rc >= 0 && read_cb_len < read_cb_size); ++#else ++ rc = -1; ++#endif ++ return rc; ++} ++ ++/****************************************************************** ++ * CTR DRBG callback functions ++ ******************************************************************/ ++ ++/* BCC function for CTR DRBG as defined in 10.4.3 */ ++static gpg_err_code_t ++gcry_drbg_ctr_bcc (struct gcry_drbg_state *drbg, ++ unsigned char *out, const unsigned char *key, ++ struct gcry_drbg_string *in) ++{ ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ struct gcry_drbg_string *curr = in; ++ size_t inpos = curr->len; ++ const unsigned char *pos = curr->buf; ++ struct gcry_drbg_string data; ++ ++ gcry_drbg_string_fill (&data, out, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.4.3 step 1 */ ++ memset (out, 0, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.4.3 step 2 / 4 */ ++ while (inpos) ++ { ++ short cnt = 0; ++ /* 10.4.3 step 4.1 */ ++ for (cnt = 0; cnt < gcry_drbg_blocklen (drbg); cnt++) ++ { ++ out[cnt] ^= *pos; ++ pos++; ++ inpos--; ++ /* the following branch implements the linked list ++ * iteration. If we are at the end of the current data ++ * set, we have to start using the next data set if ++ * available -- the inpos value always points to the ++ * current byte and will be zero if we have processed ++ * the last byte of the last linked list member */ ++ if (0 == inpos) ++ { ++ curr = curr->next; ++ if (NULL != curr) ++ { ++ pos = curr->buf; ++ inpos = curr->len; ++ } ++ else ++ { ++ inpos = 0; ++ break; ++ } ++ } ++ } ++ /* 10.4.3 step 4.2 */ ++ ret = gcry_drbg_sym (drbg, key, out, &data); ++ if (ret) ++ return ret; ++ /* 10.4.3 step 2 */ ++ } ++ return 0; ++} ++ ++ ++/* ++ * scratchpad usage: gcry_drbg_ctr_update is interlinked with gcry_drbg_ctr_df ++ * (and gcry_drbg_ctr_bcc, but this function does not need any temporary buffers), ++ * the scratchpad is used as follows: ++ * gcry_drbg_ctr_update: ++ * temp ++ * start: drbg->scratchpad ++ * length: gcry_drbg_statelen(drbg) + gcry_drbg_blocklen(drbg) ++ * note: the cipher writing into this variable works ++ * blocklen-wise. Now, when the statelen is not a multiple ++ * of blocklen, the generateion loop below "spills over" ++ * by at most blocklen. Thus, we need to give sufficient ++ * memory. ++ * df_data ++ * start: drbg->scratchpad + ++ * gcry_drbg_statelen(drbg) + ++ * gcry_drbg_blocklen(drbg) ++ * length: gcry_drbg_statelen(drbg) ++ * ++ * gcry_drbg_ctr_df: ++ * pad ++ * start: df_data + gcry_drbg_statelen(drbg) ++ * length: gcry_drbg_blocklen(drbg) ++ * iv ++ * start: pad + gcry_drbg_blocklen(drbg) ++ * length: gcry_drbg_blocklen(drbg) ++ * temp ++ * start: iv + gcry_drbg_blocklen(drbg) ++ * length: gcry_drbg_satelen(drbg) + gcry_drbg_blocklen(drbg) ++ * note: temp is the buffer that the BCC function operates ++ * on. BCC operates blockwise. gcry_drbg_statelen(drbg) ++ * is sufficient when the DRBG state length is a multiple ++ * of the block size. For AES192 (and maybe other ciphers) ++ * this is not correct and the length for temp is ++ * insufficient (yes, that also means for such ciphers, ++ * the final output of all BCC rounds are truncated). ++ * Therefore, add gcry_drbg_blocklen(drbg) to cover all ++ * possibilities. ++ */ ++ ++/* Derivation Function for CTR DRBG as defined in 10.4.2 */ ++static gpg_err_code_t ++gcry_drbg_ctr_df (struct gcry_drbg_state *drbg, unsigned char *df_data, ++ size_t bytes_to_return, struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ unsigned char L_N[8]; ++ /* S3 is input */ ++ struct gcry_drbg_string S1, S2, S4, cipherin; ++ struct gcry_drbg_string *tempstr = addtl; ++ unsigned char *pad = df_data + gcry_drbg_statelen (drbg); ++ unsigned char *iv = pad + gcry_drbg_blocklen (drbg); ++ unsigned char *temp = iv + gcry_drbg_blocklen (drbg); ++ size_t padlen = 0; ++ unsigned int templen = 0; ++ /* 10.4.2 step 7 */ ++ unsigned int i = 0; ++ /* 10.4.2 step 8 */ ++ const unsigned char *K = (unsigned char *) ++ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" ++ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; ++ unsigned char *X; ++ size_t generated_len = 0; ++ size_t inputlen = 0; ++ ++ memset (pad, 0, gcry_drbg_blocklen (drbg)); ++ memset (iv, 0, gcry_drbg_blocklen (drbg)); ++ memset (temp, 0, gcry_drbg_statelen (drbg)); ++ ++ /* 10.4.2 step 1 is implicit as we work byte-wise */ ++ ++ /* 10.4.2 step 2 */ ++ if ((512 / 8) < bytes_to_return) ++ return GPG_ERR_INV_ARG; ++ ++ /* 10.4.2 step 2 -- calculate the entire length of all input data */ ++ for (; NULL != tempstr; tempstr = tempstr->next) ++ inputlen += tempstr->len; ++ gcry_drbg_cpu_to_be32 (inputlen, &L_N[0]); ++ ++ /* 10.4.2 step 3 */ ++ gcry_drbg_cpu_to_be32 (bytes_to_return, &L_N[4]); ++ ++ /* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */ ++ padlen = (inputlen + sizeof (L_N) + 1) % (gcry_drbg_blocklen (drbg)); ++ /* wrap the padlen appropriately */ ++ if (padlen) ++ padlen = gcry_drbg_blocklen (drbg) - padlen; ++ /* pad / padlen contains the 0x80 byte and the following zero bytes, so ++ * add one for byte for 0x80 */ ++ padlen++; ++ pad[0] = 0x80; ++ ++ /* 10.4.2 step 4 -- first fill the linked list and then order it */ ++ gcry_drbg_string_fill (&S1, iv, gcry_drbg_blocklen (drbg)); ++ gcry_drbg_string_fill (&S2, L_N, sizeof (L_N)); ++ gcry_drbg_string_fill (&S4, pad, padlen); ++ S1.next = &S2; ++ S2.next = addtl; ++ ++ /* Splice in addtl between S2 and S4 -- we place S4 at the end of the ++ * input data chain. As this code is only triggered when addtl is not ++ * NULL, no NULL checks are necessary.*/ ++ tempstr = addtl; ++ while (tempstr->next) ++ tempstr = tempstr->next; ++ tempstr->next = &S4; ++ ++ /* 10.4.2 step 9 */ ++ while (templen < (gcry_drbg_keylen (drbg) + (gcry_drbg_blocklen (drbg)))) ++ { ++ /* 10.4.2 step 9.1 - the padding is implicit as the buffer ++ * holds zeros after allocation -- even the increment of i ++ * is irrelevant as the increment remains within length of i */ ++ gcry_drbg_cpu_to_be32 (i, iv); ++ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */ ++ ret = gcry_drbg_ctr_bcc (drbg, temp + templen, K, &S1); ++ if (ret) ++ goto out; ++ /* 10.4.2 step 9.3 */ ++ i++; ++ templen += gcry_drbg_blocklen (drbg); ++ } ++ ++ /* 10.4.2 step 11 */ ++ /* implicit key len with seedlen - blocklen according to table 3 */ ++ X = temp + (gcry_drbg_keylen (drbg)); ++ gcry_drbg_string_fill (&cipherin, X, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.4.2 step 12: overwriting of outval */ ++ ++ /* 10.4.2 step 13 */ ++ while (generated_len < bytes_to_return) ++ { ++ short blocklen = 0; ++ /* 10.4.2 step 13.1 */ ++ /* the truncation of the key length is implicit as the key ++ * is only gcry_drbg_blocklen in size -- check for the implementation ++ * of the cipher function callback */ ++ ret = gcry_drbg_sym (drbg, temp, X, &cipherin); ++ if (ret) ++ goto out; ++ blocklen = (gcry_drbg_blocklen (drbg) < ++ (bytes_to_return - generated_len)) ? ++ gcry_drbg_blocklen (drbg) : (bytes_to_return - generated_len); ++ /* 10.4.2 step 13.2 and 14 */ ++ memcpy (df_data + generated_len, X, blocklen); ++ generated_len += blocklen; ++ } ++ ++ ret = 0; ++ ++out: ++ memset (iv, 0, gcry_drbg_blocklen (drbg)); ++ memset (temp, 0, gcry_drbg_statelen (drbg)); ++ memset (pad, 0, gcry_drbg_blocklen (drbg)); ++ return ret; ++} ++ ++/* ++ * update function of CTR DRBG as defined in 10.2.1.2 ++ * ++ * The reseed variable has an enhanced meaning compared to the update ++ * functions of the other DRBGs as follows: ++ * 0 => initial seed from initialization ++ * 1 => reseed via gcry_drbg_seed ++ * 2 => first invocation from gcry_drbg_ctr_update when addtl is present. In ++ * this case, the df_data scratchpad is not deleted so that it is ++ * available for another calls to prevent calling the DF function ++ * again. ++ * 3 => second invocation from gcry_drbg_ctr_update. When the update function ++ * was called with addtl, the df_data memory already contains the ++ * DFed addtl information and we do not need to call DF again. ++ */ ++static gpg_err_code_t ++gcry_drbg_ctr_update (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *addtl, int reseed) ++{ ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ /* 10.2.1.2 step 1 */ ++ unsigned char *temp = drbg->scratchpad; ++ unsigned char *df_data = drbg->scratchpad + ++ gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); ++ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */ ++ unsigned int len = 0; ++ struct gcry_drbg_string cipherin; ++ unsigned char prefix = DRBG_PREFIX1; ++ ++ memset (temp, 0, gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg)); ++ if (3 > reseed) ++ memset (df_data, 0, gcry_drbg_statelen (drbg)); ++ ++ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ ++ /* TODO use reseed variable to avoid re-doing DF operation */ ++ (void) reseed; ++ if (addtl && 0 < addtl->len) ++ { ++ ret = ++ gcry_drbg_ctr_df (drbg, df_data, gcry_drbg_statelen (drbg), addtl); ++ if (ret) ++ goto out; ++ } ++ ++ gcry_drbg_string_fill (&cipherin, drbg->V, gcry_drbg_blocklen (drbg)); ++ /* 10.2.1.3.2 step 2 and 3 -- are already covered as we memset(0) ++ * all memory during initialization */ ++ while (len < (gcry_drbg_statelen (drbg))) ++ { ++ /* 10.2.1.2 step 2.1 */ ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); ++ /* 10.2.1.2 step 2.2 */ ++ /* using target of temp + len: 10.2.1.2 step 2.3 and 3 */ ++ ret = gcry_drbg_sym (drbg, drbg->C, temp + len, &cipherin); ++ if (ret) ++ goto out; ++ /* 10.2.1.2 step 2.3 and 3 */ ++ len += gcry_drbg_blocklen (drbg); ++ } ++ ++ /* 10.2.1.2 step 4 */ ++ temp_p = temp; ++ df_data_p = df_data; ++ for (len = 0; len < gcry_drbg_statelen (drbg); len++) ++ { ++ *temp_p ^= *df_data_p; ++ df_data_p++; ++ temp_p++; ++ } ++ ++ /* 10.2.1.2 step 5 */ ++ memcpy (drbg->C, temp, gcry_drbg_keylen (drbg)); ++ /* 10.2.1.2 step 6 */ ++ memcpy (drbg->V, temp + gcry_drbg_keylen (drbg), gcry_drbg_blocklen (drbg)); ++ ret = 0; ++ ++out: ++ memset (temp, 0, gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg)); ++ if (2 != reseed) ++ memset (df_data, 0, gcry_drbg_statelen (drbg)); ++ return ret; ++} ++ ++/* ++ * scratchpad use: gcry_drbg_ctr_update is called independently from ++ * gcry_drbg_ctr_extract_bytes. Therefore, the scratchpad is reused ++ */ ++/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ ++static gpg_err_code_t ++gcry_drbg_ctr_generate (struct gcry_drbg_state *drbg, ++ unsigned char *buf, unsigned int buflen, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned int len = 0; ++ struct gcry_drbg_string data; ++ unsigned char prefix = DRBG_PREFIX1; ++ ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.2.1.5.2 step 2 */ ++ if (addtl && 0 < addtl->len) ++ { ++ addtl->next = NULL; ++ ret = gcry_drbg_ctr_update (drbg, addtl, 2); ++ if (ret) ++ return ret; ++ } ++ ++ /* 10.2.1.5.2 step 4.1 */ ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); ++ gcry_drbg_string_fill (&data, drbg->V, gcry_drbg_blocklen (drbg)); ++ while (len < buflen) ++ { ++ unsigned int outlen = 0; ++ /* 10.2.1.5.2 step 4.2 */ ++ ret = gcry_drbg_sym (drbg, drbg->C, drbg->scratchpad, &data); ++ if (ret) ++ goto out; ++ outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? ++ gcry_drbg_blocklen (drbg) : (buflen - len); ++ if (!gcry_drbg_fips_continuous_test (drbg, drbg->scratchpad)) ++ { ++ /* 10.2.1.5.2 step 6 */ ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); ++ continue; ++ } ++ /* 10.2.1.5.2 step 4.3 */ ++ memcpy (buf + len, drbg->scratchpad, outlen); ++ len += outlen; ++ /* 10.2.1.5.2 step 6 */ ++ if (len < buflen) ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_blocklen (drbg), &prefix, 1); ++ } ++ ++ /* 10.2.1.5.2 step 6 */ ++ if (addtl) ++ addtl->next = NULL; ++ ret = gcry_drbg_ctr_update (drbg, addtl, 3); ++ ++out: ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ return ret; ++} ++ ++static struct gcry_drbg_state_ops gcry_drbg_ctr_ops = { ++ gcry_drbg_ctr_update, ++ gcry_drbg_ctr_generate, ++}; ++ ++/****************************************************************** ++ * HMAC DRBG callback functions ++ ******************************************************************/ ++ ++static gpg_err_code_t ++gcry_drbg_hmac_update (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *seed, int reseed) ++{ ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ int i = 0; ++ struct gcry_drbg_string seed1, seed2, cipherin; ++ ++ if (!reseed) ++ /* 10.1.2.3 step 2 already implicitly covered with ++ * the initial memset(0) of drbg->C */ ++ memset (drbg->V, 1, gcry_drbg_statelen (drbg)); ++ ++ /* build linked list which implements the concatenation and fill ++ * first part*/ ++ gcry_drbg_string_fill (&seed1, drbg->V, gcry_drbg_statelen (drbg)); ++ /* buffer will be filled in for loop below with one byte */ ++ gcry_drbg_string_fill (&seed2, NULL, 1); ++ seed1.next = &seed2; ++ /* seed may be NULL */ ++ seed2.next = seed; ++ ++ gcry_drbg_string_fill (&cipherin, drbg->V, gcry_drbg_statelen (drbg)); ++ /* we execute two rounds of V/K massaging */ ++ for (i = 2; 0 < i; i--) ++ { ++ /* first round uses 0x0, second 0x1 */ ++ unsigned char prefix = DRBG_PREFIX0; ++ if (1 == i) ++ prefix = DRBG_PREFIX1; ++ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ ++ seed2.buf = &prefix; ++ ret = gcry_drbg_hmac (drbg, drbg->C, drbg->C, &seed1); ++ if (ret) ++ return ret; ++ ++ /* 10.1.2.2 step 2 and 5 -- HMAC for V */ ++ ret = gcry_drbg_hmac (drbg, drbg->C, drbg->V, &cipherin); ++ if (ret) ++ return ret; ++ ++ /* 10.1.2.2 step 3 */ ++ if (!seed || 0 == seed->len) ++ return ret; ++ } ++ return 0; ++} ++ ++/* generate function of HMAC DRBG as defined in 10.1.2.5 */ ++static gpg_err_code_t ++gcry_drbg_hmac_generate (struct gcry_drbg_state *drbg, ++ unsigned char *buf, ++ unsigned int buflen, struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned int len = 0; ++ struct gcry_drbg_string data; ++ ++ /* 10.1.2.5 step 2 */ ++ if (addtl && 0 < addtl->len) ++ { ++ addtl->next = NULL; ++ ret = gcry_drbg_hmac_update (drbg, addtl, 1); ++ if (ret) ++ return ret; ++ } ++ ++ gcry_drbg_string_fill (&data, drbg->V, gcry_drbg_statelen (drbg)); ++ while (len < buflen) ++ { ++ unsigned int outlen = 0; ++ /* 10.1.2.5 step 4.1 */ ++ ret = gcry_drbg_hmac (drbg, drbg->C, drbg->V, &data); ++ if (ret) ++ return ret; ++ outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? ++ gcry_drbg_blocklen (drbg) : (buflen - len); ++ if (!gcry_drbg_fips_continuous_test (drbg, drbg->V)) ++ continue; ++ ++ /* 10.1.2.5 step 4.2 */ ++ memcpy (buf + len, drbg->V, outlen); ++ len += outlen; ++ } ++ ++ /* 10.1.2.5 step 6 */ ++ if (addtl) ++ addtl->next = NULL; ++ ret = gcry_drbg_hmac_update (drbg, addtl, 1); ++ ++ return ret; ++} ++ ++static struct gcry_drbg_state_ops gcry_drbg_hmac_ops = { ++ gcry_drbg_hmac_update, ++ gcry_drbg_hmac_generate, ++}; ++ ++/****************************************************************** ++ * Hash DRBG callback functions ++ ******************************************************************/ ++ ++/* ++ * scratchpad usage: as gcry_drbg_hash_update and gcry_drbg_hash_df are used ++ * interlinked, the scratchpad is used as follows: ++ * gcry_drbg_hash_update ++ * start: drbg->scratchpad ++ * length: gcry_drbg_statelen(drbg) ++ * gcry_drbg_hash_df: ++ * start: drbg->scratchpad + gcry_drbg_statelen(drbg) ++ * length: gcry_drbg_blocklen(drbg) ++ */ ++/* Derivation Function for Hash DRBG as defined in 10.4.1 */ ++static gpg_err_code_t ++gcry_drbg_hash_df (struct gcry_drbg_state *drbg, ++ unsigned char *outval, size_t outlen, ++ struct gcry_drbg_string *entropy) ++{ ++ gpg_err_code_t ret = 0; ++ size_t len = 0; ++ unsigned char input[5]; ++ unsigned char *tmp = drbg->scratchpad + gcry_drbg_statelen (drbg); ++ struct gcry_drbg_string data1; ++ ++ memset (tmp, 0, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.4.1 step 3 */ ++ input[0] = 1; ++ gcry_drbg_cpu_to_be32 ((outlen * 8), &input[1]); ++ ++ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */ ++ gcry_drbg_string_fill (&data1, input, 5); ++ data1.next = entropy; ++ ++ /* 10.4.1 step 4 */ ++ while (len < outlen) ++ { ++ short blocklen = 0; ++ /* 10.4.1 step 4.1 */ ++ ret = gcry_drbg_hmac (drbg, NULL, tmp, &data1); ++ if (ret) ++ goto out; ++ /* 10.4.1 step 4.2 */ ++ input[0]++; ++ blocklen = (gcry_drbg_blocklen (drbg) < (outlen - len)) ? ++ gcry_drbg_blocklen (drbg) : (outlen - len); ++ memcpy (outval + len, tmp, blocklen); ++ len += blocklen; ++ } ++ ++out: ++ memset (tmp, 0, gcry_drbg_blocklen (drbg)); ++ return ret; ++} ++ ++/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */ ++static gpg_err_code_t ++gcry_drbg_hash_update (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *seed, int reseed) ++{ ++ gpg_err_code_t ret = 0; ++ struct gcry_drbg_string data1, data2; ++ unsigned char *V = drbg->scratchpad; ++ unsigned char prefix = DRBG_PREFIX1; ++ ++ memset (drbg->scratchpad, 0, gcry_drbg_statelen (drbg)); ++ if (!seed) ++ return GPG_ERR_INV_ARG; ++ ++ if (reseed) ++ { ++ /* 10.1.1.3 step 1: string length is concatenation of ++ * 1 byte, V and seed (which is concatenated entropy/addtl ++ * input) ++ */ ++ memcpy (V, drbg->V, gcry_drbg_statelen (drbg)); ++ gcry_drbg_string_fill (&data1, &prefix, 1); ++ gcry_drbg_string_fill (&data2, V, gcry_drbg_statelen (drbg)); ++ data1.next = &data2; ++ data2.next = seed; ++ } ++ else ++ { ++ gcry_drbg_string_fill (&data1, seed->buf, seed->len); ++ data1.next = seed->next; ++ } ++ ++ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */ ++ ret = gcry_drbg_hash_df (drbg, drbg->V, gcry_drbg_statelen (drbg), &data1); ++ if (ret) ++ goto out; ++ ++ /* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */ ++ prefix = DRBG_PREFIX0; ++ gcry_drbg_string_fill (&data1, &prefix, 1); ++ gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); ++ data1.next = &data2; ++ /* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */ ++ ret = gcry_drbg_hash_df (drbg, drbg->C, gcry_drbg_statelen (drbg), &data1); ++ ++out: ++ memset (drbg->scratchpad, 0, gcry_drbg_statelen (drbg)); ++ return ret; ++} ++ ++/* processing of additional information string for Hash DRBG */ ++static gpg_err_code_t ++gcry_drbg_hash_process_addtl (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ struct gcry_drbg_string data1, data2; ++ struct gcry_drbg_string *data3; ++ unsigned char prefix = DRBG_PREFIX2; ++ ++ /* this is value w as per documentation */ ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.1.1.4 step 2 */ ++ if (!addtl || 0 == addtl->len) ++ return 0; ++ ++ /* 10.1.1.4 step 2a -- concatenation */ ++ gcry_drbg_string_fill (&data1, &prefix, 1); ++ gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); ++ data3 = addtl; ++ data1.next = &data2; ++ data2.next = data3; ++ data3->next = NULL; ++ /* 10.1.1.4 step 2a -- cipher invocation */ ++ ret = gcry_drbg_hmac (drbg, NULL, drbg->scratchpad, &data1); ++ if (ret) ++ goto out; ++ ++ /* 10.1.1.4 step 2b */ ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), ++ drbg->scratchpad, gcry_drbg_blocklen (drbg)); ++ ++out: ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ return ret; ++} ++ ++/* ++ * Hashgen defined in 10.1.1.4 ++ */ ++static gpg_err_code_t ++gcry_drbg_hash_hashgen (struct gcry_drbg_state *drbg, ++ unsigned char *buf, unsigned int buflen) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned int len = 0; ++ unsigned char *src = drbg->scratchpad; ++ unsigned char *dst = drbg->scratchpad + gcry_drbg_statelen (drbg); ++ struct gcry_drbg_string data; ++ unsigned char prefix = DRBG_PREFIX1; ++ ++ /* use the scratchpad as a lookaside buffer */ ++ memset (src, 0, gcry_drbg_statelen (drbg)); ++ memset (dst, 0, gcry_drbg_blocklen (drbg)); ++ ++ /* 10.1.1.4 step hashgen 2 */ ++ memcpy (src, drbg->V, gcry_drbg_statelen (drbg)); ++ ++ gcry_drbg_string_fill (&data, src, gcry_drbg_statelen (drbg)); ++ while (len < buflen) ++ { ++ unsigned int outlen = 0; ++ /* 10.1.1.4 step hashgen 4.1 */ ++ ret = gcry_drbg_hmac (drbg, NULL, dst, &data); ++ if (ret) ++ goto out; ++ outlen = (gcry_drbg_blocklen (drbg) < (buflen - len)) ? ++ gcry_drbg_blocklen (drbg) : (buflen - len); ++ if (!gcry_drbg_fips_continuous_test (drbg, dst)) ++ { ++ gcry_drbg_add_buf (src, gcry_drbg_statelen (drbg), &prefix, 1); ++ continue; ++ } ++ /* 10.1.1.4 step hashgen 4.2 */ ++ memcpy (buf + len, dst, outlen); ++ len += outlen; ++ /* 10.1.1.4 hashgen step 4.3 */ ++ if (len < buflen) ++ gcry_drbg_add_buf (src, gcry_drbg_statelen (drbg), &prefix, 1); ++ } ++ ++out: ++ memset (drbg->scratchpad, 0, ++ (gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg))); ++ return ret; ++} ++ ++/* generate function for Hash DRBG as defined in 10.1.1.4 */ ++static gpg_err_code_t ++gcry_drbg_hash_generate (struct gcry_drbg_state *drbg, ++ unsigned char *buf, unsigned int buflen, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned char prefix = DRBG_PREFIX3; ++ struct gcry_drbg_string data1, data2; ++ union ++ { ++ unsigned char req[8]; ++ u64 req_int; ++ } u; ++ ++ /* ++ * scratchpad usage: gcry_drbg_hash_process_addtl uses the scratchpad, but ++ * fully completes before returning. Thus, we can reuse the scratchpad ++ */ ++ /* 10.1.1.4 step 2 */ ++ ret = gcry_drbg_hash_process_addtl (drbg, addtl); ++ if (ret) ++ return ret; ++ /* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in ++ * 10.1.1.4 */ ++ ret = gcry_drbg_hash_hashgen (drbg, buf, buflen); ++ if (ret) ++ return ret; ++ ++ /* this is the value H as documented in 10.1.1.4 */ ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ /* 10.1.1.4 step 4 */ ++ gcry_drbg_string_fill (&data1, &prefix, 1); ++ gcry_drbg_string_fill (&data2, drbg->V, gcry_drbg_statelen (drbg)); ++ data1.next = &data2; ++ ret = gcry_drbg_hmac (drbg, NULL, drbg->scratchpad, &data1); ++ if (ret) ++ goto out; ++ ++ /* 10.1.1.4 step 5 */ ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), ++ drbg->scratchpad, gcry_drbg_blocklen (drbg)); ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), drbg->C, ++ gcry_drbg_statelen (drbg)); ++ u.req_int = be_bswap64 (drbg->reseed_ctr); ++ gcry_drbg_add_buf (drbg->V, gcry_drbg_statelen (drbg), u.req, ++ sizeof (u.req)); ++ ++out: ++ memset (drbg->scratchpad, 0, gcry_drbg_blocklen (drbg)); ++ return ret; ++} ++ ++/* ++ * scratchpad usage: as update and generate are used isolated, both ++ * can use the scratchpad ++ */ ++static struct gcry_drbg_state_ops gcry_drbg_hash_ops = { ++ gcry_drbg_hash_update, ++ gcry_drbg_hash_generate, ++}; ++ ++/****************************************************************** ++ * Functions common for DRBG implementations ++ ******************************************************************/ ++ ++/* ++ * Seeding or reseeding of the DRBG ++ * ++ * @drbg: DRBG state struct ++ * @pers: personalization / additional information buffer ++ * @reseed: 0 for initial seed process, 1 for reseeding ++ * ++ * return: ++ * 0 on success ++ * error value otherwise ++ */ ++static gpg_err_code_t ++gcry_drbg_seed (struct gcry_drbg_state *drbg, struct gcry_drbg_string *pers, ++ int reseed) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned char *entropy = NULL; ++ size_t entropylen = 0; ++ struct gcry_drbg_string data1; ++ ++ /* 9.1 / 9.2 / 9.3.1 step 3 */ ++ if (pers && pers->len > (gcry_drbg_max_addtl ())) ++ { ++ dbg (("DRBG: personalization string too long %lu\n", pers->len)); ++ return GPG_ERR_INV_ARG; ++ } ++ if (drbg->test_data && drbg->test_data->testentropy) ++ { ++ gcry_drbg_string_fill (&data1, drbg->test_data->testentropy->buf, ++ drbg->test_data->testentropy->len); ++ dbg (("DRBG: using test entropy\n")); ++ } ++ else ++ { ++ /* Gather entropy equal to the security strength of the DRBG. ++ * With a derivation function, a nonce is required in addition ++ * to the entropy. A nonce must be at least 1/2 of the security ++ * strength of the DRBG in size. Thus, entropy * nonce is 3/2 ++ * of the strength. The consideration of a nonce is only ++ * applicable during initial seeding. */ ++ entropylen = gcry_drbg_sec_strength (drbg->core->flags); ++ if (!entropylen) ++ return GPG_ERR_GENERAL; ++ if (0 == reseed) ++ /* make sure we round up strength/2 in ++ * case it is not divisible by 2 */ ++ entropylen = ((entropylen + 1) / 2) * 3; ++ dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen)); ++ entropy = xcalloc_secure (1, entropylen); ++ if (!entropy) ++ return GPG_ERR_ENOMEM; ++ ret = gcry_drbg_get_entropy (drbg, entropy, entropylen); ++ if (ret) ++ goto out; ++ gcry_drbg_string_fill (&data1, entropy, entropylen); ++ } ++ ++ /* concatenation of entropy with personalization str / addtl input) ++ * the variable pers is directly handed by the caller, check its ++ * contents whether it is appropriate */ ++ if (pers && pers->buf && 0 < pers->len && NULL == pers->next) ++ { ++ data1.next = pers; ++ dbg (("DRBG: using personalization string\n")); ++ } ++ ++ ret = drbg->d_ops->update (drbg, &data1, reseed); ++ dbg (("DRBG: state updated with seed\n")); ++ if (ret) ++ goto out; ++ drbg->seeded = 1; ++ /* 10.1.1.2 / 10.1.1.3 step 5 */ ++ drbg->reseed_ctr = 1; ++ ++out: ++ xfree (entropy); ++ return ret; ++} ++ ++/************************************************************************* ++ * exported interfaces ++ *************************************************************************/ ++ ++/* ++ * DRBG generate function as required by SP800-90A - this function ++ * generates random numbers ++ * ++ * @drbg DRBG state handle ++ * @buf Buffer where to store the random numbers -- the buffer must already ++ * be pre-allocated by caller ++ * @buflen Length of output buffer - this value defines the number of random ++ * bytes pulled from DRBG ++ * @addtl Additional input that is mixed into state, may be NULL -- note ++ * the entropy is pulled by the DRBG internally unconditionally ++ * as defined in SP800-90A. The additional input is mixed into ++ * the state in addition to the pulled entropy. ++ * ++ * return: generated number of bytes ++ */ ++static gpg_err_code_t ++gcry_drbg_generate (struct gcry_drbg_state *drbg, ++ unsigned char *buf, unsigned int buflen, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = GPG_ERR_INV_ARG; ++ ++ if (0 == buflen || !buf) ++ { ++ dbg (("DRBG: no buffer provided\n")); ++ return ret; ++ } ++ if (addtl && NULL == addtl->buf && 0 < addtl->len) ++ { ++ dbg (("DRBG: wrong format of additional information\n")); ++ return ret; ++ } ++ ++ /* 9.3.1 step 2 */ ++ if (buflen > (gcry_drbg_max_request_bytes ())) ++ { ++ dbg (("DRBG: requested random numbers too large %u\n", buflen)); ++ return ret; ++ } ++ /* 9.3.1 step 3 is implicit with the chosen DRBG */ ++ /* 9.3.1 step 4 */ ++ if (addtl && addtl->len > (gcry_drbg_max_addtl ())) ++ { ++ dbg (("DRBG: additional information string too long %lu\n", ++ addtl->len)); ++ return ret; ++ } ++ /* 9.3.1 step 5 is implicit with the chosen DRBG */ ++ /* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a ++ * bit convoluted here, we make it simpler */ ++ if ((gcry_drbg_max_requests ()) < drbg->reseed_ctr) ++ drbg->seeded = 0; ++ ++ if (drbg->pr || !drbg->seeded) ++ { ++ dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded")); ++ /* 9.3.1 steps 7.1 through 7.3 */ ++ ret = gcry_drbg_seed (drbg, addtl, 1); ++ if (ret) ++ return ret; ++ /* 9.3.1 step 7.4 */ ++ addtl = NULL; ++ } ++ ++ if (addtl && addtl->buf) ++ { ++ dbg (("DRBG: using additional information string\n")); ++ } ++ ++ /* 9.3.1 step 8 and 10 */ ++ ret = drbg->d_ops->generate (drbg, buf, buflen, addtl); ++ ++ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ ++ drbg->reseed_ctr++; ++ if (ret) ++ return ret; ++ ++ /* 11.3.3 -- re-perform self tests after some generated random ++ * numbers, the chosen value after which self test is performed ++ * is arbitrary, but it should be reasonable */ ++ /* Here we do not perform the self tests because of the following ++ * reasons: it is mathematically impossible that the initial self tests ++ * were successfully and the following are not. If the initial would ++ * pass and the following would not, the system integrity is violated. ++ * In this case, the entire system operation is questionable and it ++ * is unlikely that the integrity violation only affects to the ++ * correct operation of the DRBG. ++ */ ++#if 0 ++ if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) ++ { ++ dbg (("DRBG: start to perform self test\n")); ++ ret = gcry_drbg_healthcheck (); ++ if (ret) ++ { ++ log_fatal (("DRBG: self test failed\n")); ++ return ret; ++ } ++ else ++ { ++ dbg (("DRBG: self test successful\n")); ++ } ++ } ++#endif ++ ++ return ret; ++} ++ ++/* ++ * Wrapper around gcry_drbg_generate which can pull arbitrary long strings ++ * from the DRBG without hitting the maximum request limitation. ++ * ++ * Parameters: see gcry_drbg_generate ++ * Return codes: see gcry_drbg_generate -- if one gcry_drbg_generate request fails, ++ * the entire gcry_drbg_generate_long request fails ++ */ ++static gpg_err_code_t ++gcry_drbg_generate_long (struct gcry_drbg_state *drbg, ++ unsigned char *buf, unsigned int buflen, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ unsigned int slice = 0; ++ unsigned char *buf_p = buf; ++ unsigned len = 0; ++ do ++ { ++ unsigned int chunk = 0; ++ slice = ((buflen - len) / gcry_drbg_max_request_bytes ()); ++ chunk = slice ? gcry_drbg_max_request_bytes () : (buflen - len); ++ ret = gcry_drbg_generate (drbg, buf_p, chunk, addtl); ++ if (ret) ++ return ret; ++ buf_p += chunk; ++ len += chunk; ++ } ++ while (slice > 0 && (len < buflen)); ++ return ret; ++} ++ ++/* ++ * DRBG uninstantiate function as required by SP800-90A - this function ++ * frees all buffers and the DRBG handle ++ * ++ * @drbg DRBG state handle ++ * ++ * return ++ * 0 on success ++ */ ++static gpg_err_code_t ++gcry_drbg_uninstantiate (struct gcry_drbg_state *drbg) ++{ ++ if (!drbg) ++ return GPG_ERR_INV_ARG; ++ xfree (drbg->V); ++ drbg->V = NULL; ++ xfree (drbg->C); ++ drbg->C = NULL; ++ drbg->reseed_ctr = 0; ++ xfree (drbg->scratchpad); ++ drbg->scratchpad = NULL; ++ drbg->seeded = 0; ++ drbg->pr = 0; ++ drbg->fips_primed = 0; ++ xfree (drbg->prev); ++ drbg->prev = NULL; ++ drbg->seed_init_pid = 0; ++ return 0; ++} ++ ++/* ++ * DRBG instantiation function as required by SP800-90A - this function ++ * sets up the DRBG handle, performs the initial seeding and all sanity ++ * checks required by SP800-90A ++ * ++ * @drbg memory of state -- if NULL, new memory is allocated ++ * @pers Personalization string that is mixed into state, may be NULL -- note ++ * the entropy is pulled by the DRBG internally unconditionally ++ * as defined in SP800-90A. The additional input is mixed into ++ * the state in addition to the pulled entropy. ++ * @coreref reference to core ++ * @flags Flags defining the requested DRBG type and cipher type. The flags ++ * are defined in drbg.h and may be XORed. Beware, if you XOR multiple ++ * cipher types together, the code picks the core on a first come first ++ * serve basis as it iterates through the available cipher cores and ++ * uses the one with the first match. The minimum required flags are: ++ * cipher type flag ++ * ++ * return ++ * 0 on success ++ * error value otherwise ++ */ ++static gpg_err_code_t ++gcry_drbg_instantiate (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *pers, int coreref, int pr) ++{ ++ gpg_err_code_t ret = GPG_ERR_ENOMEM; ++ unsigned int sb_size = 0; ++ ++ if (!drbg) ++ return GPG_ERR_INV_ARG; ++ ++ dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n", ++ coreref, pr ? "enabled" : "disabled")); ++ drbg->core = &gcry_drbg_cores[coreref]; ++ drbg->pr = pr; ++ drbg->seeded = 0; ++ if (drbg->core->flags & GCRY_DRBG_HMAC) ++ drbg->d_ops = &gcry_drbg_hmac_ops; ++ else if (drbg->core->flags & GCRY_DRBG_HASH_MASK) ++ drbg->d_ops = &gcry_drbg_hash_ops; ++ else if (drbg->core->flags & GCRY_DRBG_CTR_MASK) ++ drbg->d_ops = &gcry_drbg_ctr_ops; ++ else ++ return GPG_ERR_GENERAL; ++ /* 9.1 step 1 is implicit with the selected DRBG type -- see ++ * gcry_drbg_sec_strength() */ ++ ++ /* 9.1 step 2 is implicit as caller can select prediction resistance ++ * and the flag is copied into drbg->flags -- ++ * all DRBG types support prediction resistance */ ++ ++ /* 9.1 step 4 is implicit in gcry_drbg_sec_strength */ ++ ++ /* no allocation of drbg as this is done by the kernel crypto API */ ++ drbg->V = xcalloc_secure (1, gcry_drbg_statelen (drbg)); ++ if (!drbg->V) ++ goto err; ++ drbg->C = xcalloc_secure (1, gcry_drbg_statelen (drbg)); ++ if (!drbg->C) ++ goto err; ++ drbg->prev = xcalloc_secure (1, gcry_drbg_blocklen (drbg)); ++ if (!drbg->prev) ++ goto err; ++ drbg->fips_primed = 0; ++ /* scratchpad is only generated for CTR and Hash */ ++ if (drbg->core->flags & GCRY_DRBG_HMAC) ++ sb_size = 0; ++ else if (drbg->core->flags & GCRY_DRBG_CTR_MASK) ++ sb_size = gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg) + /* temp */ ++ gcry_drbg_statelen (drbg) + /* df_data */ ++ gcry_drbg_blocklen (drbg) + /* pad */ ++ gcry_drbg_blocklen (drbg) + /* iv */ ++ gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); /* temp */ ++ else ++ sb_size = gcry_drbg_statelen (drbg) + gcry_drbg_blocklen (drbg); ++ ++ if (0 < sb_size) ++ { ++ drbg->scratchpad = xcalloc_secure (1, sb_size); ++ if (!drbg->scratchpad) ++ goto err; ++ } ++ dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size)); ++ ++ /* 9.1 step 6 through 11 */ ++ ret = gcry_drbg_seed (drbg, pers, 0); ++ if (ret) ++ goto err; ++ ++ dbg (("DRBG: core %d %s prediction resistance successfully initialized\n", ++ coreref, pr ? "with" : "without")); ++ return 0; ++ ++err: ++ gcry_drbg_uninstantiate (drbg); ++ return ret; ++} ++ ++/* ++ * DRBG reseed function as required by SP800-90A ++ * ++ * @drbg DRBG state handle ++ * @addtl Additional input that is mixed into state, may be NULL -- note ++ * the entropy is pulled by the DRBG internally unconditionally ++ * as defined in SP800-90A. The additional input is mixed into ++ * the state in addition to the pulled entropy. ++ * ++ * return ++ * 0 on success ++ * error value otherwise ++ */ ++static gpg_err_code_t ++gcry_drbg_reseed (struct gcry_drbg_state *drbg, ++ struct gcry_drbg_string *addtl) ++{ ++ gpg_err_code_t ret = 0; ++ ret = gcry_drbg_seed (drbg, addtl, 1); ++ return ret; ++} ++ ++/****************************************************************** ++ ****************************************************************** ++ ****************************************************************** ++ * libgcrypt integration code ++ ****************************************************************** ++ ****************************************************************** ++ ******************************************************************/ ++ ++/*************************************************************** ++ * libgcrypt backend functions to the RNG API code ++ ***************************************************************/ ++ ++/* global state variable holding the current instance of the DRBG -- the ++ * default DRBG type is defined in _gcry_gcry_drbg_init */ ++static struct gcry_drbg_state *gcry_drbg = NULL; ++ ++/* This is the lock we use to serialize access to this RNG. */ ++static ath_mutex_t drbg_lock; ++ ++static inline void ++gcry_drbg_lock (void) ++{ ++ int my_errno; ++ ++ my_errno = ath_mutex_lock (&drbg_lock); ++ if (my_errno) ++ log_fatal ("failed to acquire the RNG lock: %s\n", strerror (my_errno)); ++} ++ ++static inline void ++gcry_drbg_unlock (void) ++{ ++ int my_errno; ++ ++ my_errno = ath_mutex_unlock (&drbg_lock); ++ if (my_errno) ++ log_fatal ("failed to release the RNG lock: %s\n", strerror (my_errno)); ++} ++ ++/* Basic initialization is required to initialize mutexes and ++ do a few checks on the implementation. */ ++static void ++basic_initialization (void) ++{ ++ static int initialized; ++ int my_errno; ++ ++ if (initialized) ++ return; ++ initialized = 1; ++ ++ my_errno = ath_mutex_init (&drbg_lock); ++ if (my_errno) ++ log_fatal ("failed to create the RNG lock: %s\n", strerror (my_errno)); ++} ++ ++/****** helper functions where lock must be held by caller *****/ ++ ++/* Check whether given flags are known to point to an applicable DRBG */ ++static gpg_err_code_t ++gcry_drbg_algo_available (u32 flags, int *coreref) ++{ ++ int i = 0; ++ for (i = 0; ARRAY_SIZE (gcry_drbg_cores) > i; i++) ++ { ++ if ((gcry_drbg_cores[i].flags & GCRY_DRBG_CIPHER_MASK) == ++ (flags & GCRY_DRBG_CIPHER_MASK)) ++ { ++ *coreref = i; ++ return 0; ++ } ++ } ++ return GPG_ERR_GENERAL; ++} ++ ++static gpg_err_code_t ++_gcry_drbg_init_internal (u32 flags, struct gcry_drbg_string *pers) ++{ ++ gpg_err_code_t ret = 0; ++ static u32 oldflags = 0; ++ int coreref = 0; ++ int pr = 0; ++ ++ /* If a caller provides 0 as flags, use the flags of the previous ++ * initialization, otherwise use the current flags and remember them ++ * for the next invocation ++ */ ++ if (0 == flags) ++ flags = oldflags; ++ else ++ oldflags = flags; ++ ++ ret = gcry_drbg_algo_available (flags, &coreref); ++ if (ret) ++ return ret; ++ ++ if (NULL != gcry_drbg) ++ { ++ gcry_drbg_uninstantiate (gcry_drbg); ++ } ++ else ++ { ++ gcry_drbg = xcalloc_secure (1, sizeof (struct gcry_drbg_state)); ++ if (!gcry_drbg) ++ return GPG_ERR_ENOMEM; ++ } ++ if (flags & GCRY_DRBG_PREDICTION_RESIST) ++ pr = 1; ++ ret = gcry_drbg_instantiate (gcry_drbg, pers, coreref, pr); ++ if (ret) ++ fips_signal_error ("DRBG cannot be initialized"); ++ else ++ gcry_drbg->seed_init_pid = getpid (); ++ return ret; ++} ++ ++/************* calls available to common RNG code **************/ ++ ++/* ++ * Initialize one DRBG invoked by the libgcrypt API ++ */ ++void ++_gcry_drbg_init (int full) ++{ ++ (void) full; /* ignore for now */ ++ /* default DRBG */ ++ u32 flags = GCRY_DRBG_NOPR_HMACSHA256; ++ basic_initialization (); ++ gcry_drbg_lock (); ++ _gcry_drbg_init_internal (flags, NULL); ++ gcry_drbg_unlock (); ++} ++ ++/* ++ * Backend handler function for GCRYCTL_DRBG_REINIT ++ * ++ * Select a different DRBG type and initialize it. ++ * Function checks whether requested DRBG type exists and returns an error in ++ * case it does not. In case of an error, the previous instantiated DRBG is ++ * left untouched and alive. Thus, in case of an error, a DRBG is always ++ * available, even if it is not the chosen one. ++ * ++ * Re-initialization will be performed in any case regardless whether flags ++ * or personalization string are set. ++ * ++ * If flags == 0, do not change current DRBG ++ * If personalization string is NULL or its length is 0, re-initialize without ++ * personalization string ++ */ ++gpg_err_code_t ++_gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers) ++{ ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags)); ++ gcry_drbg_lock (); ++ ret = _gcry_drbg_init_internal (flags, pers); ++ gcry_drbg_unlock (); ++ return ret; ++} ++ ++/* Print some statistics about the RNG. */ ++void ++_gcry_drbg_dump_stats (void) ++{ ++ /* Not yet implemented. */ ++ /* Maybe dumping of reseed counter? */ ++} ++ ++/* This function returns true if no real RNG is available or the ++ * quality of the RNG has been degraded for test purposes. */ ++int ++_gcry_drbg_is_faked (void) ++{ ++ return 0; /* Faked random is not allowed. */ ++} ++ ++/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY ++ * should be in the range of 0..100 to indicate the goodness of the ++ * entropy added, or -1 for goodness not known. */ ++gcry_error_t ++_gcry_drbg_add_bytes (const void *buf, size_t buflen, int quality) ++{ ++ gpg_err_code_t ret = 0; ++ struct gcry_drbg_string seed; ++ (void) quality; ++ if (NULL == gcry_drbg) ++ return GPG_ERR_GENERAL; ++ gcry_drbg_string_fill (&seed, (unsigned char *) buf, buflen); ++ gcry_drbg_lock (); ++ ret = gcry_drbg_reseed (gcry_drbg, &seed); ++ gcry_drbg_unlock (); ++ return ret; ++} ++ ++/* This function is to be used for all types of random numbers, including ++ * nonces ++ */ ++void ++_gcry_drbg_randomize (void *buffer, size_t length, ++ enum gcry_random_level level) ++{ ++ (void) level; ++ gcry_drbg_lock (); ++ if (NULL == gcry_drbg) ++ { ++ fips_signal_error ("DRBG is not initialized"); ++ goto bailout; ++ } ++ ++ /* As reseeding changes the entire state of the DRBG, including any ++ * key, either a re-init or a reseed is sufficient for a fork */ ++ if (gcry_drbg->seed_init_pid != getpid ()) ++ { ++ /* We are in a child of us. Perform a reseeding. */ ++ if (gcry_drbg_reseed (gcry_drbg, NULL)) ++ { ++ fips_signal_error ("reseeding upon fork failed"); ++ log_fatal ("severe error getting random\n"); ++ goto bailout; ++ } ++ gcry_drbg->seed_init_pid = getpid (); ++ } ++ /* potential integer overflow is covered by gcry_drbg_generate which ++ * ensures that length cannot overflow an unsigned int */ ++ if (0 < length) ++ { ++ if (!buffer) ++ goto bailout; ++ if (gcry_drbg_generate_long ++ (gcry_drbg, buffer, (unsigned int) length, NULL)) ++ log_fatal ("No random numbers generated\n"); ++ } ++ else ++ { ++ struct gcry_drbg_gen *data = (struct gcry_drbg_gen *) buffer; ++ /* catch NULL pointer */ ++ if (!data || !data->outbuf) ++ { ++ fips_signal_error ("No output buffer provided"); ++ goto bailout; ++ } ++ if (gcry_drbg_generate_long (gcry_drbg, data->outbuf, data->outlen, ++ data->addtl)) ++ log_fatal ("No random numbers generated\n"); ++ } ++bailout: ++ gcry_drbg_unlock (); ++ return; ++ ++} ++ ++/*************************************************************** ++ * Self-test code ++ ***************************************************************/ ++ ++/* ++ * Test vectors from ++ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip ++ */ ++struct gcry_drbg_test_vector gcry_drbg_test_pr[] = { ++ { ++ .flags = (GCRY_DRBG_PR_HASHSHA256), ++ .entropy = (unsigned char *) ++ "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d" ++ "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0" ++ "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1" ++ "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6", ++ .entropylen = 48, ++ .entpra = (unsigned char *) ++ "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb" ++ "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13" ++ "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15", ++ .entprb = (unsigned char *) ++ "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09" ++ "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde" ++ "\x76\xaa\x55\x04\x8b\x0a\x72\x95", ++ .entprlen = 32, ++ .expected = (unsigned char *) ++ "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32" ++ "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c" ++ "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18" ++ "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb" ++ "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81" ++ "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4" ++ "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6" ++ "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13" ++ "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9" ++ "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60" ++ "\x50\x47\xa3\x63\x81\x16\xaf\x19", ++ .expectedlen = 128, ++ .addtla = (unsigned char *) ++ "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d" ++ "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad" ++ "\xa9\xd0\x1d\x59\x02\xc4\xff\x70", ++ .addtlb = (unsigned char *) ++ "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31" ++ "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41" ++ "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd", ++ .addtllen = 32, ++ .pers = NULL, ++ .perslen = 0, ++ }, ++ { ++ .flags = (GCRY_DRBG_PR_HMACSHA256), ++ .entropy = (unsigned char *) ++ "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89" ++ "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf" ++ "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20" ++ "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67", ++ .entropylen = 48, ++ .entpra = (unsigned char *) ++ "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79" ++ "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57" ++ "\x20\x28\xad\xf2\x60\xd7\xcd\x45", ++ .entprb = (unsigned char *) ++ "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71" ++ "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66" ++ "\x1f\xfa\x74\xd3\xac\xa6\x74\x60", ++ .entprlen = 32, ++ .expected = (unsigned char *) ++ "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99" ++ "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3" ++ "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75" ++ "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61" ++ "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88" ++ "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e" ++ "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c" ++ "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce" ++ "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc" ++ "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc" ++ "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3", ++ .expectedlen = 128, ++ .addtla = NULL, ++ .addtlb = NULL, ++ .addtllen = 0, ++ .pers = (unsigned char *) ++ "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f" ++ "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce" ++ "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa", ++ .perslen = 32, ++ }, ++ { ++ .flags = (GCRY_DRBG_PR_CTRAES128), ++ .entropy = (unsigned char *) ++ "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06" ++ "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97", ++ .entropylen = 24, ++ .entpra = (unsigned char *) ++ "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7" ++ "\xc4\x2c\xe8\x10", ++ .entprb = (unsigned char *) ++ "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22" ++ "\x08\xf7\xa5\x01", ++ .entprlen = 16, ++ .expected = (unsigned char *) ++ "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71" ++ "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28" ++ "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45" ++ "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08" ++ "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4" ++ "\x23\xc5\x1f\x68", ++ .expectedlen = 64, ++ .addtla = (unsigned char *) ++ "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59" ++ "\x23\x6d\xad\x1d", ++ .addtlb = (unsigned char *) ++ "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12" ++ "\xbc\x59\x31\x8c", ++ .addtllen = 16, ++ .pers = (unsigned char *) ++ "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4" ++ "\x37\x3c\x5c\x0b", ++ .perslen = 16, ++ }, ++}; ++ ++struct gcry_drbg_test_vector gcry_drbg_test_nopr[] = { ++ { ++ .flags = GCRY_DRBG_NOPR_HASHSHA256, ++ .entropy = (unsigned char *) ++ "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c" ++ "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d" ++ "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff" ++ "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56", ++ .entropylen = 48, ++ .expected = (unsigned char *) ++ "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7" ++ "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b" ++ "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0" ++ "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8" ++ "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f" ++ "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d" ++ "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59" ++ "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b" ++ "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0" ++ "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c" ++ "\x70\xa8\x07\x59\x97\xeb\xf6\xbe", ++ .expectedlen = 128, ++ .addtla = (unsigned char *) ++ "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73" ++ "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10" ++ "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd", ++ .addtlb = (unsigned char *) ++ "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0" ++ "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d" ++ "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40", ++ .addtllen = 32, ++ .pers = NULL, ++ .perslen = 0, ++ }, ++ { ++ .flags = GCRY_DRBG_NOPR_HMACSHA256, ++ .entropy = (unsigned char *) ++ "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf" ++ "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54" ++ "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf" ++ "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e", ++ .entropylen = 48, ++ .expected = (unsigned char *) ++ "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81" ++ "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37" ++ "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10" ++ "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61" ++ "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28" ++ "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f" ++ "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07" ++ "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66" ++ "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2" ++ "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29" ++ "\x10\x37\x41\x03\x0c\xcc\x3a\x56", ++ .expectedlen = 128, ++ .addtla = NULL, ++ .addtlb = NULL, ++ .addtllen = 0, ++ .pers = (unsigned char *) ++ "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37" ++ "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58" ++ "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9", ++ .perslen = 32, ++ }, ++ { ++ .flags = GCRY_DRBG_NOPR_CTRAES128, ++ .entropy = (unsigned char *) ++ "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98" ++ "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6", ++ .entropylen = 24, ++ .expected = (unsigned char *) ++ "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a" ++ "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95" ++ "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f" ++ "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a" ++ "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a" ++ "\x2b\x49\x1e\x5c", ++ .expectedlen = 64, ++ .addtla = (unsigned char *) ++ "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2" ++ "\x44\x85\xe7\xfe", ++ .addtlb = (unsigned char *) ++ "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4" ++ "\x82\x16\x62\x7f", ++ .addtllen = 16, ++ .pers = (unsigned char *) ++ "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f" ++ "\x8e\xcf\xe0\x02", ++ .perslen = 16, ++ }, ++}; ++ ++ ++/* ++ * Tests implement the CAVS test approach as documented in ++ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf ++ */ ++ ++/* ++ * CAVS test ++ * ++ * This function is not static as it is needed for as a private API ++ * call for the CAVS test tool. ++ */ ++gpg_err_code_t ++gcry_drbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf) ++{ ++ gpg_err_code_t ret = 0; ++ struct gcry_drbg_state *drbg = NULL; ++ struct gcry_drbg_test_data test_data; ++ struct gcry_drbg_string addtl, pers, testentropy; ++ int coreref = 0; ++ int pr = 0; ++ ++ ret = gcry_drbg_algo_available (test->flags, &coreref); ++ if (ret) ++ goto outbuf; ++ ++ drbg = gcry_xcalloc (1, sizeof (struct gcry_drbg_state)); ++ if (!drbg) ++ { ++ ret = GPG_ERR_ENOMEM; ++ goto outbuf; ++ } ++ ++ if (test->flags & GCRY_DRBG_PREDICTION_RESIST) ++ pr = 1; ++ ++ test_data.testentropy = &testentropy; ++ gcry_drbg_string_fill (&testentropy, test->entropy, test->entropylen); ++ drbg->test_data = &test_data; ++ gcry_drbg_string_fill (&pers, test->pers, test->perslen); ++ ret = gcry_drbg_instantiate (drbg, &pers, coreref, pr); ++ if (ret) ++ goto outbuf; ++ ++ gcry_drbg_string_fill (&addtl, test->addtla, test->addtllen); ++ if (test->entpra) ++ { ++ gcry_drbg_string_fill (&testentropy, test->entpra, test->entprlen); ++ drbg->test_data = &test_data; ++ } ++ gcry_drbg_generate_long (drbg, buf, test->expectedlen, &addtl); ++ ++ gcry_drbg_string_fill (&addtl, test->addtlb, test->addtllen); ++ if (test->entprb) ++ { ++ gcry_drbg_string_fill (&testentropy, test->entprb, test->entprlen); ++ drbg->test_data = &test_data; ++ } ++ gcry_drbg_generate_long (drbg, buf, test->expectedlen, &addtl); ++ gcry_drbg_uninstantiate (drbg); ++ ++outbuf: ++ xfree (drbg); ++ return ret; ++} ++ ++/* ++ * Invoke the CAVS test and perform the final check whether the ++ * calculated random value matches the expected one. ++ * ++ * This function is not static as it is needed for as a private API ++ * call for the CAVS test tool. ++ */ ++gpg_err_code_t ++gcry_drbg_healthcheck_one (struct gcry_drbg_test_vector * test) ++{ ++ gpg_err_code_t ret = GPG_ERR_ENOMEM; ++ unsigned char *buf = gcry_xcalloc (1, test->expectedlen); ++ if (!buf) ++ return GPG_ERR_ENOMEM; ++ ++ ret = gcry_drbg_cavs_test (test, buf); ++ ret = memcmp (test->expected, buf, test->expectedlen); ++ ++ xfree (buf); ++ return ret; ++} ++ ++/* ++ * Tests as defined in 11.3.2 in addition to the cipher tests: testing ++ * of the error handling. ++ * ++ * Note, testing the reseed counter is not done as an automatic reseeding ++ * is performed in gcry_drbg_generate when the reseed counter is too large. ++ */ ++static gpg_err_code_t ++gcry_drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test) ++{ ++ unsigned int len = 0; ++ struct gcry_drbg_state *drbg = NULL; ++ gpg_err_code_t ret = GPG_ERR_GENERAL; ++ gpg_err_code_t tmpret = GPG_ERR_GENERAL; ++ struct gcry_drbg_test_data test_data; ++ struct gcry_drbg_string addtl, testentropy; ++ int coreref = 0; ++ unsigned char *buf = NULL; ++ size_t max_addtllen, max_request_bytes; ++ ++ /* only perform test in FIPS mode */ ++ if (0 == fips_mode ()) ++ return 0; ++ ++ buf = gcry_xcalloc (1, test->expectedlen); ++ if (!buf) ++ return GPG_ERR_ENOMEM; ++ tmpret = gcry_drbg_algo_available (test->flags, &coreref); ++ if (tmpret) ++ goto outbuf; ++ drbg = gcry_xcalloc (1, sizeof (struct gcry_drbg_state)); ++ if (!drbg) ++ goto outbuf; ++ ++ /* if the following tests fail, it is likely that there is a buffer ++ * overflow and we get a SIGSEV */ ++ ret = gcry_drbg_instantiate (drbg, NULL, coreref, 1); ++ if (ret) ++ goto outbuf; ++ max_addtllen = gcry_drbg_max_addtl (); ++ max_request_bytes = gcry_drbg_max_request_bytes (); ++ /* overflow addtllen with additonal info string */ ++ gcry_drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1)); ++ len = gcry_drbg_generate (drbg, buf, test->expectedlen, &addtl); ++ if (len) ++ goto outdrbg; ++ ++ /* overflow max_bits */ ++ len = gcry_drbg_generate (drbg, buf, (max_request_bytes + 1), NULL); ++ if (len) ++ goto outdrbg; ++ gcry_drbg_uninstantiate (drbg); ++ ++ /* test failing entropy source as defined in 11.3.2 */ ++ test_data.testentropy = NULL; ++ test_data.fail_seed_source = 1; ++ drbg->test_data = &test_data; ++ tmpret = gcry_drbg_instantiate (drbg, NULL, coreref, 0); ++ if (!tmpret) ++ goto outdrbg; ++ test_data.fail_seed_source = 0; ++ ++ test_data.testentropy = &testentropy; ++ gcry_drbg_string_fill (&testentropy, test->entropy, test->entropylen); ++ /* overflow max addtllen with personalization string */ ++ tmpret = gcry_drbg_instantiate (drbg, &addtl, coreref, 0); ++ if (!tmpret) ++ goto outdrbg; ++ ++ dbg (("DRBG: Sanity tests for failure code paths successfully completed\n")); ++ ret = 0; ++ ++outdrbg: ++ gcry_drbg_uninstantiate (drbg); ++outbuf: ++ xfree (buf); ++ xfree (drbg); ++ return ret; ++} ++ ++/* ++ * DRBG Healthcheck function as required in SP800-90A ++ * ++ * return: ++ * 0 on success (all tests pass) ++ * >0 on error (return code indicate the number of failures) ++ */ ++static int ++gcry_drbg_healthcheck (void) ++{ ++ int ret = 0; ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[0]); ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[1]); ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_nopr[2]); ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[0]); ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[1]); ++ ret += gcry_drbg_healthcheck_one (&gcry_drbg_test_pr[2]); ++ ret += gcry_drbg_healthcheck_sanity (&gcry_drbg_test_nopr[0]); ++ return ret; ++} ++ ++/* Run the self-tests. */ ++gcry_error_t ++_gcry_drbg_selftest (selftest_report_func_t report) ++{ ++ gcry_err_code_t ec; ++ const char *errtxt = NULL; ++ gcry_drbg_lock (); ++ if (0 != gcry_drbg_healthcheck ()) ++ errtxt = "RNG output does not match known value"; ++ gcry_drbg_unlock (); ++ if (report && errtxt) ++ report ("random", 0, "KAT", errtxt); ++ ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0; ++ return gpg_error (ec); ++} ++ ++/*************************************************************** ++ * Cipher invocations requested by DRBG ++ ***************************************************************/ ++ ++static gpg_err_code_t ++gcry_drbg_hmac (struct gcry_drbg_state *drbg, const unsigned char *key, ++ unsigned char *outval, const struct gcry_drbg_string *buf) ++{ ++ gpg_error_t err; ++ gcry_md_hd_t hd; ++ ++ if (key) ++ { ++ err = ++ _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC); ++ if (err) ++ return err; ++ err = _gcry_md_setkey (hd, key, gcry_drbg_statelen (drbg)); ++ if (err) ++ return err; ++ } ++ else ++ { ++ err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0); ++ if (err) ++ return err; ++ } ++ for (; NULL != buf; buf = buf->next) ++ _gcry_md_write (hd, buf->buf, buf->len); ++ gcry_md_final (hd); ++ memcpy (outval, _gcry_md_read (hd, drbg->core->backend_cipher), ++ gcry_drbg_blocklen (drbg)); ++ _gcry_md_close (hd); ++ return 0; ++} ++ ++static gpg_err_code_t ++gcry_drbg_sym (struct gcry_drbg_state *drbg, const unsigned char *key, ++ unsigned char *outval, const struct gcry_drbg_string *buf) ++{ ++ gpg_error_t err; ++ gcry_cipher_hd_t hd; ++ ++ if (gcry_drbg_blocklen (drbg) != ++ _gcry_cipher_get_algo_blklen (drbg->core->backend_cipher)) ++ return -GPG_ERR_NO_ERROR; ++ if (gcry_drbg_blocklen (drbg) < buf->len) ++ return -GPG_ERR_NO_ERROR; ++ err = ++ _gcry_cipher_open (&hd, drbg->core->backend_cipher, GCRY_CIPHER_MODE_ECB, ++ 0); ++ if (err) ++ return err; ++ err = _gcry_cipher_setkey (hd, key, gcry_drbg_keylen (drbg)); ++ if (err) ++ { ++ _gcry_cipher_close (hd); ++ return err; ++ } ++ /* in is only component */ ++ _gcry_cipher_encrypt (hd, outval, gcry_drbg_blocklen (drbg), buf->buf, ++ buf->len); ++ _gcry_cipher_close (hd); ++ return 0; ++} +diff -up libgcrypt-1.5.3/random/Makefile.am.drbg libgcrypt-1.5.3/random/Makefile.am +--- libgcrypt-1.5.3/random/Makefile.am.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/random/Makefile.am 2014-09-26 17:00:16.051215890 +0200 +@@ -35,6 +35,7 @@ random.c random.h \ + rand-internal.h \ + random-csprng.c \ + random-fips.c \ ++drbg.c \ + rndhw.c + + if USE_RANDOM_DAEMON +diff -up libgcrypt-1.5.3/random/Makefile.in.drbg libgcrypt-1.5.3/random/Makefile.in +--- libgcrypt-1.5.3/random/Makefile.in.drbg 2013-07-25 11:22:44.000000000 +0200 ++++ libgcrypt-1.5.3/random/Makefile.in 2014-09-26 17:00:16.051215890 +0200 +@@ -91,10 +91,10 @@ CONFIG_CLEAN_VPATH_FILES = + LTLIBRARIES = $(noinst_LTLIBRARIES) + am__DEPENDENCIES_1 = + am__librandom_la_SOURCES_DIST = random.c random.h rand-internal.h \ +- random-csprng.c random-fips.c rndhw.c random-daemon.c ++ random-csprng.c random-fips.c drbg.c rndhw.c random-daemon.c + @USE_RANDOM_DAEMON_TRUE@am__objects_1 = random-daemon.lo + am_librandom_la_OBJECTS = random.lo random-csprng.lo random-fips.lo \ +- rndhw.lo $(am__objects_1) ++ drbg.lo rndhw.lo $(am__objects_1) + librandom_la_OBJECTS = $(am_librandom_la_OBJECTS) + DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) + depcomp = $(SHELL) $(top_srcdir)/depcomp +@@ -283,7 +283,7 @@ GCRYPT_MODULES = @GCRYPT_RANDOM@ + librandom_la_DEPENDENCIES = $(GCRYPT_MODULES) + librandom_la_LIBADD = $(GCRYPT_MODULES) + librandom_la_SOURCES = random.c random.h rand-internal.h \ +- random-csprng.c random-fips.c rndhw.c $(am__append_1) ++ random-csprng.c random-fips.c drbg.c rndhw.c $(am__append_1) + EXTRA_librandom_la_SOURCES = \ + rndlinux.c \ + rndegd.c \ +@@ -346,6 +346,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-csprng.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-daemon.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-fips.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drbg.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndegd.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndhw.Plo@am__quote@ +diff -up libgcrypt-1.5.3/random/rand-internal.h.drbg libgcrypt-1.5.3/random/rand-internal.h +--- libgcrypt-1.5.3/random/rand-internal.h.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/random/rand-internal.h 2014-09-26 17:00:16.051215890 +0200 +@@ -91,6 +91,15 @@ gcry_err_code_t _gcry_rngfips_run_extern + char *buffer, size_t buflen); + void _gcry_rngfips_deinit_external_test (void *context); + ++/* drbg-gcry.h */ ++void _gcry_drbg_init(int full); ++void _gcry_drbg_close_fds(void); ++void _gcry_drbg_dump_stats(void); ++int _gcry_drbg_is_faked (void); ++gcry_error_t _gcry_drbg_add_bytes (const void *buf, size_t buflen, int quality); ++void _gcry_drbg_randomize (void *buffer, size_t length, ++ enum gcry_random_level level); ++gcry_error_t _gcry_drbg_selftest (selftest_report_func_t report); + + + +diff -up libgcrypt-1.5.3/random/random.c.drbg libgcrypt-1.5.3/random/random.c +--- libgcrypt-1.5.3/random/random.c.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/random/random.c 2014-09-26 17:00:16.051215890 +0200 +@@ -76,7 +76,7 @@ void + _gcry_random_initialize (int full) + { + if (fips_mode ()) +- _gcry_rngfips_initialize (full); ++ _gcry_drbg_init (full); + else + _gcry_rngcsprng_initialize (full); + } +@@ -86,7 +86,7 @@ void + _gcry_random_dump_stats (void) + { + if (fips_mode ()) +- _gcry_rngfips_dump_stats (); ++ _gcry_drbg_dump_stats (); + else + _gcry_rngcsprng_dump_stats (); + } +@@ -145,7 +145,7 @@ int + _gcry_random_is_faked (void) + { + if (fips_mode ()) +- return _gcry_rngfips_is_faked (); ++ return _gcry_drbg_is_faked (); + else + return _gcry_rngcsprng_is_faked (); + } +@@ -169,7 +169,7 @@ static void + do_randomize (void *buffer, size_t length, enum gcry_random_level level) + { + if (fips_mode ()) +- _gcry_rngfips_randomize (buffer, length, level); ++ _gcry_drbg_randomize (buffer, length, level); + else + _gcry_rngcsprng_randomize (buffer, length, level); + } +@@ -266,7 +266,7 @@ void + gcry_create_nonce (void *buffer, size_t length) + { + if (fips_mode ()) +- _gcry_rngfips_create_nonce (buffer, length); ++ _gcry_drbg_randomize (buffer, length, GCRY_WEAK_RANDOM); + else + _gcry_rngcsprng_create_nonce (buffer, length); + } +@@ -278,7 +278,7 @@ gpg_error_t + _gcry_random_selftest (selftest_report_func_t report) + { + if (fips_mode ()) +- return _gcry_rngfips_selftest (report); ++ return _gcry_drbg_selftest (report); + else + return 0; /* No selftests yet. */ + } +@@ -294,13 +294,7 @@ _gcry_random_init_external_test (void ** + const void *seed, size_t seedlen, + const void *dt, size_t dtlen) + { +- (void)flags; +- if (fips_mode ()) +- return _gcry_rngfips_init_external_test (r_context, flags, key, keylen, +- seed, seedlen, +- dt, dtlen); +- else +- return GPG_ERR_NOT_SUPPORTED; ++ return GPG_ERR_NOT_SUPPORTED; + } + + /* Get BUFLEN bytes from the RNG using the test CONTEXT and store them +@@ -308,16 +302,12 @@ _gcry_random_init_external_test (void ** + gcry_err_code_t + _gcry_random_run_external_test (void *context, char *buffer, size_t buflen) + { +- if (fips_mode ()) +- return _gcry_rngfips_run_external_test (context, buffer, buflen); +- else +- return GPG_ERR_NOT_SUPPORTED; ++ return GPG_ERR_NOT_SUPPORTED; + } + + /* Release the test CONTEXT. */ + void + _gcry_random_deinit_external_test (void *context) + { +- if (fips_mode ()) +- _gcry_rngfips_deinit_external_test (context); ++ return; + } +diff -up libgcrypt-1.5.3/random/random.h.drbg libgcrypt-1.5.3/random/random.h +--- libgcrypt-1.5.3/random/random.h.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/random/random.h 2014-09-26 17:00:16.051215890 +0200 +@@ -51,7 +51,29 @@ gcry_err_code_t _gcry_random_run_externa + char *buffer, size_t buflen); + void _gcry_random_deinit_external_test (void *context); + ++/*-- drbg.c --*/ ++gpg_err_code_t _gcry_drbg_reinit (u32 flags, struct gcry_drbg_string *pers); ++/* private interfaces for testing of DRBG */ ++struct gcry_drbg_test_vector ++{ ++ u32 flags; ++ unsigned char *entropy; ++ size_t entropylen; ++ unsigned char *entpra; ++ unsigned char *entprb; ++ size_t entprlen; ++ unsigned char *addtla; ++ unsigned char *addtlb; ++ size_t addtllen; ++ unsigned char *pers; ++ size_t perslen; ++ unsigned char *expected; ++ size_t expectedlen; ++}; + ++gpg_err_code_t gcry_drbg_cavs_test (struct gcry_drbg_test_vector *test, ++ unsigned char *buf); ++gpg_err_code_t gcry_drbg_healthcheck_one (struct gcry_drbg_test_vector *test); + /*-- rndegd.c --*/ + gpg_error_t _gcry_rndegd_set_socket_name (const char *name); + +diff -up libgcrypt-1.5.3/src/gcrypt.h.in.drbg libgcrypt-1.5.3/src/gcrypt.h.in +--- libgcrypt-1.5.3/src/gcrypt.h.in.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/src/gcrypt.h.in 2014-09-26 17:16:30.965224999 +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_DRBG_REINIT = 74 ++ /* Note: 75 is used internally */ + }; + + /* Perform various operations defined by CMD. */ +@@ -1907,6 +1909,109 @@ int gcry_is_secure (const void *a) _GCRY + /* Return true if Libgcrypt is in FIPS mode. */ + #define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0) + ++/* DRBG input data structure for DRBG generate with additional information ++ * string */ ++struct gcry_drbg_gen { ++ unsigned char *outbuf; /* output buffer for random numbers */ ++ unsigned int outlen; /* size of output buffer */ ++ struct gcry_drbg_string *addtl; /* input buffer for ++ * additional information string */ ++}; ++ ++/* ++ * Concatenation Helper and string operation helper ++ * ++ * SP800-90A requires the concatenation of different data. To avoid copying ++ * buffers around or allocate additional memory, the following data structure ++ * is used to point to the original memory with its size. In addition, it ++ * is used to build a linked list. The linked list defines the concatenation ++ * of individual buffers. The order of memory block referenced in that ++ * linked list determines the order of concatenation. ++ */ ++/* DRBG string definition */ ++struct gcry_drbg_string { ++ const unsigned char *buf; ++ size_t len; ++ struct gcry_drbg_string *next; ++}; ++ ++#define gcry_drbg_string_fill(s, b, l) \ ++do { \ ++ (s)->buf = (b); \ ++ (s)->len = (l); \ ++ (s)->next = NULL; \ ++} while (0) ++ ++/* this is a wrapper function for users of libgcrypt */ ++#define gcry_randomize_drbg(ob, ol, lvl, add) \ ++do { \ ++ struct gcry_drbg_gen genbuf; \ ++ genbuf.outbuf = (unsigned char *)(ob); \ ++ genbuf.outlen = (ol); \ ++ genbuf.addtl = (add); \ ++ gcry_randomize(&genbuf, 0, (lvl)); \ ++} while (0) ++ ++/* ++ * DRBG flags bitmasks ++ * ++ * 31 (B) 28 19 (A) 0 ++ * +-+-+-+--------+---+-----------+-----+ ++ * |~|~|u|~~~~~~~~| 3 | 2 | 1 | ++ * +-+-+-+--------+- -+-----------+-----+ ++ * ctl flg| |drbg use selection flags ++ * ++ */ ++ ++/* internal state control flags (B) */ ++#define GCRY_DRBG_PREDICTION_RESIST ((u_int32_t)1<<28) ++ ++/* CTR type modifiers (A.1)*/ ++#define GCRY_DRBG_CTRAES ((u_int32_t)1<<0) ++#define GCRY_DRBG_CTRSERPENT ((u_int32_t)1<<1) ++#define GCRY_DRBG_CTRTWOFISH ((u_int32_t)1<<2) ++#define GCRY_DRBG_CTR_MASK (GCRY_DRBG_CTRAES | GCRY_DRBG_CTRSERPENT | GCRY_DRBG_CTRTWOFISH) ++ ++/* HASH type modifiers (A.2)*/ ++#define GCRY_DRBG_HASHSHA1 ((u_int32_t)1<<4) ++#define GCRY_DRBG_HASHSHA224 ((u_int32_t)1<<5) ++#define GCRY_DRBG_HASHSHA256 ((u_int32_t)1<<6) ++#define GCRY_DRBG_HASHSHA384 ((u_int32_t)1<<7) ++#define GCRY_DRBG_HASHSHA512 ((u_int32_t)1<<8) ++#define GCRY_DRBG_HASH_MASK (GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HASHSHA224 | \ ++ GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HASHSHA384 | \ ++ GCRY_DRBG_HASHSHA512) ++/* type modifiers (A.3)*/ ++#define GCRY_DRBG_HMAC ((u_int32_t)1<<12) ++#define GCRY_DRBG_SYM128 ((u_int32_t)1<<13) ++#define GCRY_DRBG_SYM192 ((u_int32_t)1<<14) ++#define GCRY_DRBG_SYM256 ((u_int32_t)1<<15) ++#define GCRY_DRBG_TYPE_MASK (GCRY_DRBG_HMAC | GCRY_DRBG_SYM128 | GCRY_DRBG_SYM192 | \ ++ GCRY_DRBG_SYM256) ++#define GCRY_DRBG_CIPHER_MASK (GCRY_DRBG_CTR_MASK | GCRY_DRBG_HASH_MASK | GCRY_DRBG_TYPE_MASK) ++ ++#define GCRY_DRBG_PR_CTRAES128 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128) ++#define GCRY_DRBG_PR_CTRAES192 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192) ++#define GCRY_DRBG_PR_CTRAES256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256) ++#define GCRY_DRBG_NOPR_CTRAES128 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM128) ++#define GCRY_DRBG_NOPR_CTRAES192 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM192) ++#define GCRY_DRBG_NOPR_CTRAES256 (GCRY_DRBG_CTRAES | GCRY_DRBG_SYM256) ++#define GCRY_DRBG_PR_HASHSHA1 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA1) ++#define GCRY_DRBG_PR_HASHSHA256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA256) ++#define GCRY_DRBG_PR_HASHSHA384 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA384) ++#define GCRY_DRBG_PR_HASHSHA512 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA512) ++#define GCRY_DRBG_NOPR_HASHSHA1 (GCRY_DRBG_HASHSHA1) ++#define GCRY_DRBG_NOPR_HASHSHA256 (GCRY_DRBG_HASHSHA256) ++#define GCRY_DRBG_NOPR_HASHSHA384 (GCRY_DRBG_HASHSHA384) ++#define GCRY_DRBG_NOPR_HASHSHA512 (GCRY_DRBG_HASHSHA512) ++#define GCRY_DRBG_PR_HMACSHA1 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_PR_HMACSHA256 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_PR_HMACSHA384 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_PR_HMACSHA512 (GCRY_DRBG_PREDICTION_RESIST | GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_NOPR_HMACSHA1 (GCRY_DRBG_HASHSHA1 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_NOPR_HMACSHA256 (GCRY_DRBG_HASHSHA256 | GCRY_DRBG_HMAC) ++#define GCRY_DRBG_NOPR_HMACSHA384 (GCRY_DRBG_HASHSHA384 | GCRY_DRBG_HMAC) ++#define DRBG_NOPR_HMACSHA512 (GCRY_DRBG_HASHSHA512 | GCRY_DRBG_HMAC) + + /* Include support for Libgcrypt modules. */ + #include +diff -up libgcrypt-1.5.3/src/global.c.drbg libgcrypt-1.5.3/src/global.c +--- libgcrypt-1.5.3/src/global.c.drbg 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/src/global.c 2014-09-26 17:00:16.052215913 +0200 +@@ -609,6 +609,28 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + err = GPG_ERR_GENERAL; + break; + ++ case GCRYCTL_DRBG_REINIT: ++ { ++ u32 flags = va_arg (arg_ptr, u32); ++ struct gcry_drbg_string *pers = va_arg (arg_ptr, ++ struct gcry_drbg_string *); ++ err = _gcry_drbg_reinit(flags, pers); ++ } ++ break; ++ ++ case 75: ++ { ++ struct gcry_drbg_test_vector *test = ++ va_arg (arg_ptr, struct gcry_drbg_test_vector *); ++ unsigned char *buf = va_arg (arg_ptr, unsigned char *); ++ ++ if (buf) ++ err = gcry_drbg_cavs_test (test, buf); ++ else ++ err = gcry_drbg_healthcheck_one (test); ++ } ++ break; ++ + default: + err = GPG_ERR_INV_OP; + } diff --git a/SOURCES/libgcrypt-1.5.3-fips-cavs.patch b/SOURCES/libgcrypt-1.5.3-fips-cavs.patch new file mode 100644 index 0000000..5cbe8b8 --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-fips-cavs.patch @@ -0,0 +1,1451 @@ +diff -up libgcrypt-1.5.3/cipher/dsa.c.cavs libgcrypt-1.5.3/cipher/dsa.c +--- libgcrypt-1.5.3/cipher/dsa.c.cavs 2014-09-26 17:45:38.429674771 +0200 ++++ libgcrypt-1.5.3/cipher/dsa.c 2014-09-26 17:45:38.433674862 +0200 +@@ -479,7 +479,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, +@@ -487,13 +486,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; +@@ -784,13 +792,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.5.3/tests/cavs_driver.pl.cavs libgcrypt-1.5.3/tests/cavs_driver.pl +--- libgcrypt-1.5.3/tests/cavs_driver.pl.cavs 2013-05-22 18:02:55.000000000 +0200 ++++ libgcrypt-1.5.3/tests/cavs_driver.pl 2014-10-21 09:38:34.250691408 +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 ++# 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,16 +305,30 @@ 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 + # return: hash of digest information in hex format with Y, R, S as keys + my $dsa_sign; + ++my $rsa_keygen; ++ ++my $rsa_keygen_kat; ++ + ################################################################ + ##### OpenSSL interface functions + ################################################################ +@@ -404,6 +468,35 @@ sub libgcrypt_rsa_derive($$$$$$$$) { + } + + ++sub libgcrypt_rsa_keygen($) { ++ my $n = shift; ++ my $sexp; ++ ++ $n = sprintf ("%u", $n); ++ $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")))\n"; ++ ++ return pipe_through_program($sexp, "fipsdrv rsa-keygen"); ++} ++ ++ ++sub libgcrypt_rsa_keygen_kat($$$$) { ++ my $n = shift; ++ my $e = shift; ++ my $p = shift; ++ my $q = shift; ++ my $sexp; ++ ++ $n = sprintf ("%u", $n); ++ $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")" ++ . "(test-parms" ++ . "(e #$e#)" ++ . "(p #$p#)" ++ . "(q #$q#))))\n"; ++ ++ return pipe_through_program($sexp, "fipsdrv rsa-keygen-kat"); ++} ++ ++ + sub libgcrypt_rsa_sign($$$) { + my $data = shift; + my $hashalgo = shift; +@@ -500,17 +593,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 +627,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 +1258,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 +1324,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 +1332,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 +1357,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; + +@@ -1429,7 +1552,7 @@ sub rsa_sigver($$$$$) { + # $7 xq2 + # $8 Xq + # return: string formatted as expected by CAVS +-sub rsa_keygen($$$$$$$$) { ++sub rsa_keygen_x931($$$$$$$$) { + my $modulus = shift; + my $e = shift; + my $xp1 = shift; +@@ -1503,21 +1626,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 +1650,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 +@@ -1598,6 +1874,53 @@ sub dsa_sigver($$$$$$$$) { + return $out; + } + ++# RSA Keygen RPP test ++# $1 modulus size ++# $2 number of rounds to perform the test ++# return: string formatted as expected by CAVS ++sub rsa_keygen_driver($$) { ++ my $mod = shift; ++ my $rounds = shift; ++ ++ my $out = ""; ++ ++ for(my $i=0; $i<$rounds; $i++) { ++ my $ret = &$rsa_keygen($mod); ++ my ($e, $p, $q, $n, $d) = split(/\n/, $ret); ++ die "Return value does not contain all expected values of e, p, q, n, d for rsa_keygen" ++ if (!defined($e) || !defined($p) || !defined($q) || !defined($n) || !defined($d)); ++ ++ $out .= "e = $e\n"; ++ $out .= "p = $p\n"; ++ $out .= "q = $q\n"; ++ $out .= "n = $n\n"; ++ $out .= "d = $d\n\n"; ++ } ++ ++ return $out; ++} ++ ++# RSA RPP Keygen KAT test ++# $1 modulus size ++# $2 p in hex form ++# $3 q in hex form ++# return: string formatted as expected by CAVS ++sub rsa_keygen_kat_driver($$$) { ++ my $mod = shift; ++ my $p = shift; ++ my $q = shift; ++ ++ my $out = ""; ++ my $ret = &$rsa_keygen_kat($mod, $p, $q); ++ my ($Result) = split(/\n/, $ret); ++ die "Return value does not contain all expected values of Result for rsa_keygen_kat" ++ if (!defined($Result)); ++ ++ $out .= "Result = $Result\n\n"; ++ return $out; ++} ++ ++ + ############################################################## + # Parser of input file and generator of result file + # +@@ -1658,12 +1981,18 @@ 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 $prandom = ""; ++ my $qrandom = ""; + my $xp1 = ""; + my $xp2 = ""; + my $Xp = ""; +@@ -1700,7 +2029,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|KeyGen - Random Probably Prime|KeyPair|PQGVer)/) { + if ($tmpline =~ /CBC/) { $mode="cbc"; } + elsif ($tmpline =~ /ECB/) { $mode="ecb"; } + elsif ($tmpline =~ /OFB/) { $mode="ofb"; } +@@ -1749,7 +2078,23 @@ sub parse($$) { + + if ($tt == 0) { + ##### Identify the test type +- if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) { ++ if ($tmpline =~ /KeyGen - Random Probably Prime Known Answer Test/) { ++ $tt = 19; ++ die "Interface function rsa_keygen_kat for RSA key generation KAT not defined for tested library" ++ if (!defined($rsa_keygen_kat)); ++ } elsif ($tmpline =~ /KeyGen - Random Probably Prime Test/) { ++ $tt = 18; ++ die "Interface function rsa_keygen for RSA key generation not defined for tested library" ++ if (!defined($rsa_keygen)); ++ } elsif ($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 +2105,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 +2137,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 +2220,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 +@@ -1907,6 +2278,9 @@ sub parse($$) { + } + elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests + $e=$1; ++ if ($tt == 19) { ++ $out .= $line . "\n"; # print it ++ } + } + elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests + die "S seen twice - input file crap" if ($signature ne ""); +@@ -1932,11 +2306,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 +2344,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); +@@ -1995,6 +2384,22 @@ sub parse($$) { + if ($Xq); + $Xq = $1; + } ++ elsif ($line =~ /^prandom\s*=\s*(.*)/) { #RSA key gen KAT ++ die "prandom seen twice - check input file" ++ if ($prandom); ++ $prandom = $1; ++ $out .= $line . "\n"; # print it ++ } ++ elsif ($line =~ /^qrandom\s*=\s*(.*)/) { #RSA key gen KAT ++ die "qrandom seen twice - check input file" ++ if ($qrandom); ++ $qrandom = $1; ++ $out .= $line . "\n"; # print it ++ } ++ elsif ($tt == 19 && $line =~ /^ / && $qrandom eq "") { #RSA key gen KAT ++ $qrandom = "00"; ++ $out .= $line . "\n"; # print it ++ } + else { + $out .= $line . "\n"; + } +@@ -2074,11 +2479,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 "") { +@@ -2124,7 +2528,7 @@ sub parse($$) { + $xq1 ne "" && + $xq2 ne "" && + $Xq ne "") { +- $out .= rsa_keygen($modulus, ++ $out .= rsa_keygen_x931($modulus, + $e, + $xp1, + $xp2, +@@ -2141,6 +2545,96 @@ 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 == 18) { ++ if ($modulus ne "" && ++ $capital_n > 0) { ++ $out .= rsa_keygen_driver($modulus, ++ $capital_n); ++ $capital_n = 0; ++ } ++ } ++ elsif ($tt == 19) { ++ if ($modulus ne "" && ++ $e ne "" && ++ $prandom ne "" && ++ $qrandom ne "") { ++ $out .= rsa_keygen_kat_driver($modulus, ++ $e, ++ $prandom, ++ $qrandom); ++ $prandom = ""; ++ $qrandom = ""; ++ $e = ""; ++ } ++ } + elsif ($tt > 0) { + die "Test case $tt not defined"; + } +@@ -2199,10 +2693,14 @@ 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; ++ $rsa_keygen = \&libgcrypt_rsa_keygen; ++ $rsa_keygen_kat = \&libgcrypt_rsa_keygen_kat; + } else { + die "Invalid interface option given"; + } +diff -up libgcrypt-1.5.3/tests/cavs_tests.sh.cavs libgcrypt-1.5.3/tests/cavs_tests.sh +--- libgcrypt-1.5.3/tests/cavs_tests.sh.cavs 2013-05-22 18:02:55.000000000 +0200 ++++ libgcrypt-1.5.3/tests/cavs_tests.sh 2014-09-26 17:45:38.434674884 +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.5.3/tests/fipsdrv.c.cavs libgcrypt-1.5.3/tests/fipsdrv.c +--- libgcrypt-1.5.3/tests/fipsdrv.c.cavs 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/tests/fipsdrv.c 2014-10-21 09:30:30.796777225 +0200 +@@ -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; + +@@ -1346,6 +1349,69 @@ run_rsa_derive (const void *data, size_t + } + + ++/* Generate RSA key using the S-expression in (DATA,DATALEN). This ++ S-expression is used directly as input to gcry_pk_genkey. The ++ result is printed to stdout with one parameter per line in hex ++ format and in this order: e, p, q, n, d. */ ++static void ++run_rsa_keygen (const void *data, size_t datalen, int test) ++{ ++ gpg_error_t err; ++ gcry_sexp_t s_keyspec, s_key, s_top, l1; ++ gcry_mpi_t mpi; ++ const char *parmlist; ++ int idx; ++ ++ if (!datalen) ++ err = gpg_error (GPG_ERR_NO_DATA); ++ else ++ err = gcry_sexp_new (&s_keyspec, data, datalen, 1); ++ if (err) ++ die ("gcry_sexp_new failed for RSA key generation: %s\n", ++ gpg_strerror (err)); ++ ++ err = gcry_pk_genkey (&s_key, s_keyspec); ++ ++ gcry_sexp_release (s_keyspec); ++ ++ if (test) { ++ if (err) ++ printf("F\n"); ++ else { ++ gcry_sexp_release (s_key); ++ printf("P\n"); ++ } ++ return; ++ } ++ ++ if (err) ++ die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err)); ++ ++ parmlist = "epqnd"; ++ ++ /* Parse and print the parameters. */ ++ l1 = gcry_sexp_find_token (s_key, "private-key", 0); ++ s_top = gcry_sexp_find_token (l1, "rsa", 0); ++ gcry_sexp_release (l1); ++ if (!s_top) ++ die ("private-key part not found in result\n"); ++ ++ for (idx=0; parmlist[idx]; idx++) ++ { ++ l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1); ++ mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); ++ gcry_sexp_release (l1); ++ if (!mpi) ++ die ("parameter %c missing in private-key\n", parmlist[idx]); ++ print_mpi_line (mpi, 1); ++ gcry_mpi_release (mpi); ++ } ++ ++ gcry_sexp_release (s_top); ++ gcry_sexp_release (s_key); ++} ++ ++ + + static size_t + compute_tag_length (size_t n) +@@ -1675,14 +1741,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 +1766,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 +1775,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 +1787,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 +1830,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 +1866,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 +1920,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 +2032,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 +2088,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; + +- gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen); +- err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL); ++ s_key = read_sexp_from_file (keyfile); ++ algo = dsa_hash_from_key(s_key); ++ ++ 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 +2108,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 +2183,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 +2205,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 +2237,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 +2247,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 +2274,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 +2368,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++; +@@ -2406,6 +2639,18 @@ main (int argc, char **argv) + die ("no data available (do not use --chunk)\n"); + run_rsa_derive (data, datalen); + } ++ else if (!strcmp (mode_string, "rsa-keygen")) ++ { ++ if (!data) ++ die ("no data available (do not use --chunk)\n"); ++ run_rsa_keygen (data, datalen, 0); ++ } ++ else if (!strcmp (mode_string, "rsa-keygen-kat")) ++ { ++ if (!data) ++ die ("no data available (do not use --chunk)\n"); ++ run_rsa_keygen (data, datalen, 1); ++ } + else if (!strcmp (mode_string, "rsa-gen")) + { + int keysize; +@@ -2463,23 +2708,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/SOURCES/libgcrypt-1.5.3-fips-cfgrandom.patch b/SOURCES/libgcrypt-1.5.3-fips-cfgrandom.patch new file mode 100644 index 0000000..9585bf3 --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-fips-cfgrandom.patch @@ -0,0 +1,142 @@ +diff -up libgcrypt-1.5.3/random/drbg.c.cfgrandom libgcrypt-1.5.3/random/drbg.c +--- libgcrypt-1.5.3/random/drbg.c.cfgrandom 2014-10-30 16:42:49.000000000 +0100 ++++ libgcrypt-1.5.3/random/drbg.c 2014-10-30 16:46:57.291800433 +0100 +@@ -485,8 +485,11 @@ gcry_drbg_get_entropy (struct gcry_drbg_ + read_cb_size = len; + read_cb_len = 0; + #if USE_RNDLINUX ++ _gcry_rndlinux_gather_random (gcry_drbg_read_cb, 0, len, ++ -1); ++ read_cb_len = 0; + rc = _gcry_rndlinux_gather_random (gcry_drbg_read_cb, 0, len, +- GCRY_VERY_STRONG_RANDOM); ++ GCRY_STRONG_RANDOM); + #elif USE_RNDUNIX + rc = _gcry_rndunix_gather_random (read_cb, 0, length, + GCRY_VERY_STRONG_RANDOM); +diff -up libgcrypt-1.5.3/random/random-fips.c.cfgrandom libgcrypt-1.5.3/random/random-fips.c +--- libgcrypt-1.5.3/random/random-fips.c.cfgrandom 2014-10-30 16:42:49.942216405 +0100 ++++ libgcrypt-1.5.3/random/random-fips.c 2014-10-30 16:42:49.970217037 +0100 +@@ -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 + { +diff -up libgcrypt-1.5.3/random/rndlinux.c.cfgrandom libgcrypt-1.5.3/random/rndlinux.c +--- libgcrypt-1.5.3/random/rndlinux.c.cfgrandom 2014-10-30 16:42:49.949216563 +0100 ++++ libgcrypt-1.5.3/random/rndlinux.c 2014-10-30 16:42:49.971217059 +0100 +@@ -37,7 +37,9 @@ + #include "g10lib.h" + #include "rand-internal.h" + +-static int open_device ( const char *name ); ++#define NAME_OF_CFG_RNGSEED "/etc/gcrypt/rngseed" ++ ++static int open_device ( const char *name, int fatal ); + + + static int +@@ -58,13 +60,17 @@ set_cloexec_flag (int fd) + * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)). + */ + static int +-open_device ( const char *name ) ++open_device ( const char *name, int fatal ) + { + int fd; + + fd = open ( name, O_RDONLY ); + if ( fd == -1 ) +- log_fatal ("can't open %s: %s\n", name, strerror(errno) ); ++ { ++ if (! fatal) ++ return fd; ++ log_fatal ("can't open %s: %s\n", name, strerror(errno) ); ++ } + + if (set_cloexec_flag (fd)) + log_error ("error setting FD_CLOEXEC on fd %d: %s\n", +@@ -93,6 +99,7 @@ _gcry_rndlinux_gather_random (void (*add + { + static int fd_urandom = -1; + static int fd_random = -1; ++ static int fd_configured = -1; + int fd; + int n; + byte buffer[768]; +@@ -101,6 +108,7 @@ _gcry_rndlinux_gather_random (void (*add + size_t last_so_far = 0; + int any_need_entropy = 0; + int delay; ++ size_t orig_length = length; + + /* First read from a hardware source. However let it account only + for up to 50% of the requested bytes. */ +@@ -111,16 +119,26 @@ _gcry_rndlinux_gather_random (void (*add + length -= n_hw; + + /* Open the requested device. */ ++ ++ if (level == -1) ++ { ++ if (fd_configured == -1) ++ fd_configured = open_device ( NAME_OF_CFG_RNGSEED, 0 ); ++ fd = fd_configured; ++ if (fd == -1) ++ return -1; ++ } ++ + if (level >= 2) + { + if( fd_random == -1 ) +- fd_random = open_device ( NAME_OF_DEV_RANDOM ); ++ fd_random = open_device ( NAME_OF_DEV_RANDOM, 1 ); + fd = fd_random; + } +- else ++ else if (level != -1) + { + if( fd_urandom == -1 ) +- fd_urandom = open_device ( NAME_OF_DEV_URANDOM ); ++ fd_urandom = open_device ( NAME_OF_DEV_URANDOM, 1 ); + fd = fd_urandom; + } + diff --git a/SOURCES/libgcrypt-1.5.3-fips-ctor.patch b/SOURCES/libgcrypt-1.5.3-fips-ctor.patch new file mode 100644 index 0000000..ad483bf --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-fips-ctor.patch @@ -0,0 +1,72 @@ +diff -up libgcrypt-1.5.3/cipher/md.c.fips-ctor libgcrypt-1.5.3/cipher/md.c +--- libgcrypt-1.5.3/cipher/md.c.fips-ctor 2013-07-25 11:10:03.000000000 +0200 ++++ libgcrypt-1.5.3/cipher/md.c 2014-12-12 15:32:35.464515238 +0100 +@@ -570,11 +570,8 @@ md_enable (gcry_md_hd_t hd, int algorith + + if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) + { +- _gcry_inactivate_fips_mode ("MD5 used"); + if (_gcry_enforced_fips_mode () ) + { +- /* We should never get to here because we do not register +- MD5 in enforced fips mode. But better throw an error. */ + err = GPG_ERR_DIGEST_ALGO; + } + } +diff -up libgcrypt-1.5.3/src/global.c.fips-ctor libgcrypt-1.5.3/src/global.c +--- libgcrypt-1.5.3/src/global.c.fips-ctor 2014-12-12 15:32:35.463515215 +0100 ++++ libgcrypt-1.5.3/src/global.c 2014-12-12 16:46:33.424883301 +0100 +@@ -140,6 +140,34 @@ global_init (void) + } + + ++#ifndef FIPS_MODULE_PATH ++#define FIPS_MODULE_PATH "/etc/system-fips" ++#endif ++ ++void __attribute__ ((constructor)) _gcry_global_constructor (void) ++{ ++ int rv; ++ ++ rv = access (FIPS_MODULE_PATH, F_OK); ++ if (rv < 0 && errno != ENOENT) ++ rv = 0; ++ ++ if (!rv) ++ { ++ int no_secmem_save; ++ ++ /* it should be always 0 at this point but let's keep on the safe side */ ++ no_secmem_save = no_secure_memory; ++ no_secure_memory = 1; ++ /* force selftests */ ++ global_init (); ++ if (fips_mode ()) ++ _gcry_random_initialize (1); ++ _gcry_fips_run_selftests (0); ++ no_secure_memory = no_secmem_save; ++ } ++} ++ + /* This function is called by the macro fips_is_operational and makes + sure that the minimal initialization has been done. This is far + from a perfect solution and hides problems with an improper +@@ -500,8 +528,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + + case GCRYCTL_FIPS_MODE_P: + if (fips_mode () +- && !_gcry_is_fips_mode_inactive () +- && !no_secure_memory) ++ && !_gcry_is_fips_mode_inactive ()) + err = GPG_ERR_GENERAL; /* Used as TRUE value */ + break; + +@@ -600,7 +627,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + break; + + case GCRYCTL_SET_ENFORCED_FIPS_FLAG: +- if (!any_init_done) ++ if (fips_mode ()) + { + /* Not yet intialized at all. Set the enforced fips mode flag */ + _gcry_set_enforced_fips_mode (); diff --git a/SOURCES/libgcrypt-1.5.3-fips-reqs.patch b/SOURCES/libgcrypt-1.5.3-fips-reqs.patch new file mode 100644 index 0000000..c4de13d --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-fips-reqs.patch @@ -0,0 +1,359 @@ +diff -up libgcrypt-1.5.3/cipher/dsa.c.fips-reqs libgcrypt-1.5.3/cipher/dsa.c +--- libgcrypt-1.5.3/cipher/dsa.c.fips-reqs 2014-11-12 17:05:01.000000000 +0100 ++++ libgcrypt-1.5.3/cipher/dsa.c 2014-11-14 14:32:23.751354070 +0100 +@@ -55,42 +55,86 @@ typedef struct + } dsa_domain_t; + + +-/* A sample 1024 bit DSA key used for the selftests. */ ++/* A sample 2048 bit DSA key used for the selftests. */ + static const char sample_secret_key[] = + "(private-key" + " (dsa" +-" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" +-" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" +-" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" +-" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" +-" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" +-" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" +-" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" +-" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" +-" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" +-" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" +-" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" +-" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" +-" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" +-" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; +-/* A sample 1024 bit DSA key used for the selftests (public only). */ ++" (p #a85378d8fd3f8d72ec7418080da21317e43ec4b62ba8c862" ++" 3b7e4d04441dd1a0658662596493ca8e9e8fbb7e34aaddb6" ++" 2e5d67b6d09a6e61b769e7c352aa2b10e20ca0636963b552" ++" 3e86470decbbeda027e797e7b67635d4d49c30700e74af8a" ++" 0ff156a801af57a26e7078f1d82f74908ecb6d07e70b3503" ++" eed94fa32cf17a7fc3d6cf40dc7b00830e6a2566dc073e34" ++" 3312517c6aa5152b4bfecd2e551fee346318a153423c996b" ++" 0d5dcb9102aedd38798616f1f1e0d6c403525b1f9b3d4dc7" ++" 66de2dfc4a56d7b8ba5963d60f3e16318870ad436952e557" ++" 65374eab85e8ec17d6b9a4547b9b5f2752f3105be809b23a" ++" 2c8d7469db02e24d592394a7dba069e9#)" ++" (q #d277044e50f5a4e3f510a50a0b84fdffbca047ed27602056" ++" 7441a0a5#)" ++" (g #13d754e21fd241655da891c522a65a72a89bdc64ec9b54a8" ++" 21ed4a898b490e0c4fcb72192a4a20f541f3f2925399f0ba" ++" ecf929aafbf79dfe4332393b32cd2e2fcf272f32a627434a" ++" 0df242b75b414df372121e53a553f222f836b000f016485b" ++" 6bd0898451801dcd8de64cd5365696ffc532d528c506620a" ++" 942a0305046d8f1876341f1e570bc3974ba6b9a438e97023" ++" 02a2e6e67bfd06d32bc679962271d7b40cd72f386e64e0d7" ++" ef86ca8ca5d14228dc2a4f16e3189886b5990674f4200f3a" ++" 4cf65a3f0ddba1fa672dff2f5e143d10e4e97ae84f6da095" ++" 35d5b9df259181a79b63b069e949972b02ba36b3586aab7e" ++" 45f322f82e4e85ca3ab85591b3c2a966#)" ++" (y #2452f3ccbe9ed5ca7dc74c602b99226e8f2fab38e7d7ddfb" ++" 75539b17155e9fcfd1aba564eb8535d812c9c2dcf9728444" ++" 1bc482243624c7f457580c1c38a57c46c457392470edb52c" ++" b5a6e03fe6287bb6f49a42a2065a054f030839df1fd3149c" ++" 4ca0531dd8ca8aaa9cc7337193387348336118224545e88c" ++" 80ffd8765d74360333ccab9972779b6525a65bdd0d10c675" ++" c109bbd3e5be4d72ef6eba6e438d5226237db888379c5fcc" ++" 47a3847ff63711baed6d03afe81e694a413b680bd38ab490" ++" 3f8370a707ef551d4941026d9579d691de8edaa16105eb9d" ++" ba3c2f4c1bec508275aa0207e251b5eccb286a4b01d449d3" ++" 0acb673717a0d2fb3b50c893f7dab14f#)" ++" (x #0c4b3089d1b862cb3c436491f0915470c52796e3acbee800" ++" ec55f6cc#)))"; ++/* A sample 2048 bit DSA key used for the selftests (public only). */ + static const char sample_public_key[] = + "(public-key" + " (dsa" +-" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" +-" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" +-" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" +-" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" +-" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" +-" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" +-" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" +-" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" +-" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" +-" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" +-" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" +-" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" +-" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))"; +- ++" (p #a85378d8fd3f8d72ec7418080da21317e43ec4b62ba8c862" ++" 3b7e4d04441dd1a0658662596493ca8e9e8fbb7e34aaddb6" ++" 2e5d67b6d09a6e61b769e7c352aa2b10e20ca0636963b552" ++" 3e86470decbbeda027e797e7b67635d4d49c30700e74af8a" ++" 0ff156a801af57a26e7078f1d82f74908ecb6d07e70b3503" ++" eed94fa32cf17a7fc3d6cf40dc7b00830e6a2566dc073e34" ++" 3312517c6aa5152b4bfecd2e551fee346318a153423c996b" ++" 0d5dcb9102aedd38798616f1f1e0d6c403525b1f9b3d4dc7" ++" 66de2dfc4a56d7b8ba5963d60f3e16318870ad436952e557" ++" 65374eab85e8ec17d6b9a4547b9b5f2752f3105be809b23a" ++" 2c8d7469db02e24d592394a7dba069e9#)" ++" (q #d277044e50f5a4e3f510a50a0b84fdffbca047ed27602056" ++" 7441a0a5#)" ++" (g #13d754e21fd241655da891c522a65a72a89bdc64ec9b54a8" ++" 21ed4a898b490e0c4fcb72192a4a20f541f3f2925399f0ba" ++" ecf929aafbf79dfe4332393b32cd2e2fcf272f32a627434a" ++" 0df242b75b414df372121e53a553f222f836b000f016485b" ++" 6bd0898451801dcd8de64cd5365696ffc532d528c506620a" ++" 942a0305046d8f1876341f1e570bc3974ba6b9a438e97023" ++" 02a2e6e67bfd06d32bc679962271d7b40cd72f386e64e0d7" ++" ef86ca8ca5d14228dc2a4f16e3189886b5990674f4200f3a" ++" 4cf65a3f0ddba1fa672dff2f5e143d10e4e97ae84f6da095" ++" 35d5b9df259181a79b63b069e949972b02ba36b3586aab7e" ++" 45f322f82e4e85ca3ab85591b3c2a966#)" ++" (y #2452f3ccbe9ed5ca7dc74c602b99226e8f2fab38e7d7ddfb" ++" 75539b17155e9fcfd1aba564eb8535d812c9c2dcf9728444" ++" 1bc482243624c7f457580c1c38a57c46c457392470edb52c" ++" b5a6e03fe6287bb6f49a42a2065a054f030839df1fd3149c" ++" 4ca0531dd8ca8aaa9cc7337193387348336118224545e88c" ++" 80ffd8765d74360333ccab9972779b6525a65bdd0d10c675" ++" c109bbd3e5be4d72ef6eba6e438d5226237db888379c5fcc" ++" 47a3847ff63711baed6d03afe81e694a413b680bd38ab490" ++" 3f8370a707ef551d4941026d9579d691de8edaa16105eb9d" ++" ba3c2f4c1bec508275aa0207e251b5eccb286a4b01d449d3" ++" 0acb673717a0d2fb3b50c893f7dab14f#)))"; + + + +@@ -1046,14 +1090,14 @@ dsa_get_nbits (int algo, gcry_mpi_t *pke + */ + + static const char * +-selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) ++selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) + { + static const char sample_data[] = + "(data (flags raw)" +- " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; ++ " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4f1e2d3c4b5a6978879605142#))"; + static const char sample_data_bad[] = + "(data (flags raw)" +- " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; ++ " (value #a0b1c2d3e4f500102030405060708090a1b2c3d401e2d3c4b5a6978879605142#))"; + + const char *errtxt = NULL; + gcry_error_t err; +@@ -1131,7 +1175,7 @@ selftests_dsa (selftest_report_func_t re + } + + what = "sign"; +- errtxt = selftest_sign_1024 (pkey, skey); ++ errtxt = selftest_sign (pkey, skey); + if (errtxt) + goto failed; + +diff -up libgcrypt-1.5.3/cipher/rsa.c.fips-reqs libgcrypt-1.5.3/cipher/rsa.c +--- libgcrypt-1.5.3/cipher/rsa.c.fips-reqs 2014-11-12 17:05:01.299387339 +0100 ++++ libgcrypt-1.5.3/cipher/rsa.c 2014-11-14 14:06:00.099602441 +0100 +@@ -52,33 +52,57 @@ typedef struct + } RSA_secret_key; + + +-/* A sample 1024 bit RSA key used for the selftests. */ ++/* A sample 2048 bit RSA key used for the selftests. */ + static const char sample_secret_key[] = + "(private-key" + " (rsa" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +-" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +-" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +-" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" ++" (n #00c9d56d9d90db43d602ed9688138ab2bf6ea10610b27837a714a8ffdd00" ++" ddb493a045cc9690edada9ddc4d6ca0cf0ed4f725e21499a1812158f905a" ++" dbb63399a3e6b4f0c4972126bbe3baf2ffa072da89638e8b3e089d922abe" ++" 16e14315fc57c71f0911671ca996d18b3e8093c159d06d39f2ac95cc1075" ++" e93124d143af68524be716d749656f26c086adc0070ac1e12f8785863bdc" ++" 5a99bee9f9b9e98227510415ab060e765a288d92bdc5b57ba8df4e47a2c1" ++" e752bf47f762e03a6f4d6a4d4ed4b95969fab214c1eee62f95cd9472aee4" ++" db189ac4cd70bdee3116b74965ac40190eb56d83f136bb082f2e4e9262a4" ++" ff50db2045a2eb167af2d528c1fd4e0371#)" + " (e #010001#)" +-" (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11" +-" 7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd" +-" c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21" +-" c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)" +-" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" +-" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)" +-" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" +-" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)" +-" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" +-" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))"; +-/* A sample 1024 bit RSA key used for the selftests (public only). */ ++" (d #36273db1f91bdba7a0417f1223ac232999d53a7b606741076353b4d2e758" ++" 950ac705f34eb2b412d470dc4f8506d3ddd863273e673121243904bc06a4" ++" ccce2b7afe7badde116ea3a5e604530ea34e2db48f31bfca7525520285de" ++" 3db27243b2898a9a3441263f9a67bea4967b0e75baa693d5b8d8b857f24b" ++" 0f1481d1574ef6454ca63bd070cad39d55de2205e78e284dee11cfb66776" ++" 09d3e33c13f99934107bec8138f0b6349c9b506f0b91814d8994047bf03c" ++" f4b1b200488d5a8f889ec5ab3a9e443f54e7d96e47aaa1bd404631f9f034" ++" b604e12b5b7386dd3a921b71c73f32e5c3c2aba17ebfa452a0b06890d120" ++" 1279e9d7c940baf219c7a50092860d01#)" ++" (p #00fc5c6e16ce1f037bcdf7b372b28f1672b856aef7cd67d84e7d07afd543" ++" 26c335be438f4e2f1c434e6bd2b2ec526d97522bcc5c3a6bf414c674da66" ++" 381c7a3f842fe3f95ab865694606a33779b2a15b58ed5ea75f8c6566bbd1" ++" 2436e637a73d49778a8c34d86929f34d5822b05124b640a886590ab7ba5c" ++" 97da57e836da7a9cad#)" ++" (q #00ccbe7b096906ee45bf884738a8f817e5b6ba6755e3e8058bb8e253d68e" ++" ef2ce74f4af74e268d850b3fecc31cd4ebec6ac8722a257dfda67796f01e" ++" cd2857f83730756bbdd47b0c87c56c8740a5bb272c78c9745a545b0b306f" ++" 444afa71e4216166f9ee65de7c04d7fda9155b7fe27aba698672a6068d9b" ++" 9055609e4c5da9b655#)" ++" (u #00afdecbdc5268ea7b1bff7284db7f6757dae3165fd80691ed2bbe8e54a1" ++" 6f7ff950aad059e9695903d93e59ff206ee1470bd2b099ca4e83426a7684" ++" 75a1ecafd3092fec0f008d78fe773174ec6fbff85384f3a91c2e4b1f59f1" ++" 1f2000fee86569f6cab5de338087bc615b90570de4aeb1a9125abbe3834d" ++" 5a69716c0a5fa20603#)))"; ++/* A sample 2048 bit RSA key used for the selftests (public only). */ + static const char sample_public_key[] = + "(public-key" + " (rsa" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +-" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +-" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +-" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" ++" (n #00c9d56d9d90db43d602ed9688138ab2bf6ea10610b27837a714a8ffdd00" ++" ddb493a045cc9690edada9ddc4d6ca0cf0ed4f725e21499a1812158f905a" ++" dbb63399a3e6b4f0c4972126bbe3baf2ffa072da89638e8b3e089d922abe" ++" 16e14315fc57c71f0911671ca996d18b3e8093c159d06d39f2ac95cc1075" ++" e93124d143af68524be716d749656f26c086adc0070ac1e12f8785863bdc" ++" 5a99bee9f9b9e98227510415ab060e765a288d92bdc5b57ba8df4e47a2c1" ++" e752bf47f762e03a6f4d6a4d4ed4b95969fab214c1eee62f95cd9472aee4" ++" db189ac4cd70bdee3116b74965ac40190eb56d83f136bb082f2e4e9262a4" ++" ff50db2045a2eb167af2d528c1fd4e0371#)" + " (e #010001#)))"; + + +@@ -1379,20 +1403,35 @@ compute_keygrip (gcry_md_hd_t md, gcry_s + */ + + static const char * +-selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) ++selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey) + { + static const char sample_data[] = + "(data (flags pkcs1)" +- " (hash sha1 #11223344556677889900aabbccddeeff10203040#))"; ++ " (hash sha256 #11223344556677889900aabbccddeeffa0b0c0d0102030405060708090a1b1c1#))"; + static const char sample_data_bad[] = + "(data (flags pkcs1)" +- " (hash sha1 #11223344556677889900aabbccddeeff80203040#))"; ++ " (hash sha256 #11223344556677889900aabbccddeeffa0b0c0d0102030405060708091a1b1c1#))"; ++ static const char signature_ka[] = ++ "(sig-val \n" ++ " (rsa \n" ++ " (s #0B12D55738B099D401C81BEEDA54E045B4B7D9CDA5A8769E9C484F696A58912A" ++ "1E5DE7E5A2D181DA15A5C254D802AB75F1056E27406850AC7BE310BC32D2CED8" ++ "6697FE84508F7EFFF4D147C52E955A0873EF2F52ED71F2FC9C3C12D4045CB643" ++ "70158378E1494D8FBAD2248B9B64233D2CC2C1932B0531E539DEB07434B76D3B" ++ "6959E8A37E33B234C0C8C2C8FB1D00939239C9C491B2EBEED77BF952B597E11B" ++ "D4ED0C103D2B88BC78B4E505CF9D8D08B585CE3688D4FBE83ED58D1E1341AC4D" ++ "7C5EFF3CBC565CC7AE61C2F568426763A5239D31C1FFFD366984901679A343C4" ++ "01BB778BBA5E533B7875BA658A19AA9E56170F4A28E4322BF1621175FB06463E#)\n" ++ " )\n" ++ " )\n"; + + const char *errtxt = NULL; + gcry_error_t err; + gcry_sexp_t data = NULL; + gcry_sexp_t data_bad = NULL; + gcry_sexp_t sig = NULL; ++ char buf[1024]; ++ size_t len; + + err = gcry_sexp_sscan (&data, NULL, + sample_data, strlen (sample_data)); +@@ -1411,6 +1450,12 @@ selftest_sign_1024 (gcry_sexp_t pkey, gc + errtxt = "signing failed"; + goto leave; + } ++ len = gcry_sexp_sprint (sig, GCRYSEXP_FMT_ADVANCED, buf, sizeof(buf)); ++ if (len != sizeof (signature_ka) - 1 || memcmp (buf, signature_ka, len) != 0) ++ { ++ errtxt = "signature KAT failed"; ++ goto leave; ++ } + err = gcry_pk_verify (sig, data, pkey); + if (err) + { +@@ -1467,11 +1512,11 @@ extract_a_from_sexp (gcry_sexp_t encr_da + + + static const char * +-selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) ++selftest_encr (gcry_sexp_t pkey, gcry_sexp_t skey) + { + const char *errtxt = NULL; + gcry_error_t err; +- const unsigned int nbits = 1000; /* Encrypt 1000 random bits. */ ++ const unsigned int nbits = 2000; /* Encrypt 2000 random bits. */ + gcry_mpi_t plaintext = NULL; + gcry_sexp_t plain = NULL; + gcry_sexp_t encr = NULL; +@@ -1594,12 +1639,12 @@ selftests_rsa (selftest_report_func_t re + } + + what = "sign"; +- errtxt = selftest_sign_1024 (pkey, skey); ++ errtxt = selftest_sign (pkey, skey); + if (errtxt) + goto failed; + + what = "encrypt"; +- errtxt = selftest_encr_1024 (pkey, skey); ++ errtxt = selftest_encr (pkey, skey); + if (errtxt) + goto failed; + +diff -up libgcrypt-1.5.3/random/drbg.c.fips-reqs libgcrypt-1.5.3/random/drbg.c +--- libgcrypt-1.5.3/random/drbg.c.fips-reqs 2014-11-12 17:05:01.000000000 +0100 ++++ libgcrypt-1.5.3/random/drbg.c 2014-11-14 14:45:33.820190218 +0100 +@@ -390,6 +390,9 @@ gcry_drbg_fips_continuous_test (struct g + ret = memcmp (drbg->prev, buf, gcry_drbg_blocklen (drbg)); + memcpy (drbg->prev, buf, gcry_drbg_blocklen (drbg)); + /* the test shall pass when the two compared values are not equal */ ++ if (ret == 0) ++ fips_signal_error ("duplicate block returned by DRBG"); ++ + return ret != 0; + } + +diff -up libgcrypt-1.5.3/src/visibility.c.fips-reqs libgcrypt-1.5.3/src/visibility.c +--- libgcrypt-1.5.3/src/visibility.c.fips-reqs 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/src/visibility.c 2014-11-12 17:05:27.251973230 +0100 +@@ -1217,6 +1217,9 @@ gcry_kdf_derive (const void *passphrase, + unsigned long iterations, + size_t keysize, void *keybuffer) + { ++ if (!fips_is_operational ()) ++ return gpg_error (fips_not_operational ()); ++ + return _gcry_kdf_derive (passphrase, passphraselen, algo, hashalgo, + salt, saltlen, iterations, keysize, keybuffer); + } +@@ -1271,6 +1274,13 @@ void + gcry_mpi_randomize (gcry_mpi_t w, + unsigned int nbits, enum gcry_random_level level) + { ++ if (!fips_is_operational ()) ++ { ++ (void)fips_not_operational (); ++ fips_signal_fatal_error ("called in non-operational state"); ++ fips_noreturn (); ++ } ++ + _gcry_mpi_randomize (w, nbits, level); + } + +@@ -1296,6 +1306,9 @@ gcry_prime_generate (gcry_mpi_t *prime, + gcry_random_level_t random_level, + unsigned int flags) + { ++ if (!fips_is_operational ()) ++ return gpg_error (fips_not_operational ()); ++ + return _gcry_prime_generate (prime, prime_bits, factor_bits, factors, + cb_func, cb_arg, random_level, flags); + } diff --git a/SOURCES/libgcrypt-1.5.3-fips-test.patch b/SOURCES/libgcrypt-1.5.3-fips-test.patch new file mode 100644 index 0000000..cd80494 --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-fips-test.patch @@ -0,0 +1,18 @@ +diff -up libgcrypt-1.5.3/tests/basic.c.fips-test libgcrypt-1.5.3/tests/basic.c +--- libgcrypt-1.5.3/tests/basic.c.fips-test 2014-09-26 17:36:41.620556071 +0200 ++++ libgcrypt-1.5.3/tests/basic.c 2014-09-26 17:36:43.317594382 +0200 +@@ -563,6 +563,14 @@ check_ctr_cipher (void) + if (!tv[i].algo) + continue; + ++ if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, " algorithm %d not available in fips mode\n", ++ tv[i].algo); ++ continue; ++ } ++ + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0); diff --git a/SOURCES/libgcrypt-1.5.3-rsa-fips-keygen.patch b/SOURCES/libgcrypt-1.5.3-rsa-fips-keygen.patch new file mode 100644 index 0000000..9d0f001 --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-rsa-fips-keygen.patch @@ -0,0 +1,374 @@ +diff -up libgcrypt-1.5.3/cipher/primegen.c.fips-keygen libgcrypt-1.5.3/cipher/primegen.c +--- libgcrypt-1.5.3/cipher/primegen.c.fips-keygen 2014-10-21 15:05:59.434189992 +0200 ++++ libgcrypt-1.5.3/cipher/primegen.c 2014-10-21 15:05:59.458190534 +0200 +@@ -1189,6 +1189,22 @@ gcry_prime_check (gcry_mpi_t x, unsigned + return gcry_error (err); + } + ++/* Check whether the number X is prime according to FIPS 186-4 table C.2. */ ++gpg_err_code_t ++_gcry_fips186_4_prime_check (gcry_mpi_t x, unsigned int bits) ++{ ++ gpg_err_code_t ec = GPG_ERR_NO_ERROR; ++ gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */ ++ ++ /* We use 5 or 4 rounds as specified in table C.2 */ ++ if (! check_prime (x, val_2, bits > 1024 ? 4 : 5, NULL, NULL)) ++ ec = GPG_ERR_NO_PRIME; ++ ++ mpi_free (val_2); ++ ++ return ec; ++} ++ + /* Find a generator for PRIME where the factorization of (prime-1) is + in the NULL terminated array FACTORS. Return the generator as a + newly allocated MPI in R_G. If START_G is not NULL, use this as s +diff -up libgcrypt-1.5.3/cipher/rsa.c.fips-keygen libgcrypt-1.5.3/cipher/rsa.c +--- libgcrypt-1.5.3/cipher/rsa.c.fips-keygen 2014-10-21 15:05:59.423189744 +0200 ++++ libgcrypt-1.5.3/cipher/rsa.c 2014-10-21 15:12:45.200350340 +0200 +@@ -328,6 +328,279 @@ generate_std (RSA_secret_key *sk, unsign + } + + ++/**************** ++ * Generate a key pair with a key of size NBITS. ++ * USE_E = 0 let Libcgrypt decide what exponent to use. ++ * = 1 request the use of a "secure" exponent; this is required by some ++ * specification to be 65537. ++ * > 2 Use this public exponent. If the given exponent ++ * is not odd one is internally added to it. ++ * TESTPARMS: If set, do not generate but test whether the p,q is probably prime ++ * Returns key with zeroes to not break code calling this function. ++ * TRANSIENT_KEY: If true, generate the primes using the standard RNG. ++ * Returns: 2 structures filled with all needed values ++ */ ++static gpg_err_code_t ++generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, ++ gcry_sexp_t testparms, int transient_key) ++{ ++ gcry_mpi_t p, q; /* the two primes */ ++ gcry_mpi_t d; /* the private key */ ++ gcry_mpi_t u; ++ gcry_mpi_t p1, q1; ++ gcry_mpi_t n; /* the public key */ ++ gcry_mpi_t e; /* the exponent */ ++ gcry_mpi_t g; ++ gcry_mpi_t minp; ++ gcry_mpi_t diff, mindiff; ++ gcry_random_level_t random_level; ++ unsigned int pbits = nbits/2; ++ unsigned int i; ++ int pqswitch; ++ gpg_err_code_t ec = GPG_ERR_NO_PRIME; ++ ++ if (nbits < 1024 || (nbits & 0x1FF)) ++ return GPG_ERR_INV_VALUE; ++ if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072) ++ return GPG_ERR_INV_VALUE; ++ ++ /* The random quality depends on the transient_key flag. */ ++ random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; ++ ++ if (testparms) ++ { ++ /* Parameters to derive the key are given. */ ++ /* Note that we explicitly need to setup the values of tbl ++ because some compilers (e.g. OpenWatcom, IRIX) don't allow ++ to initialize a structure with automatic variables. */ ++ struct { const char *name; gcry_mpi_t *value; } tbl[] = { ++ { "e" }, ++ { "p" }, ++ { "q" }, ++ { NULL } ++ }; ++ int idx; ++ gcry_sexp_t oneparm; ++ ++ tbl[0].value = &e; ++ tbl[1].value = &p; ++ tbl[2].value = &q; ++ ++ for (idx=0; tbl[idx].name; idx++) ++ { ++ oneparm = gcry_sexp_find_token (testparms, tbl[idx].name, 0); ++ if (oneparm) ++ { ++ *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1, ++ GCRYMPI_FMT_USG); ++ gcry_sexp_release (oneparm); ++ } ++ } ++ for (idx=0; tbl[idx].name; idx++) ++ if (!*tbl[idx].value) ++ break; ++ if (tbl[idx].name) ++ { ++ /* At least one parameter is missing. */ ++ for (idx=0; tbl[idx].name; idx++) ++ gcry_mpi_release (*tbl[idx].value); ++ return GPG_ERR_MISSING_VALUE; ++ } ++ } ++ else ++ { ++ if (use_e < 65537) ++ use_e = 65537; /* This is the smallest value allowed by FIPS */ ++ ++ e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); ++ ++ use_e |= 1; /* make sure this is odd */ ++ mpi_set_ui (e, use_e); ++ ++ p = gcry_mpi_snew (pbits); ++ q = gcry_mpi_snew (pbits); ++ } ++ ++ n = gcry_mpi_new (nbits); ++ d = gcry_mpi_snew (nbits); ++ u = gcry_mpi_snew (nbits); ++ ++ /* prepare approximate minimum p and q */ ++ minp = gcry_mpi_new (pbits); ++ mpi_set_ui (minp, 0xB504F334); ++ gcry_mpi_lshift (minp, minp, pbits - 32); ++ ++ /* prepare minimum p and q difference */ ++ diff = gcry_mpi_new (pbits); ++ mindiff = gcry_mpi_new (pbits - 99); ++ mpi_set_ui (mindiff, 1); ++ gcry_mpi_lshift (mindiff, mindiff, pbits - 100); ++ ++ p1 = gcry_mpi_snew (pbits); ++ q1 = gcry_mpi_snew (pbits); ++ g = gcry_mpi_snew (pbits); ++ ++retry: ++ /* generate p and q */ ++ for (i = 0; i < 5 * pbits; i++) ++ { ++ ploop: ++ if (!testparms) ++ { ++ gcry_mpi_randomize (p, pbits, random_level); ++ } ++ if (mpi_cmp (p, minp) < 0) ++ { ++ if (testparms) goto err; ++ goto ploop; ++ } ++ ++ mpi_sub_ui (p1, p, 1); ++ if (gcry_mpi_gcd (g, p1, e)) ++ { ++ if (_gcry_fips186_4_prime_check (p, pbits) != GPG_ERR_NO_ERROR) ++ { ++ /* not a prime */ ++ if (testparms) goto err; ++ } ++ else ++ break; ++ } ++ else if (testparms) goto err; ++ } ++ if (i >= 5 * pbits) ++ goto err; ++ ++ for (i = 0; i < 5 * pbits; i++) ++ { ++ qloop: ++ if (!testparms) ++ { ++ gcry_mpi_randomize (q, pbits, random_level); ++ } ++ if (mpi_cmp (q, minp) < 0) ++ { ++ if (testparms) goto err; ++ goto qloop; ++ } ++ if (mpi_cmp (p, q) < 0) ++ { ++ pqswitch = 1; ++ mpi_sub (diff, q, p); ++ } ++ else ++ { ++ pqswitch = 0; ++ mpi_sub (diff, p, q); ++ } ++ if (mpi_cmp (diff, mindiff) < 0) ++ { ++ if (testparms) goto err; ++ goto qloop; ++ } ++ ++ mpi_sub_ui (q1, q, 1); ++ if (gcry_mpi_gcd (g, q1, e)) ++ { ++ if (_gcry_fips186_4_prime_check (q, pbits) != GPG_ERR_NO_ERROR) ++ { ++ /* not a prime */ ++ if (testparms) goto err; ++ } ++ else ++ break; ++ } ++ else if (testparms) goto err; ++ } ++ if (i >= 5 * pbits) ++ goto err; ++ ++ if (testparms) ++ { ++ mpi_clear (p); ++ mpi_clear (q); ++ } ++ else ++ { ++ gcry_mpi_t f; ++ ++ if (pqswitch) ++ { ++ gcry_mpi_t tmp; ++ ++ tmp = p; ++ p = q; ++ q = tmp; ++ } ++ ++ f = gcry_mpi_snew (nbits); ++ ++ /* calculate the modulus */ ++ mpi_mul(n, p, q); ++ ++ /* calculate the secret key d = e^1 mod phi */ ++ gcry_mpi_gcd (g, p1, q1); ++ mpi_fdiv_q (f, p1, g); ++ mpi_mul (f, f, q1); ++ ++ mpi_invm (d, e, f); ++ ++ gcry_mpi_release (f); ++ ++ if (mpi_get_nbits (d) < pbits) goto retry; ++ ++ /* calculate the inverse of p and q (used for chinese remainder theorem)*/ ++ mpi_invm(u, p, q ); ++ } ++ ++ ec = 0; ++ ++ if( DBG_CIPHER ) ++ { ++ log_mpidump(" p= ", p ); ++ log_mpidump(" q= ", q ); ++ log_mpidump(" n= ", n ); ++ log_mpidump(" e= ", e ); ++ log_mpidump(" d= ", d ); ++ log_mpidump(" u= ", u ); ++ } ++ ++err: ++ ++ gcry_mpi_release (p1); ++ gcry_mpi_release (q1); ++ gcry_mpi_release (g); ++ gcry_mpi_release (minp); ++ gcry_mpi_release (mindiff); ++ gcry_mpi_release (diff); ++ ++ sk->n = n; ++ sk->e = e; ++ sk->p = p; ++ sk->q = q; ++ sk->d = d; ++ sk->u = u; ++ ++ /* Now we can test our keys. */ ++ if (ec || (!testparms && test_keys (sk, nbits - 64))) ++ { ++ gcry_mpi_release (sk->n); sk->n = NULL; ++ gcry_mpi_release (sk->e); sk->e = NULL; ++ gcry_mpi_release (sk->p); sk->p = NULL; ++ gcry_mpi_release (sk->q); sk->q = NULL; ++ gcry_mpi_release (sk->d); sk->d = NULL; ++ gcry_mpi_release (sk->u); sk->u = NULL; ++ if (!ec) ++ { ++ fips_signal_error ("self-test after key generation failed"); ++ return GPG_ERR_SELFTEST_FAILED; ++ } ++ } ++ ++ return ec; ++} ++ ++ + /* Helper for generate_x931. */ + static gcry_mpi_t + gen_x931_parm_xp (unsigned int nbits) +@@ -812,7 +1085,7 @@ rsa_generate_ext (int algo, unsigned int + } + } + +- if (deriveparms || use_x931 || fips_mode ()) ++ if (deriveparms || use_x931) + { + int swapped; + ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped); +@@ -841,8 +1114,14 @@ rsa_generate_ext (int algo, unsigned int + transient_key = 1; + gcry_sexp_release (l1); + } ++ deriveparms = (genparms? ++ gcry_sexp_find_token (genparms, "test-parms", 0) : NULL); + /* Generate. */ +- ec = generate_std (&sk, nbits, evalue, transient_key); ++ if (deriveparms || fips_mode()) ++ ec = generate_fips (&sk, nbits, evalue, deriveparms, transient_key); ++ else ++ ec = generate_std (&sk, nbits, evalue, transient_key); ++ gcry_sexp_release (deriveparms); + } + + if (!ec) +diff -up libgcrypt-1.5.3/src/g10lib.h.fips-keygen libgcrypt-1.5.3/src/g10lib.h +--- libgcrypt-1.5.3/src/g10lib.h.fips-keygen 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/src/g10lib.h 2014-10-21 15:05:59.459190556 +0200 +@@ -195,6 +195,9 @@ gpg_err_code_t _gcry_generate_fips186_3_ + int *r_counter, + void **r_seed, size_t *r_seedlen, int *r_hashalgo); + ++gpg_err_code_t _gcry_fips186_4_prime_check ++ (const gcry_mpi_t x, unsigned int bits); ++ + + /* Replacements of missing functions (missing-string.c). */ + #ifndef HAVE_STPCPY +diff -up libgcrypt-1.5.3/tests/keygen.c.fips-keygen libgcrypt-1.5.3/tests/keygen.c +--- libgcrypt-1.5.3/tests/keygen.c.fips-keygen 2014-10-21 15:05:59.424189766 +0200 ++++ libgcrypt-1.5.3/tests/keygen.c 2014-10-21 15:05:59.459190556 +0200 +@@ -190,12 +190,12 @@ check_rsa_keys (void) + + + if (verbose) +- fprintf (stderr, "creating 1024 bit RSA key with e=257\n"); ++ fprintf (stderr, "creating 1024 bit RSA key with e=65539\n"); + rc = gcry_sexp_new (&keyparm, + "(genkey\n" + " (rsa\n" + " (nbits 4:1024)\n" +- " (rsa-use-e 3:257)\n" ++ " (rsa-use-e 5:65539)\n" + " ))", 0, 1); + if (rc) + die ("error creating S-expression: %s\n", gpg_strerror (rc)); +@@ -204,7 +204,7 @@ check_rsa_keys (void) + if (rc) + die ("error generating RSA key: %s\n", gpg_strerror (rc)); + +- check_generated_rsa_key (key, 257); ++ check_generated_rsa_key (key, 65539); + gcry_sexp_release (key); + + if (verbose) diff --git a/SPECS/libgcrypt.spec b/SPECS/libgcrypt.spec index c7de2a1..61176a7 100644 --- a/SPECS/libgcrypt.spec +++ b/SPECS/libgcrypt.spec @@ -1,6 +1,6 @@ Name: libgcrypt Version: 1.5.3 -Release: 4%{?dist} +Release: 12%{?dist} URL: http://www.gnupg.org/ Source0: libgcrypt-%{version}-hobbled.tar.xz # The original libgcrypt sources now contain potentially patented ECC @@ -16,11 +16,8 @@ Patch1: libgcrypt-1.5.0-noecc.patch Patch2: libgcrypt-1.5.0-use-fipscheck.patch # fix tests in the FIPS mode, fix the FIPS-186-3 DSA keygen Patch5: libgcrypt-1.5.0-tests.patch -# add configurable source of RNG seed and seed by default -# from /dev/urandom in the FIPS mode -Patch6: libgcrypt-1.5.0-fips-cfgrandom.patch # make the FIPS-186-3 DSA CAVS testable -Patch7: libgcrypt-1.5.0-fips-cavs.patch +Patch7: libgcrypt-1.5.3-fips-cavs.patch # fix for memory leaks an other errors found by Coverity scan Patch9: libgcrypt-1.5.0-leak.patch # use poll instead of select when gathering randomness @@ -35,6 +32,19 @@ Patch15: libgcrypt-1.5.3-pbkdf-speedup.patch # with files generated with buggy version set environment # varible GCRYPT_WHIRLPOOL_BUG Patch16: libgcrypt-1.5.3-whirlpool-bug.patch +# FIPS DRBG +Patch17: libgcrypt-1.5.3-drbg.patch +# Run the FIPS mode initialization in the shared library constructor +Patch18: libgcrypt-1.5.3-fips-ctor.patch +# Make it possible to run the test suite in the FIPS mode +Patch19: libgcrypt-1.5.3-fips-test.patch +# Make the FIPS RSA keygen to be FIPS 186-4 compliant +Patch20: libgcrypt-1.5.3-rsa-fips-keygen.patch +# add configurable source of RNG seed and seed by default +# from /dev/urandom in the FIPS mode +Patch21: libgcrypt-1.5.3-fips-cfgrandom.patch +# update the selftests for new FIPS requirements +Patch22: libgcrypt-1.5.3-fips-reqs.patch %define gcrylibdir %{_libdir} @@ -73,7 +83,6 @@ applications using libgcrypt. %patch1 -p1 -b .noecc %patch2 -p1 -b .use-fipscheck %patch5 -p1 -b .tests -%patch6 -p1 -b .cfgrandom %patch7 -p1 -b .cavs %patch9 -p1 -b .leak %patch11 -p1 -b .use-poll @@ -81,6 +90,12 @@ applications using libgcrypt. %patch13 -p1 -b .gccopt %patch15 -p1 -b .pbkdf-speedup %patch16 -p1 -b .whirlpool-bug +%patch17 -p1 -b .drbg +%patch18 -p1 -b .fips-ctor +%patch19 -p1 -b .fips-test +%patch20 -p1 -b .fips-keygen +%patch21 -p1 -b .cfgrandom +%patch22 -p1 -b .fips-reqs %build %configure --disable-static \ @@ -182,6 +197,27 @@ exit 0 %doc COPYING %changelog +* Wed Jan 14 2015 Tomáš Mráz 1.5.3-12 +- use macros instead of inline functions in the public header + +* Fri Dec 12 2014 Tomáš Mráz 1.5.3-11 +- do not initialize secure memory during the selftest + +* Fri Nov 14 2014 Tomáš Mráz 1.5.3-10 +- update the selftests for the new FIPS requirements + +* Fri Oct 31 2014 Tomáš Mráz 1.5.3-9 +- apply the fips-cfgrandom change also to the drbg seeding + +* Tue Oct 21 2014 Tomáš Mráz 1.5.3-7 +- make the RSA keygen to be compliant to FIPS 186-4 in + FIPS mode + +* Fri Sep 26 2014 Tomáš Mráz 1.5.3-5 +- add FIPS DRBG implementation +- run the FIPS POST tests in shared library constructor +- make it possible to run the test suite in the FIPS mode + * Fri Jan 24 2014 Daniel Mach - 1.5.3-4 - Mass rebuild 2014-01-24