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(<IN>) {
@@ -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 <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
@@ -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);