diff --git a/SOURCES/libgcrypt-1.5.3-ath-reinstall.patch b/SOURCES/libgcrypt-1.5.3-ath-reinstall.patch new file mode 100644 index 0000000..88421ba --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-ath-reinstall.patch @@ -0,0 +1,133 @@ +diff -up libgcrypt-1.5.3/src/ath.c.ath-reinstall libgcrypt-1.5.3/src/ath.c +--- libgcrypt-1.5.3/src/ath.c.ath-reinstall 2013-07-25 11:10:04.000000000 +0200 ++++ libgcrypt-1.5.3/src/ath.c 2017-02-28 14:37:15.267668432 +0100 +@@ -36,7 +36,7 @@ + #include + + #include "ath.h" +- ++#include "g10lib.h" + + + /* The interface table. */ +@@ -45,6 +45,13 @@ static struct ath_ops ops; + /* True if we should use the external callbacks. */ + static int ops_set; + ++struct lock_list ++{ ++ ath_mutex_t *lock; ++ struct lock_list *next; ++}; ++ ++static struct lock_list *reinstallable_locks; + + /* For the dummy interface. */ + #define MUTEX_UNLOCKED ((ath_mutex_t) 0) +@@ -62,6 +69,50 @@ static int ops_set; + /* The lock we take while checking for lazy lock initialization. */ + static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER; + ++static void ++add_reinstallable_lock(ath_mutex_t *lock) ++{ ++ struct lock_list *ll, *new, **ptr; ++ ++ new = gcry_calloc(1, sizeof(*new)); ++ if (!new) ++ abort(); ++ ++ for (ll = reinstallable_locks, ptr = &reinstallable_locks; ll != NULL; ptr = &ll->next, ll = ll->next) ++ { ++ if (ll->lock == lock) ++ { ++ gcry_free(new); ++ return; ++ } ++ } ++ ++ new->lock = lock; ++ *ptr = new; ++} ++ ++static void ++remove_reinstallable_lock(ath_mutex_t *lock) ++{ ++ struct lock_list *ll, **ptr; ++ ++ for (ll = reinstallable_locks, ptr = &reinstallable_locks; ll != NULL; ptr = &ll->next, ll = ll->next) ++ { ++ if (ll->lock == lock) ++ { ++ *ptr = ll->next; ++ gcry_free(ll); ++ /* we do not store duplicates */ ++ return; ++ } ++ } ++ ++#ifndef NDEBUG ++ /* lock not found, should not happen */ ++ abort(); ++#endif ++} ++ + int + ath_init (void) + { +@@ -85,7 +136,9 @@ ath_init (void) + gpg_err_code_t + ath_install (struct ath_ops *ath_ops, int check_only) + { +- if (check_only) ++ gpg_err_code_t err = 0; ++ ++ if (check_only && ops_set) + { + unsigned int option = 0; + +@@ -119,7 +172,25 @@ ath_install (struct ath_ops *ath_ops, in + else + ops_set = 0; + +- return 0; ++ if (ops_set && reinstallable_locks) ++ { ++ struct lock_list *ll; ++ ++ ath_init(); ++ for (ll = reinstallable_locks; ll != NULL;) ++ { ++ struct lock_list *prev; ++ ++ if (ath_mutex_init(ll->lock)) ++ err = GPG_ERR_NOT_SUPPORTED; ++ prev = ll; ++ ll = ll->next; ++ gcry_free(prev); ++ } ++ reinstallable_locks = NULL; ++ } ++ ++ return err; + } + + +@@ -143,6 +214,8 @@ ath_mutex_init (ath_mutex_t *lock) + { + if (ops_set) + return mutex_init (lock, 0); ++ else ++ add_reinstallable_lock(lock); + + #ifndef NDEBUG + *lock = MUTEX_UNLOCKED; +@@ -168,6 +241,8 @@ ath_mutex_destroy (ath_mutex_t *lock) + (*ops.mutex_unlock) (&check_init_lock); + return (*ops.mutex_destroy) (lock); + } ++ else ++ remove_reinstallable_lock(lock); + + #ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); diff --git a/SOURCES/libgcrypt-1.5.3-drbg-cavs.patch b/SOURCES/libgcrypt-1.5.3-drbg-cavs.patch new file mode 100644 index 0000000..51ae70d --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-drbg-cavs.patch @@ -0,0 +1,972 @@ +diff -up libgcrypt-1.5.3/random/drbg.c.drbg-cavs libgcrypt-1.5.3/random/drbg.c +--- libgcrypt-1.5.3/random/drbg.c.drbg-cavs 2017-02-28 14:28:55.695906569 +0100 ++++ libgcrypt-1.5.3/random/drbg.c 2017-02-28 14:28:55.700906686 +0100 +@@ -2130,6 +2130,16 @@ gcry_drbg_cavs_test (struct gcry_drbg_te + if (ret) + goto outbuf; + ++ if (test->entropyrsd) ++ { ++ gcry_drbg_string_fill (&testentropy, test->entropyrsd, ++ test->entropyrsdlen); ++ gcry_drbg_string_fill (&addtl, test->addtlrsd, ++ test->addtlrsdlen); ++ if (gcry_drbg_reseed (drbg, &addtl)) ++ goto outbuf; ++ } ++ + gcry_drbg_string_fill (&addtl, test->addtla, test->addtllen); + if (test->entpra) + { +diff -up libgcrypt-1.5.3/random/random.h.drbg-cavs libgcrypt-1.5.3/random/random.h +--- libgcrypt-1.5.3/random/random.h.drbg-cavs 2017-02-28 14:28:55.686906357 +0100 ++++ libgcrypt-1.5.3/random/random.h 2017-02-28 14:28:55.700906686 +0100 +@@ -69,6 +69,10 @@ struct gcry_drbg_test_vector + size_t perslen; + unsigned char *expected; + size_t expectedlen; ++ unsigned char *entropyrsd; ++ size_t entropyrsdlen; ++ unsigned char *addtlrsd; ++ size_t addtlrsdlen; + }; + + gpg_err_code_t gcry_drbg_cavs_test (struct gcry_drbg_test_vector *test, +diff -up libgcrypt-1.5.3/tests/cavs_driver.pl.drbg-cavs libgcrypt-1.5.3/tests/cavs_driver.pl +--- libgcrypt-1.5.3/tests/cavs_driver.pl.drbg-cavs 2017-02-28 14:28:55.674906074 +0100 ++++ libgcrypt-1.5.3/tests/cavs_driver.pl 2017-02-28 14:41:46.086048300 +0100 +@@ -192,15 +192,17 @@ my $rsa_derive; + # Sign a message with RSA + # $1: data to be signed in hex form + # $2: Hash algo +-# $3: Key file in PEM format with the private key ++# $3: PSS flag ++# $4: Key file in PEM format with the private key + # return: digest in hex format + my $rsa_sign; + + # Verify a message with RSA + # $1: data to be verified in hex form + # $2: hash algo +-# $3: file holding the public RSA key in PEM format +-# $4: file holding the signature in binary form ++# $3: PSS flag ++# $4: file holding the public RSA key in PEM format ++# $5: file holding the signature in binary form + # return: 1 == verified / 0 == not verified + my $rsa_verify; + +@@ -329,6 +331,8 @@ my $rsa_keygen; + + my $rsa_keygen_kat; + ++my $drbg_kat; ++ + ################################################################ + ##### OpenSSL interface functions + ################################################################ +@@ -350,9 +354,10 @@ sub openssl_encdec($$$$$) { + return bin2hex($data); + } + +-sub openssl_rsa_sign($$$) { ++sub openssl_rsa_sign($$$$) { + my $data = shift; + my $cipher = shift; ++ my $pss = shift; # unsupported + my $keyfile = shift; + + $data=hex2bin($data); +@@ -365,6 +370,7 @@ sub openssl_rsa_sign($$$) { + sub openssl_rsa_verify($$$$) { + my $data = shift; + my $cipher = shift; ++ my $pss = shift; # unsupported + my $keyfile = shift; + my $sigfile = shift; + +@@ -497,27 +503,38 @@ sub libgcrypt_rsa_keygen_kat($$$$) { + } + + +-sub libgcrypt_rsa_sign($$$) { ++sub libgcrypt_rsa_sign($$$$) { + my $data = shift; + my $hashalgo = shift; ++ my $pss = shift; + my $keyfile = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; + ++ if ($pss) { ++ return pipe_through_program($data, ++ "fipsdrv --pss --algo $hashalgo --key $keyfile rsa-sign"); ++ } + return pipe_through_program($data, + "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign"); + } + +-sub libgcrypt_rsa_verify($$$$) { ++sub libgcrypt_rsa_verify($$$$$) { + my $data = shift; + my $hashalgo = shift; ++ my $pss = shift; + my $keyfile = shift; + my $sigfile = shift; + + die "ARCFOUR not available for RSA" if $opt{'R'}; ++ ++ if ($pss) { ++ $data = pipe_through_program($data, ++ "fipsdrv --pss --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify"); ++ } else { + $data = pipe_through_program($data, + "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify"); +- ++ } + # Parse through the output information + return ($data =~ /GOOD signature/); + } +@@ -543,6 +560,16 @@ sub libgcrypt_hash($$) { + return pipe_through_program($pt, $program); + } + ++sub libgcrypt_hash_mct($$) { ++ my $pt = shift; ++ my $hashalgo = shift; ++ ++ my $program = "fipsdrv --algo $hashalgo --loop digest"; ++ die "ARCFOUR not available for hashes" if $opt{'R'}; ++ ++ return pipe_through_program($pt, $program); ++} ++ + sub libgcrypt_state_cipher($$$$$) { + my $cipher = shift; + my $enc = (shift) ? "encrypt": "decrypt"; +@@ -693,6 +720,35 @@ sub libgcrypt_dsa_verify($$$$) { + return ($ret =~ /GOOD signature/); + } + ++sub libgcrypt_drbg_kat($$$$$$$$$$$$$$$$$) { ++ my $mode = shift; ++ my $cipher = shift; ++ my $pr = shift; ++ my $ent = shift; ++ my $entlen = shift; ++ my $nonce = shift; ++ my $noncelen = shift; ++ my $entrs = shift; ++ my $addtlrs = shift; ++ my $entpra = shift; ++ my $entprb = shift; ++ my $addtla = shift; ++ my $addtlb = shift; ++ my $addtllen = shift; ++ my $pers = shift; ++ my $perslen = shift; ++ my $expectedlen = shift; ++ ++ my $entprlen = $entlen; ++ ++ # concatenate entropy and nonce ++ $ent .= $nonce; ++ $entlen = $entlen + $noncelen; ++ ++ return lc(pipe_through_program("$mode\n$pr\n$entlen\n$ent\n$perslen\n$pers\n$expectedlen\n$addtllen\n$entrs\n$addtlrs\n$addtla\n$addtlb\n$entprlen\n$entpra\n$entprb\n", "./fipsdrv --algo $cipher drbg")); ++} ++ ++ + ######### End of libgcrypt implementation ################ + + ################################################################ +@@ -1468,13 +1524,17 @@ sub hash_mct($$) { + my $md0=$pt; + my $md1=$pt; + my $md2=$pt; +- for (my $i=0; $i<1000; ++$i) { +- #print STDERR "outer loop $j; inner loop $i\n"; +- my $mi= $md0 . $md1 . $md2; +- $md0=$md1; +- $md1=$md2; +- $md2 = &$hash($mi, $cipher); +- $md2 =~ s/\n//; ++ if ($opt{'I'} && $opt{'I'} eq 'libgcrypt') { ++ $md2 = &libgcrypt_hash_mct($pt, $cipher); ++ } else { ++ for (my $i=0; $i<1000; ++$i) { ++ #print STDERR "outer loop $j; inner loop $i\n"; ++ my $mi= $md0 . $md1 . $md2; ++ $md0=$md1; ++ $md1=$md2; ++ $md2 = &$hash($mi, $cipher); ++ $md2 =~ s/\n//; ++ } + } + $out .= "MD = $md2\n\n"; + $pt=$md2; +@@ -1483,21 +1543,65 @@ sub hash_mct($$) { + return $out; + } + ++sub drbg_kat_driver($$$$$$$$$$$$$$$$$) { ++ my $mode = shift; ++ my $cipher = shift; ++ my $pr = shift; ++ my $ent = shift; ++ my $entlen = shift; ++ my $nonce = shift; ++ my $noncelen = shift; ++ my $entrs = shift; ++ my $addtlrs = shift; ++ my $entpra = shift; ++ my $entprb = shift; ++ my $addtla = shift; ++ my $addtlb = shift; ++ my $addtllen = shift; ++ my $pers = shift; ++ my $perslen = shift; ++ my $expectedlen = shift; ++ ++ my $out = ""; ++ ++ $out .= "ReturnedBits = " . &$drbg_kat($mode, ++ $cipher, ++ $pr, ++ $ent, ++ $entlen, ++ $nonce, ++ $noncelen, ++ $entrs, ++ $addtlrs, ++ $entpra, ++ $entprb, ++ $addtla, ++ $addtlb, ++ $addtllen, ++ $pers, ++ $perslen, ++ $expectedlen) . "\n"; ++ ++ return $out; ++} ++ + # RSA SigGen test + # $1: Message to be signed in hex form + # $2: Hash algorithm +-# $3: file name with RSA key in PEM form ++# $3: Use PSS ++# $4: file name with RSA key in PEM form + # return: string formatted as expected by CAVS +-sub rsa_siggen($$$) { ++sub rsa_siggen($$$$) { + my $data = shift; + my $cipher = shift; ++ my $pss = shift; + my $keyfile = shift; + + my $out = ""; + + $out .= "SHAAlg = $cipher\n"; + $out .= "Msg = $data\n"; +- $out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n"; ++ $out .= "S = " . &$rsa_sign($data, lc($cipher), $pss, $keyfile) . "\n"; + + return $out; + } +@@ -1505,13 +1609,15 @@ sub rsa_siggen($$$) { + # RSA SigVer test + # $1: Message to be verified in hex form + # $2: Hash algoritm +-# $3: Signature of message in hex form +-# $4: n of the RSA key in hex in hex form +-# $5: e of the RSA key in hex in hex form ++# $3: Use PSS ++# $4: Signature of message in hex form ++# $5: n of the RSA key in hex in hex form ++# $6: e of the RSA key in hex in hex form + # return: string formatted as expected by CAVS +-sub rsa_sigver($$$$$) { ++sub rsa_sigver($$$$$$) { + my $data = shift; + my $cipher = shift; ++ my $pss = shift; + my $signature = shift; + my $n = shift; + my $e = shift; +@@ -1534,7 +1640,7 @@ sub rsa_sigver($$$$$) { + print FH hex2bin($signature); + close FH; + +- $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n"); ++ $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $pss, $keyfile, $sigfile) ? "P\n" : "F\n"); + + unlink($keyfile); + unlink($sigfile); +@@ -1905,13 +2011,14 @@ sub rsa_keygen_driver($$) { + # $2 p in hex form + # $3 q in hex form + # return: string formatted as expected by CAVS +-sub rsa_keygen_kat_driver($$$) { ++sub rsa_keygen_kat_driver($$$$) { + my $mod = shift; ++ my $e = shift; + my $p = shift; + my $q = shift; + + my $out = ""; +- my $ret = &$rsa_keygen_kat($mod, $p, $q); ++ my $ret = &$rsa_keygen_kat($mod, $e, $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)); +@@ -1999,8 +2106,24 @@ sub parse($$) { + my $xq1 = ""; + my $xq2 = ""; + my $Xq = ""; ++ my $pr = 0; ++ my $ent = ""; ++ my $entlen = 0; ++ my $nonce = ""; ++ my $noncelen = 0; ++ my $entrs = ""; ++ my $addtlrs = ""; ++ my $entpra = "x"; ++ my $entprb = "x"; ++ my $addtla = "x"; ++ my $addtlb = "x"; ++ my $addtllen = 0; ++ my $pers = ""; ++ my $perslen = 0; ++ my $expectedlen = 0; + + my $mode = ""; ++ my $pss = 0; + + open(IN, "<$infile"); + while() { +@@ -2029,7 +2152,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|KeyGen - Random Probably Prime|KeyPair|PQGVer)/) { ++ 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|DRBG800-90A)/) { + if ($tmpline =~ /CBC/) { $mode="cbc"; } + elsif ($tmpline =~ /ECB/) { $mode="ecb"; } + elsif ($tmpline =~ /OFB/) { $mode="ofb"; } +@@ -2078,7 +2201,11 @@ sub parse($$) { + + if ($tt == 0) { + ##### Identify the test type +- if ($tmpline =~ /KeyGen - Random Probably Prime Known Answer Test/) { ++ if ($tmpline =~ /DRBG800-90A/) { ++ $tt = 20; ++ die "Interface function drbg_kat for DRBG KAT not defined for tested library" ++ if (!defined($drbg_kat)); ++ } elsif ($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)); +@@ -2123,10 +2250,16 @@ sub parse($$) { + die "Interface function state_rng for RNG KAT not defined for tested library" + if (!defined($state_rng)); + } elsif ($tmpline =~ /SigVer/ ) { ++ if ($tmpline =~ /RSASSA-PSS/) { ++ $pss = 1; ++ } + $tt = 6; + die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library" + if (!defined($rsa_verify) || !defined($gen_rsakey)); + } elsif ($tmpline =~ /SigGen/ ) { ++ if ($tmpline =~ /RSASSA-PSS/) { ++ $pss = 1; ++ } + $tt = 5; + die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library" + if (!defined($rsa_sign) || !defined($gen_rsakey)); +@@ -2252,7 +2385,7 @@ sub parse($$) { + $out .= "G = " . $pqg{'G'} . "\n\n"; + } + } +- elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests ++ 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 +@@ -2277,10 +2410,21 @@ sub parse($$) { + $n=$1; + } + elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests +- $e=$1; + if ($tt == 19) { ++ if ($modulus ne "" && ++ $e ne "" && ++ $prandom ne "") { ++ $out .= rsa_keygen_kat_driver($modulus, ++ $e, ++ $prandom, ++ "00"); ++ $prandom = ""; ++ $qrandom = ""; ++ $e = ""; ++ } + $out .= $line . "\n"; # print it + } ++ $e=$1; + } + elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests + die "S seen twice - input file crap" if ($signature ne ""); +@@ -2306,6 +2450,89 @@ sub parse($$) { + if ($tlen ne ""); + $tlen=$1; + } ++ elsif ($tt == 20) { ++ if ($line =~ /Hash_DRBG/) { # HASH DRBG request ++ $mode = "hash"; ++ } ++ elsif ($line =~ /HMAC_DRBG/) { # HMAC DRBG request ++ $mode = "hmac"; ++ } ++ elsif ($line =~ /CTR_DRBG/) { # CTR DRBG request ++ $mode = "ctr"; ++ } ++ elsif ($line =~ /^\[SHA-1\]/) { ++ $cipher= "sha-1"; ++ } ++ elsif ($line =~ /^\[SHA-256\]/) { ++ $cipher= "sha-256"; ++ } ++ elsif ($line =~ /^\[SHA-384\]/) { ++ $cipher= "sha-384"; ++ } ++ elsif ($line =~ /^\[SHA-512\]/) { ++ $cipher= "sha-512"; ++ } ++ elsif ($line =~ /^\[AES-128 use df\]/) { ++ $cipher= "aes-128"; ++ } ++ elsif ($line =~ /^\[AES-192 use df\]/) { ++ $cipher= "aes-192"; ++ } ++ elsif ($line =~ /^\[AES-256 use df\]/) { ++ $cipher= "aes-256"; ++ } ++ elsif ($line =~ /^\[PredictionResistance\s*=\s*True\]/) { ++ $pr = 1; ++ } ++ elsif ($line =~ /^\[PredictionResistance\s*=\s*False\]/) { ++ $pr = 0; ++ } ++ elsif ($line =~ /^\[EntropyInputLen\s*=\s*(.*)\]/) { ++ $entlen = $1; ++ } ++ elsif ($line =~ /^\[NonceLen\s*=\s*(.*)\]/) { ++ $noncelen = $1; ++ } ++ elsif ($line =~ /^\[PersonalizationStringLen\s*=\s*(.*)\]/) { ++ $perslen = $1; ++ } ++ elsif ($line =~ /^\[AdditionalInputLen\s*=\s*(.*)\]/) { ++ $addtllen = $1; ++ } ++ elsif ($line =~ /^\[ReturnedBitsLen\s*=\s*(.*)\]/) { ++ $expectedlen = $1; ++ } ++ elsif ($line =~ /^EntropyInput\s*=\s*(.*)/) { ++ $ent = $1; ++ } ++ elsif ($line =~ /^EntropyInputReseed\s*=\s*(.*)/) { ++ $entrs = $1; ++ } ++ elsif ($line =~ /^Nonce\s*=\s*(.*)/) { ++ $nonce = $1; ++ } ++ elsif ($line =~ /^PersonalizationString\s*=\s*(.*)/) { ++ $pers = $1; ++ } ++ elsif ($line =~ /^AdditionalInput\s*=\s*(.*)/) { ++ if ($addtla eq "x") { ++ $addtla = $1; ++ } else { ++ $addtlb = $1; ++ } ++ } ++ elsif ($line =~ /^EntropyInputPR\s*=\s*(.*)/) { ++ if ($entpra eq "x") { ++ $entpra = $1; ++ } else { ++ $entprb = $1; ++ } ++ } ++ elsif ($line =~ /^AdditionalInputReseed\s*=\s*(.*)/) { ++ $addtlrs = $1; ++ } ++ $out .= $line . "\n"; # print it ++ } + elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA KeyPair + die "N seen twice - check input file" + if ($capital_n); +@@ -2396,10 +2623,6 @@ sub parse($$) { + $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"; + } +@@ -2442,13 +2665,13 @@ sub parse($$) { + } + elsif ($tt == 5) { + if ($pt ne "" && $cipher ne "" && $rsa_keyfile ne "") { +- $out .= rsa_siggen($pt, $cipher, $rsa_keyfile); ++ $out .= rsa_siggen($pt, $cipher, $pss, $rsa_keyfile); + $pt = ""; + } + } + elsif ($tt == 6) { + if ($pt ne "" && $cipher ne "" && $signature ne "" && $n ne "" && $e ne "") { +- $out .= rsa_sigver($pt, $cipher, $signature, $n, $e); ++ $out .= rsa_sigver($pt, $cipher, $pss, $signature, $n, $e); + $pt = ""; + $signature = ""; + } +@@ -2635,6 +2858,37 @@ sub parse($$) { + $e = ""; + } + } ++ elsif ($tt == 20) { ++ if (($pr == 1 && $entpra ne "x" && $entprb ne "x") || ++ ($pr == 0 && $addtla ne "x" && $addtlb ne "x")) { ++ $out .= drbg_kat_driver($mode, ++ $cipher, ++ $pr, ++ $ent, ++ $entlen, ++ $nonce, ++ $noncelen, ++ $entrs, ++ $addtlrs, ++ $entpra, ++ $entprb, ++ $addtla, ++ $addtlb, ++ $addtllen, ++ $pers, ++ $perslen, ++ $expectedlen); ++ $entpra = "x"; ++ $entprb = "x"; ++ $addtla = "x"; ++ $addtlb = "x"; ++ $ent = ""; ++ $nonce = ""; ++ $pers = ""; ++ $entrs = ""; ++ $addtlrs = ""; ++ } ++ } + elsif ($tt > 0) { + die "Test case $tt not defined"; + } +@@ -2701,6 +2955,7 @@ sub main() { + $dsa_genpubkey = \&libgcrypt_dsa_genpubkey; + $rsa_keygen = \&libgcrypt_rsa_keygen; + $rsa_keygen_kat = \&libgcrypt_rsa_keygen_kat; ++ $drbg_kat = \&libgcrypt_drbg_kat; + } else { + die "Invalid interface option given"; + } +diff -up libgcrypt-1.5.3/tests/fipsdrv.c.drbg-cavs libgcrypt-1.5.3/tests/fipsdrv.c +--- libgcrypt-1.5.3/tests/fipsdrv.c.drbg-cavs 2017-02-28 14:28:55.674906074 +0100 ++++ libgcrypt-1.5.3/tests/fipsdrv.c 2017-02-28 14:43:28.320456712 +0100 +@@ -22,6 +22,7 @@ + #endif + #include + #include ++#include + #include + #include + #include +@@ -893,8 +894,10 @@ 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); ++ while (*p) { ++ *p = tolower(*p); ++ ++p; ++ } + p = buf; + if (no_lz && p[0] == '0' && p[1] == '0' && p[2]) + p += 2; +@@ -1256,6 +1259,46 @@ run_digest (int digest_algo, const void + gcry_md_close (hd); + } + ++/* Run inner loop of digest mct operation. */ ++static void ++run_digest_mct_loop (int digest_algo, const void *data, size_t datalen, int iter) ++{ ++ gpg_error_t err; ++ gcry_md_hd_t hd; ++ const unsigned char *digest; ++ unsigned int digestlen; ++ int i; ++ unsigned char *buf; ++ ++ err = gcry_md_open (&hd, digest_algo, 0); ++ if (err) ++ die ("gcry_md_open failed for algo %d: %s\n", ++ digest_algo, gpg_strerror (err)); ++ ++ digestlen = gcry_md_get_algo_dlen (digest_algo); ++ if (digestlen != datalen) ++ die ("Unexpected seed size %u for Hash mct algo %d\n", datalen, digest_algo); ++ ++ buf = malloc (3*datalen); ++ if (!buf) ++ die ("Buffer allocation failed\n"); ++ ++ memcpy (buf, data, datalen); ++ memcpy (buf + datalen, data, datalen); ++ memcpy (buf + 2*datalen, data, datalen); ++ ++ for (i = 0; i < iter; ++i) ++ { ++ gcry_md_reset (hd); ++ gcry_md_write (hd, buf, 3*datalen); ++ digest = gcry_md_read (hd, digest_algo); ++ memmove (buf, buf + datalen, 2*datalen); ++ memcpy (buf + 2*datalen, digest, datalen); ++ } ++ print_buffer (digest, digestlen); ++ gcry_md_close (hd); ++} ++ + + /* Run a HMAC operation. */ + static void +@@ -1403,7 +1446,7 @@ run_rsa_keygen (const void *data, size_t + gcry_sexp_release (l1); + if (!mpi) + die ("parameter %c missing in private-key\n", parmlist[idx]); +- print_mpi_line (mpi, 1); ++ print_mpi_line (mpi, parmlist[idx] != 'd'); + gcry_mpi_release (mpi); + } + +@@ -1592,7 +1635,7 @@ run_rsa_gen (int keysize, int pubexp) + encoded KEYFILE and the hash algorithm HASHALGO. */ + static void + run_rsa_sign (const void *data, size_t datalen, +- int hashalgo, int pkcs1, const char *keyfile) ++ int hashalgo, int pkcs1, int pss, const char *keyfile) + + { + gpg_error_t err; +@@ -1616,6 +1659,20 @@ run_rsa_sign (const void *data, size_t d + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } ++ else if (pss) ++ { ++ unsigned char hash[64]; ++ unsigned int hashsize; ++ ++ hashsize = gcry_md_get_algo_dlen (hashalgo); ++ if (!hashsize || hashsize > sizeof hash) ++ die ("digest too long for buffer or unknown hash algorithm\n"); ++ gcry_md_hash_buffer (hashalgo, hash, data, datalen); ++ err = gcry_sexp_build (&s_data, NULL, ++ "(data (flags pss)(hash %s %b))", ++ gcry_md_algo_name (hashalgo), ++ (int)hashsize, hash); ++ } + else + { + gcry_mpi_t tmp; +@@ -1683,7 +1740,7 @@ run_rsa_sign (const void *data, size_t d + binary signature in SIGFILE. */ + static void + run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1, +- const char *keyfile, const char *sigfile) ++ int pss, const char *keyfile, const char *sigfile) + + { + gpg_error_t err; +@@ -1703,6 +1760,20 @@ run_rsa_verify (const void *data, size_t + gcry_md_algo_name (hashalgo), + (int)hashsize, hash); + } ++ else if (pss) ++ { ++ unsigned char hash[64]; ++ unsigned int hashsize; ++ ++ hashsize = gcry_md_get_algo_dlen (hashalgo); ++ if (!hashsize || hashsize > sizeof hash) ++ die ("digest too long for buffer or unknown hash algorithm\n"); ++ gcry_md_hash_buffer (hashalgo, hash, data, datalen); ++ err = gcry_sexp_build (&s_data, NULL, ++ "(data (flags pss)(hash %s %b))", ++ gcry_md_algo_name (hashalgo), ++ (int)hashsize, hash); ++ } + else + { + gcry_mpi_t tmp; +@@ -2220,7 +2291,150 @@ run_dsa_verify (const void *data, size_t + gcry_sexp_release (s_data); + } + ++struct gcry_drbg_test_vector ++{ ++ uint32_t 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; ++ unsigned char *entropyrsd; ++ size_t entropyrsdlen; ++ unsigned char *addtlrsd; ++ size_t addtlrsdlen; ++ }; ++ ++static uint32_t ++decode_drbg_flags(const char *algo, const char *mode, const char *pr) ++{ ++ uint32_t flags = 0; ++ ++ if (*pr == '1') ++ flags = GCRY_DRBG_PREDICTION_RESIST; ++ ++ if (!strcmp(algo, "sha-1")) ++ flags |= GCRY_DRBG_HASHSHA1; ++ else if (!strcmp(algo, "sha-256")) ++ flags |= GCRY_DRBG_HASHSHA256; ++ else if (!strcmp(algo, "sha-384")) ++ flags |= GCRY_DRBG_HASHSHA384; ++ else if (!strcmp(algo, "sha-512")) ++ flags |= GCRY_DRBG_HASHSHA512; ++ else if (!strcmp(algo, "aes-128")) ++ flags |= GCRY_DRBG_SYM128; ++ else if (!strcmp(algo, "aes-192")) ++ flags |= GCRY_DRBG_SYM192; ++ else if (!strcmp(algo, "aes-256")) ++ flags |= GCRY_DRBG_SYM256; ++ ++ if (!strcmp(mode, "hmac")) ++ flags |= GCRY_DRBG_HMAC; ++ else if (!strcmp(mode, "ctr")) ++ flags |= GCRY_DRBG_CTRAES; ++ ++ return flags; ++} ++ ++static void ++run_drbg_test (const char *algo, void *data, size_t datalen) ++{ ++ char *ptr = data; ++ char *mode; ++ char *pr; ++ char *entlen; ++ char *ent; ++ char *perslen; ++ char *pers; ++ char *expectedlen; ++ char *addtllen; ++ char *entrsd; ++ char *addtlrsd; ++ char *addtla; ++ char *addtlb; ++ char *entprlen; ++ char *entpra; ++ char *entprb; ++ unsigned char *buf; ++ size_t len; ++ struct gcry_drbg_test_vector vect; ++ ++ mode = strsep(&ptr, "\n"); ++ pr = strsep(&ptr, "\n"); ++ entlen = strsep(&ptr, "\n"); ++ ent = strsep(&ptr, "\n"); ++ perslen = strsep(&ptr, "\n"); ++ pers = strsep(&ptr, "\n"); ++ expectedlen = strsep(&ptr, "\n"); ++ addtllen = strsep(&ptr, "\n"); ++ entrsd = strsep(&ptr, "\n"); ++ addtlrsd = strsep(&ptr, "\n"); ++ addtla = strsep(&ptr, "\n"); ++ addtlb = strsep(&ptr, "\n"); ++ entprlen = strsep(&ptr, "\n"); ++ entpra = strsep(&ptr, "\n"); ++ entprb = strsep(&ptr, "\n"); ++ ++ if (entprb == NULL) { ++ fprintf(stderr, "ERROR - Missing input data\n"); ++ return; ++ } ++ ++ vect.flags = decode_drbg_flags(algo, mode, pr); ++ ++ vect.entropy = hex2buffer(ent, &len); ++ vect.entropylen = atoi(entlen) / 8; ++ if (len != vect.entropylen) { ++ fprintf(stderr, "ERROR - inconsistent input data\n"); ++ return; ++ } ++ vect.pers = hex2buffer(pers, &len); ++ vect.perslen = atoi(perslen) / 8; ++ if (len != vect.perslen) { ++ fprintf(stderr, "ERROR - inconsistent input data\n"); ++ return; ++ } ++ vect.expectedlen = atoi(expectedlen) / 8; ++ vect.expected = NULL; ++ vect.addtlrsdlen = vect.addtllen = atoi(addtllen) / 8; ++ vect.addtla = hex2buffer(addtla, &len); ++ vect.addtlb = hex2buffer(addtlb, &len); ++ vect.entropyrsdlen = vect.entprlen = atoi(entprlen) / 8; ++ vect.entpra = hex2buffer(entpra, &len); ++ vect.entprb = hex2buffer(entprb, &len); ++ if (*entrsd != '\0') { ++ vect.entropyrsd = hex2buffer(entrsd, &len); ++ if (len != vect.entropyrsdlen) { ++ fprintf(stderr, "ERROR - inconsistent input data\n"); ++ return; ++ } ++ if (*addtlrsd != '\0') { ++ vect.addtlrsd = hex2buffer(addtlrsd, &len); ++ if (len != vect.addtlrsdlen) { ++ fprintf(stderr, "ERROR - inconsistent input data\n"); ++ return; ++ } ++ } else { ++ vect.addtlrsd = NULL; ++ } ++ } else { ++ vect.entropyrsd = NULL; ++ vect.addtlrsd = NULL; ++ } ++ ++ buf = gcry_xmalloc(vect.expectedlen); + ++ gcry_control(75, &vect, buf); ++ ++ print_data_line(buf, vect.expectedlen); ++} + + + static void +@@ -2251,6 +2465,7 @@ usage (int show_help) + " --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" ++ " --pss Use PKCS#1 PSS encoding\n" + " --mct-server Run a monte carlo test server\n" + " --loop Enable random loop mode\n" + " --progress Print pogress indicators\n" +@@ -2268,6 +2483,7 @@ main (int argc, char **argv) + int no_fips = 0; + int progress = 0; + int use_pkcs1 = 0; ++ int use_pss = 0; + const char *mode_string; + const char *key_string = NULL; + const char *iv_string = NULL; +@@ -2398,6 +2614,11 @@ main (int argc, char **argv) + use_pkcs1 = 1; + argc--; argv++; + } ++ else if (!strcmp (*argv, "--pss")) ++ { ++ use_pss = 1; ++ argc--; argv++; ++ } + else if (!strcmp (*argv, "--mct-server")) + { + mct_server = 1; +@@ -2414,7 +2635,10 @@ main (int argc, char **argv) + usage (0); + mode_string = *argv; + +- if (!strcmp (mode_string, "rsa-derive")) ++ if (!strcmp (mode_string, "rsa-derive") || ++ !strcmp (mode_string, "rsa-keygen") || ++ !strcmp (mode_string, "rsa-keygen-kat") || ++ !strcmp(mode_string, "drbg")) + binary_input = 1; + + if (argc == 2 && strcmp (argv[1], "-")) +@@ -2557,7 +2781,14 @@ main (int argc, char **argv) + if (!data) + die ("no data available (do not use --chunk)\n"); + +- run_digest (algo, data, datalen); ++ if (loop_mode) ++ { ++ run_digest_mct_loop (algo, data, datalen, 1000); ++ } ++ else ++ { ++ run_digest (algo, data, datalen); ++ } + } + else if (!strcmp (mode_string, "random")) + { +@@ -2602,6 +2833,12 @@ main (int argc, char **argv) + + deinit_external_rng_test (context); + } ++ else if (!strcmp (mode_string, "drbg")) ++ { ++ if (!algo_string) ++ die ("--algo required in this mode\n"); ++ run_drbg_test (algo_string, data, datalen); ++ } + else if (!strcmp (mode_string, "hmac-sha")) + { + int algo; +@@ -2679,7 +2916,7 @@ main (int argc, char **argv) + if (!data) + die ("no data available (do not use --chunk)\n"); + +- run_rsa_sign (data, datalen, algo, use_pkcs1, key_string); ++ run_rsa_sign (data, datalen, algo, use_pkcs1, use_pss, key_string); + + } + else if (!strcmp (mode_string, "rsa-verify")) +@@ -2702,7 +2939,7 @@ main (int argc, char **argv) + if (access (signature_string, R_OK)) + die ("option --signature needs to specify an existing file\n"); + +- run_rsa_verify (data, datalen, algo, use_pkcs1, key_string, ++ run_rsa_verify (data, datalen, algo, use_pkcs1, use_pss, key_string, + signature_string); + + } +@@ -2783,12 +3020,6 @@ main (int argc, char **argv) + + gcry_free (data); + +- /* Because Libgcrypt does not enforce FIPS mode in all cases we let +- the process die if Libgcrypt is not anymore in FIPS mode after +- the actual operation. */ +- if (!no_fips && !gcry_fips_mode_active ()) +- die ("FIPS mode is not anymore active\n"); +- + if (verbose) + fputs (PGM ": ready\n", stderr); + diff --git a/SOURCES/libgcrypt-1.5.3-drbg-init.patch b/SOURCES/libgcrypt-1.5.3-drbg-init.patch new file mode 100644 index 0000000..c27fdef --- /dev/null +++ b/SOURCES/libgcrypt-1.5.3-drbg-init.patch @@ -0,0 +1,23 @@ +diff -up libgcrypt-1.5.3/random/drbg.c.drbg-init libgcrypt-1.5.3/random/drbg.c +--- libgcrypt-1.5.3/random/drbg.c.drbg-init 2017-02-28 14:28:55.000000000 +0100 ++++ libgcrypt-1.5.3/random/drbg.c 2017-02-28 15:15:54.401291408 +0100 +@@ -1820,12 +1820,16 @@ _gcry_drbg_randomize (void *buffer, size + enum gcry_random_level level) + { + (void) level; +- gcry_drbg_lock (); + if (NULL == gcry_drbg) + { +- fips_signal_error ("DRBG is not initialized"); +- goto bailout; ++ _gcry_drbg_init(1); ++ if (NULL == gcry_drbg) ++ { ++ log_fatal ("DRBG is not initialized\n"); ++ goto bailout; ++ } + } ++ gcry_drbg_lock (); + + /* As reseeding changes the entire state of the DRBG, including any + * key, either a re-init or a reseed is sufficient for a fork */ diff --git a/SPECS/libgcrypt.spec b/SPECS/libgcrypt.spec index 4d0fd9d..b9016e0 100644 --- a/SPECS/libgcrypt.spec +++ b/SPECS/libgcrypt.spec @@ -1,6 +1,6 @@ Name: libgcrypt Version: 1.5.3 -Release: 13%{?dist}.1 +Release: 14%{?dist} URL: http://www.gnupg.org/ Source0: libgcrypt-%{version}-hobbled.tar.xz # The original libgcrypt sources now contain potentially patented ECC @@ -49,6 +49,12 @@ Patch22: libgcrypt-1.5.3-fips-reqs.patch Patch24: libgcrypt-1.5.3-urandom-only.patch # fix predictable PRNG output Patch26: libgcrypt-1.5.3-rng-predictable.patch +# add drgb cavs test +Patch27: libgcrypt-1.5.3-drbg-cavs.patch +# allow reinitialization of ath in the FIPS mode +Patch28: libgcrypt-1.5.3-ath-reinstall.patch +# allow auto-initialization of drbg +Patch29: libgcrypt-1.5.3-drbg-init.patch %define gcrylibdir %{_libdir} @@ -102,6 +108,9 @@ applications using libgcrypt. %patch22 -p1 -b .fips-reqs %patch24 -p1 -b .urandom-only %patch26 -p1 -b .rng-predictable +%patch27 -p1 -b .drbg-cavs +%patch28 -p1 -b .ath-reinstall +%patch29 -p1 -b .drbg-init %build %configure --disable-static \ @@ -203,6 +212,11 @@ exit 0 %doc COPYING %changelog +* Tue Feb 28 2017 Tomáš Mráz 1.5.3-14 +- add DRBG CAVS driver and other necessary CAVS driver updates (#1172568) +- allow ath reinitialization in FIPS mode +- allow for auto-initialization of DRBG + * Tue Oct 25 2016 Tomáš Mráz 1.5.3-13.1 - fix CVE-2016-6313 - predictable PRNG output (#1366105)