diff options
author | Werner Koch <wk@gnupg.org> | 2008-11-28 19:10:15 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-11-28 19:10:15 +0000 |
commit | ee188790d59e674b31b964709971d0c94508c152 (patch) | |
tree | 2f6a9066e3a81ed825c17f22e1fab1a5f90e9f1b /tests | |
parent | d665b72c1f810b88849bf839d382264fe52f38bc (diff) | |
download | libgcrypt-ee188790d59e674b31b964709971d0c94508c152.tar.gz |
Fixed the fips 186 dsa key generation.
Allow apssing of a seed value.
Add a new regression test.
Updated the cavs driver.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/ChangeLog | 8 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rwxr-xr-x | tests/cavs_driver.pl | 473 | ||||
-rw-r--r-- | tests/fips186-dsa.c | 460 | ||||
-rw-r--r-- | tests/fipsdrv.c | 161 |
5 files changed, 982 insertions, 122 deletions
diff --git a/tests/ChangeLog b/tests/ChangeLog index 229fd1c3..703a816a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2008-11-28 Werner Koch <wk@g10code.com> + + * fips186-dsa.c: New. + + * fipsdrv.c (print_mpi_line, print_data_line): New. + (run_dsa_pqg_gen): New. + (usage): Add mode dsa-pqg-gen. + 2008-11-25 Werner Koch <wk@g10code.com> * pubkey.c (get_dsa_key_new): New. diff --git a/tests/Makefile.am b/tests/Makefile.am index 38901f66..f9f39258 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in TESTS = version t-mpi-bit prime register ac ac-schemes ac-data basic \ - mpitests tsexp keygen pubkey hmac keygrip + mpitests tsexp keygen pubkey hmac keygrip fips186-dsa # random.c uses fork() thus a test for W32 does not make any sense. diff --git a/tests/cavs_driver.pl b/tests/cavs_driver.pl index 8b4079ce..c1edb57c 100755 --- a/tests/cavs_driver.pl +++ b/tests/cavs_driver.pl @@ -1,6 +1,6 @@ #!/usr/bin/env perl # -# $Id: cavs_driver.pl 1383 2008-10-30 11:45:31Z smueller $ +# $Id: cavs_driver.pl 1395 2008-11-10 15:18:03Z smueller $ # # CAVS test driver (based on the OpenSSL driver) # Written by: Stephan Müller <sm@atsec.com> @@ -89,6 +89,11 @@ # ANSI931_AES128MCT # ANSI931_AES128VST # +# DSA +# PQGGen +# SigGen +# SigVer +# # RC4 (atsec developed tests) # RC4KeyBD # RC4MCT @@ -105,7 +110,6 @@ use MIME::Base64; # Contains the command line options my %opt; - ################################################################# ##### Central interface functions to the external ciphers ####### ################################################################# @@ -143,7 +147,7 @@ my $rsa_sign; # $2: hash algo # $3: file holding the public RSA key in PEM format # $4: file holding the signature in binary form -# return: 1 == verfied / 0 == not verified +# return: 1 == verified / 0 == not verified my $rsa_verify; # generate a new private RSA key with the following properties: @@ -171,6 +175,9 @@ my $hash; # $5: IV in binary form # return: command line to execute the application my $state_cipher; +# the only difference of the DES version is that it implements the inner loop +# of the TDES tests +my $state_cipher_des; # supplying the call to the external cipher implementation # that is being used to keep STDIN and STDOUT open @@ -196,6 +203,40 @@ my $state_rng; # return: calculated HMAC in hex format my $hmac; +# +# Generate the P, Q, G, Seed, counter, h (value used to generate g) values +# for DSA +# $1: modulus size +# 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 +# Seed\n +# counter\n +# h +my $dsa_pqggen; + +# Verify a message with DSA +# $1: data to be verified in hex form +# $2: file holding the public DSA key in PEM format +# $3: R value of the signature +# $4: S value of the signature +# return: 1 == verified / 0 == not verified +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 +my $gen_dsakey; + +# 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; + ################################################################ ##### OpenSSL interface functions ################################################################ @@ -273,8 +314,6 @@ sub openssl_state_cipher($$$$$) { my $key = shift; my $iv = shift; - #FIXME: Implement the inner loop right here. - my $enc = $encdec ? "-e": "-d"; # We only invoke the driver with the IV parameter, if we have @@ -362,7 +401,28 @@ sub libgcrypt_state_cipher($$$$$) { my $key = shift; my $iv = shift; + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "--iv ".bin2hex($iv) if ($iv); + + my $program="fipsdrv --binary --key ".bin2hex($key)." $iv --algo '$cipher' --chunk '$bufsize' $enc"; + + return $program; +} + +sub libgcrypt_state_cipher_des($$$$$) { + my $cipher = shift; + my $enc = (shift) ? "encrypt": "decrypt"; + my $bufsize = shift; + my $key = shift; + my $iv = shift; + + # We only invoke the driver with the IV parameter, if we have + # an IV, otherwise, we skip it + $iv = "--iv ".bin2hex($iv) if ($iv); + my $program="fipsdrv --algo '$cipher' --mct-server $enc"; + return $program; } @@ -384,6 +444,13 @@ sub libgcrypt_hmac($$$$) { return pipe_through_program($msg, $program); } +sub libgcrypt_dsa_pqggen($) { + my $mod = shift; + + my $program = "fipsdrv --keysize $mod dsa-pqg-gen"; + return pipe_through_program("", $program); +} + ######### End of libgcrypt implementation ################ ################################################################ @@ -532,39 +599,6 @@ sub fix_key_parity($) { } #################################################### -# Encrypt/Decrypt routines - -# encryption -# $1 key in hex form -# $2 iv in hex form -# $3 cipher -# $4 data in hex form -# return encrypted data -sub encrypt($$$$) { - my $key=shift; - my $iv=shift; - my $cipher=shift; - my $data=shift; - - return &$encdec($key, $iv, $cipher, 1, $data); -} - -# decryption -# $1 key in hex form -# $2 iv in hex form -# $3 cipher -# $4 data in hex form -# return encrypted data -sub decrypt($$$$) { - my $key=shift; - my $iv=shift; - my $cipher=shift; - my $data=shift; - - return &$encdec($key, $iv, $cipher, 0, $data); -} - -#################################################### # DER/PEM utility functions # Cf. http://www.columbia.edu/~ariel/ssleay/layman.html @@ -920,10 +954,10 @@ sub kat($$$$$$$$) { $out .= "IV = $iv\n" if (defined($iv) && $iv ne ""); if ($enc) { $out .= "PLAINTEXT = $pt\n"; - $out .= "CIPHERTEXT = " . encrypt($key1, $iv, $cipher, $pt) . "\n"; + $out .= "CIPHERTEXT = " . &$encdec($key1, $iv, $cipher, 1, $pt) . "\n"; } else { $out .= "CIPHERTEXT = $pt\n"; - $out .= "PLAINTEXT = " . decrypt($key1, $iv, $cipher, $pt) . "\n"; + $out .= "PLAINTEXT = " . &$encdec($key1, $iv, $cipher, 0, $pt) . "\n"; } return $out; @@ -1008,8 +1042,6 @@ sub crypto_mct($$$$$$$$) { my $source_data = hex2bin(shift); my $cipher = shift; my $enc = shift; - my $line; - my $next_source; my $out = ""; @@ -1025,18 +1057,7 @@ sub crypto_mct($$$$$$$$) { my $iloop=1000; if ($ciph =~ /des/) {$oloop=400;$iloop=10000;} - my ($CO, $CI); - my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv); - my $pid = open2($CO, $CI, $cipher_imp); - my $len; - for (my $i=0; $i<$oloop; ++$i) { - my $calc_data; - my $old_calc_data; - my $old_old_calc_data; - my $ov; - my $iv_arg; - $out .= "COUNT = $i\n"; if (defined($key2)) { $out .= "$keytype = ". bin2hex($key1). "\n"; @@ -1059,45 +1080,69 @@ sub crypto_mct($$$$$$$$) { } else { $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n"; } - - # Need to provide a dummy IV in case of ECB mode. - $iv_arg = (defined($iv) && $iv ne "") - ? bin2hex($iv) - : "00"x(length($source_data)); - - print $CI "1\n" - .$iloop."\n" - .bin2hex($key1)."\n" - .$iv_arg."\n" - .bin2hex($source_data)."\n\n" or die; - - # fixme: We should skip over empty lines here. - - chomp($line = <$CO>); #print STDERR " calc=$line\n"; - $calc_data = hex2bin($line); - - chomp($line = <$CO>); #print STDERR " old_calc=$line\n"; - $old_calc_data = hex2bin($line); - - chomp($line = <$CO>); #print STDERR "old_old_calc=$line\n"; - $old_old_calc_data = hex2bin($line); - - chomp($line = <$CO>); #print STDERR " ov=$line\n"; - $ov = hex2bin($line); - - chomp($line = <$CO>); #print STDERR " next source=$line\n"; - $next_source = hex2bin($line); - - # Skip over empty line. - $line = <$CO>; - + 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/); + my $pid = open2($CO, $CI, $cipher_imp); + + my $calc_data = $iv; # CT[j] + my $old_calc_data; # CT[j-1] + my $old_old_calc_data; # CT[j-2] + my $next_source; + + # TDES inner loop implements logic within driver + if ($cipher =~ /des/) { + print $CI "1\n" + .$iloop."\n" + .bin2hex($key1)."\n" + .bin2hex($iv)."\n" + .bin2hex($source_data)."\n\n" or die; + chomp(my $line = <$CO>); + $calc_data = hex2bin($line); + chomp($line = <$CO>); + $old_calc_data = hex2bin($line); + chomp($line = <$CO>); + $old_old_calc_data = hex2bin($line); + chomp($line = <$CO>); + $iv = hex2bin($line); + chomp($line = <$CO>); + $next_source = hex2bin($line); + # Skip over empty line. + $line = <$CO>; + } else { + for (my $j = 0; $j < $iloop; ++$j) { + $old_old_calc_data = $old_calc_data; + $old_calc_data = $calc_data; + + #print STDERR "source_data=", bin2hex($source_data), "\n"; + syswrite $CI, $source_data or die $!; + my $len = sysread $CO, $calc_data, $bufsize; + + #print STDERR "len=$len, bufsize=$bufsize\n"; + die if $len ne $bufsize; + #print STDERR "calc_data=", bin2hex($calc_data), "\n"; + + if ( (!$enc && $ciph =~ /des/) || + $ciph =~ /rc4/ || + $cipher =~ /ecb/ ) { + #TDES in decryption mode, RC4 and ECB mode + #have a special rule + $source_data = $calc_data; + } else { + $source_data = $old_calc_data; + } + } + } + close $CO; + close $CI; + waitpid $pid, 0; if ($enc) { $out .= "CIPHERTEXT = ". bin2hex($calc_data). "\n\n"; } else { $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n"; } - + if ( $ciph =~ /aes/ ) { $key1 ^= substr($old_calc_data . $calc_data, -$keylen); #print STDERR bin2hex($key1)."\n"; @@ -1135,13 +1180,15 @@ sub crypto_mct($$$$$$$$) { die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing"; } - if ($ciph =~ /des/) { - $iv = $ov if (defined($iv) && $iv ne ""); - if ($cipher =~ /des-ede3-ofb/) { + if ($cipher =~ /des-ede3-ofb/) { $source_data = $source_data ^ $next_source; - } else { - $source_data = $next_source; - } + } elsif (!$enc && $cipher =~ /des-ede3-cfb/) { + #TDES decryption CFB has a special rule + $source_data = $next_source; + } elsif (! $enc && $ciph =~ /des/ ) { + #TDES in decryption mode has a special rule + $iv = $old_calc_data; + $source_data = $calc_data; } elsif ( $ciph =~ /rc4/ || $cipher =~ /ecb/ ) { #No resetting of IV as the IV is all zero set initially (i.e. no IV) $source_data = $calc_data; @@ -1149,11 +1196,7 @@ sub crypto_mct($$$$$$$$) { $iv = $calc_data; $source_data = $old_calc_data; } - } - close $CO; - close $CI; - waitpid $pid, 0; return $out; } @@ -1291,6 +1334,96 @@ sub rngx931($$$$) { return $out; } +# DSA PQGGen test +# $1 modulus size +# $2 number of rounds to perform the test +# return: string formatted as expected by CAVS +sub dsa_pqggen_driver($$) { + my $mod = shift; + my $rounds = shift; + + my $out = ""; + for(my $i=0; $i<$rounds; $i++) { + my $ret = &$dsa_pqggen($mod); + 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)); + $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"; + } + + return $out; +} + + +# DSA SigGen test +# $1: Message to be signed in hex form +# $2: file name with DSA key in PEM form +# return: string formatted as expected by CAVS +sub dsa_siggen($$) { + my $data = shift; + my $keyfile = shift; + + my $out = ""; + + my %ret = &$dsa_sign($data, $keyfile); + + $out .= "Msg = $data\n"; + $out .= "Y = " . $ret{'Y'} . "\n"; + $out .= "R = " . $ret{'R'} . "\n"; + $out .= "S = " . $ret{'S'} . "\n"; + + return $out; +} + + +# DSA signature verification +# $1 modulus +# $2 P +# $3 Q +# $4 G +# $5 Y - public key +# $6 r +# $7 s +# $8 message to be verified +# return: string formatted as expected by CAVS +sub dsa_sigver($$$$$$$$) { + my $modulus = shift; + my $p = shift; + my $q = shift; + my $g = shift; + my $y = shift; + my $r = shift; + my $s = shift; + my $msg = shift; + + my $out = ""; + + #PQG are already printed - do not print them here + + $out .= "Msg = $msg\n"; + $out .= "Y = $y\n"; + $out .= "R = $r\n"; + $out .= "S = $s\n"; + + # 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 + my $keyfile = "dsa_sigver.tmp.$$"; + gen_pubdsakey($keyfile, $p, $q, $g, $y); + + $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n"); + + unlink($keyfile); + + return $out; +} + ############################################################## # Parser of input file and generator of result file # @@ -1298,12 +1431,16 @@ sub rngx931($$$$) { sub usage() { print STDERR "Usage: -$0 [-R] [-I name] <CAVS-test vector file> +$0 [-R] [-D] [-I name] <CAVS-test vector file> -R execution of ARCFOUR instead of OpenSSL -I NAME Use interface style NAME: openssl OpenSSL (default) - libgcrypt Libgcrypt"; + libgcrypt Libgcrypt +-D SigGen and SigVer are executed with DSA + Please note that the DSA CAVS vectors do not allow distinguishing + them from the RSA vectors. As the RSA test is the default, you have + to supply this option to apply the DSA logic"; } # Parser of CAVS test vector file @@ -1316,9 +1453,6 @@ sub parse($$) { my $out = ""; - # Do I need to generate the key? - my $rsa_keygen = 0; - # this is my cipher/hash type my $cipher = ""; @@ -1344,10 +1478,19 @@ sub parse($$) { my $e = ""; my $signature = ""; my $rsa_keyfile = ""; + my $dsa_keyfile = ""; my $dt = ""; my $v = ""; my $klen = ""; my $tlen = ""; + my $modulus = ""; + my $capital_n = 0; + my $capital_p = ""; + my $capital_q = ""; + my $capital_g = ""; + my $capital_y = ""; + my $capital_r = ""; + my $capital_s = ""; my $mode = ""; @@ -1378,7 +1521,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)/) { + if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen)/) { if ($tmpline =~ /CBC/) { $mode="cbc"; } elsif ($tmpline =~ /ECB/) { $mode="ecb"; } elsif ($tmpline =~ /OFB/) { $mode="ofb"; } @@ -1397,10 +1540,6 @@ sub parse($$) { $cipher="sha1"; #place holder - might be overwritten later } - # RSA Key Generation test - if ($tmpline =~ /SigGen/) { - $rsa_keygen = 1; - } if ($tmpline =~ /^#.*AESVS/) { # AES cipher (part of it) $cipher="aes"; @@ -1431,12 +1570,19 @@ sub parse($$) { if ($tt == 0) { ##### Identify the test type - if ($tmpline =~ /KeyGen RSA \(X9.31\)/) { - $tt =~ 10; - die "Interface function for RSA KeyGen testing not defined for tested library" - if (!defined($gen_rsakey)); - } - if ($tmpline =~ /Hash sizes tested/) { + if ($tmpline =~ /SigVer/ && $opt{'D'} ) { + $tt = 12; + die "Interface function dsa_verify for dSA verification not defined for tested library" + if (!defined($dsa_verify)); + } 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)); + } elsif ($tmpline =~ /PQGGen/) { + $tt = 10; + die "Interface function for DSA PQGGen testing not defined for tested library" + if (!defined($dsa_pqggen)); + } elsif ($tmpline =~ /Hash sizes tested/) { $tt = 9; die "Interface function hmac for HMAC testing not defined for tested library" if (!defined($hmac)); @@ -1463,7 +1609,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)); + if (!defined($state_cipher) || !defined($state_cipher_des)); } elsif ($cipher =~ /^sha/) { $tt = 3; die "Interface function hash for Hashing not defined for tested library" @@ -1547,19 +1693,26 @@ sub parse($$) { $pt=$2; } elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests - $out .= $line . "\n"; # print it + $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) { + if ($tt == 11) { + $dsa_keyfile = "dsa_siggen.tmp.$$"; + my %pqg = &$gen_dsakey($dsa_keyfile); + $out .= "P = " . $pqg{'P'} . "\n"; + $out .= "Q = " . $pqg{'Q'} . "\n"; + $out .= "G = " . $pqg{'G'} . "\n"; + } elsif ( $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 $rsa_keyfile = "rsa_siggen.tmp.$$"; - &$gen_rsakey($1, $rsa_keyfile); + &$gen_rsakey($modulus, $rsa_keyfile); my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile"); $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/; - $out .= "\nn = $modulus\n"; - $out .= "\ne = 10001\n" + $out .= "n = $modulus\n"; + $out .= "\ne = 10001\n" } } elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests @@ -1596,6 +1749,44 @@ sub parse($$) { if ($tlen ne ""); $tlen=$1; } + elsif ($line =~ /^N\s*=\s*(.)/) { #DSA PQGGen + die "N seen twice - check input file" + if ($capital_n); + $capital_n = $1; + } + elsif ($line =~ /^P\s*=\s*(.)/) { #DSA SigVer + die "P seen twice - check input file" + if ($capital_p); + $capital_p = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^Q\s*=\s*(.)/) { #DSA SigVer + die "Q seen twice - check input file" + if ($capital_q); + $capital_q = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^G\s*=\s*(.)/) { #DSA SigVer + die "G seen twice - check input file" + if ($capital_g); + $capital_g = $1; + $out .= $line . "\n"; # print it + } + elsif ($line =~ /^Y\s*=\s*(.)/) { #DSA SigVer + die "Y seen twice - check input file" + if ($capital_y); + $capital_y = $1; + } + elsif ($line =~ /^R\s*=\s*(.)/) { #DSA SigVer + die "R seen twice - check input file" + if ($capital_r); + $capital_r = $1; + } + elsif ($line =~ /^S\s*=\s*(.)/) { #DSA SigVer + die "S seen twice - check input file" + if ($capital_s); + $capital_s = $1; + } else { $out .= $line . "\n"; } @@ -1674,6 +1865,48 @@ sub parse($$) { $pt = ""; } } + elsif ($tt == 10) { + if ($modulus ne "" && $capital_n > 0) { + $out .= dsa_pqggen_driver($modulus, $capital_n); + #$mod is not resetted + $capital_n = 0; + } + } + elsif ($tt == 11) { + if ($pt ne "" && $dsa_keyfile ne "") { + $out .= dsa_siggen($pt, $dsa_keyfile); + $pt = ""; + } + } + elsif ($tt == 12) { + if ($modulus ne "" && + $capital_p ne "" && + $capital_q ne "" && + $capital_g ne "" && + $capital_y ne "" && + $capital_r ne "" && + $capital_s ne "" && + $pt ne "") { + $out .= dsa_sigver($modulus, + $capital_p, + $capital_q, + $capital_g, + $capital_y, + $capital_r, + $capital_s, + $pt); + + # We do not clear the domain values PQG and + # the modulus value as they + # are specified only once in a file + # and we do not need to print them as they + # are already printed above + $capital_y = ""; + $capital_r = ""; + $capital_s = ""; + $pt = ""; + } + } elsif ($tt > 0) { die "Test case $tt not defined"; } @@ -1704,7 +1937,7 @@ sub main() { usage() unless @ARGV; - getopts("RI:", \%opt) or die "bad option"; + getopts("DRI:", \%opt) or die "bad option"; ##### Set library @@ -1724,8 +1957,10 @@ sub main() { $gen_rsakey = \&libgcrypt_gen_rsakey; $hash = \&libgcrypt_hash; $state_cipher = \&libgcrypt_state_cipher; + $state_cipher_des = \&libgcrypt_state_cipher_des; $state_rng = \&libgcrypt_state_rng; $hmac = \&libgcrypt_hmac; + $dsa_pqggen = \&libgcrypt_dsa_pqggen; } else { die "Invalid interface option given"; } diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c new file mode 100644 index 00000000..c676c5d5 --- /dev/null +++ b/tests/fips186-dsa.c @@ -0,0 +1,460 @@ +/* fips186-dsa.c - FIPS 186 DSA tests + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +#include "../src/gcrypt.h" + +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + +static int verbose; +static int error_count; + +static void +info (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + error_count++; +} + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + exit (1); +} + +static void +show_sexp (const char *prefix, gcry_sexp_t a) +{ + char *buf; + size_t size; + + if (prefix) + fputs (prefix, stderr); + size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = gcry_xmalloc (size); + + gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); + fprintf (stderr, "%.*s", (int)size, buf); + gcry_free (buf); +} + +static gcry_mpi_t +mpi_from_string (const char *string) +{ + gpg_error_t err; + gcry_mpi_t a; + + err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, string, 0, NULL); + if (err) + die ("error converting string to mpi: %s\n", gpg_strerror (err)); + return a; +} + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +data_from_hex (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = gcry_xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + die ("error parsing hex string `%s'\n", string); + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + + +static void +extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected) +{ + gcry_sexp_t l1; + gcry_mpi_t a, b; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + b = mpi_from_string (expected); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( gcry_mpi_cmp (a, b) ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_mpi_release (b); + gcry_mpi_release (a); + gcry_sexp_release (l1); +} + + +static void +extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) +{ + gcry_sexp_t l1; + const void *a; + size_t alen; + void *b; + size_t blen; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_data (l1, 1, &alen); + b = data_from_hex (expected, &blen); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( alen != blen || memcmp (a, b, alen) ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_free (b); + gcry_sexp_release (l1); +} + +static void +extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected) +{ + gcry_sexp_t l1; + char *a; + + l1 = gcry_sexp_find_token (sexp, name, 0); + a = gcry_sexp_nth_string (l1, 1); + if (!a) + fail ("parameter \"%s\" missing in key\n", name); + else if ( strtoul (a, NULL, 10) != expected ) + fail ("parameter \"%s\" does not match expected value\n", name); + gcry_free (a); + gcry_sexp_release (l1); +} + + +static void +check_dsa_gen_186_2 (void) +{ + static struct { + int nbits; + const char *p, *q, *g; + const char *seed; + int counter; + const char *h; + } tbl[] = { + /* These tests are from FIPS 186-2, B.3.1. */ + { + 1024, + "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" + "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" + "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" + "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69", + "9c916d121de9a03f71fb21bc2e1c0d116f065a4f", + "8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" + "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" + "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" + "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44", + "0cb1990c1fd3626055d7a0096f8fa99807399871", + 98, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002" + }, + { + 1024, + "f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f" + "8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb" + "0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be" + "3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9", + "f8751166cf4f6f3b07c081fd2a9071f23ca1988d", + "1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62" + "4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a" + "665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c" + "4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33", + "34b3520d45d240a8861b82c8b61ffa16e67b5cce", + 622, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7" + "b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4" + "55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc" + "1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad", + "d32b29f065c1394a30490b6fcbf812a32a8634ab", + "06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1" + "ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714" + "c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231" + "80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2", + "b6ec750da2f824cb42c5f7e28c81350d97f75125", + 185, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b" + "ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f" + "d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b" + "c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5", + "de822c03445b77cec4ad3a6fb0ca39ff97059ddf", + "65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371" + "681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b" + "848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69" + "1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748", + "cd2221dd73815a75224e9fde7faf52829b81ac7a", + 62, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + { + 1024, + "898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803" + "ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891" + "354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9" + "8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227", + "c6d786643d2acfc6b8d576863fda8cfbfbd5e03f", + "2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d" + "af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d" + "5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb" + "e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb", + "73483e697599871af983a281e3afa22e0ed86b68", + 272, + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000002", + }, + + /* These tests are generated by the OpenSSL FIPS version. */ + { + 1024, + "A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C" + "A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255" + "EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033" + "11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9", + "C643946CEA8748E12D430C48DB038F9165814389", + "59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16" + "892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC" + "B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7" + "44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225", + "02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd", + 50, + "02" + }, + { + 1024, + "9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987" + "6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3" + "D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450" + "04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5", + "AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7", + "74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701" + "95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E" + "039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A" + "C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498", + "6481a12a50384888ee84b61024f7c9c685d6ac96", + 289, + "02" + }, + { + 1024, + + "B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828" + "1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63" + "5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503" + "B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF", + "EA649C04911FAB5A41440287A517EF752A40354B", + "88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162" + "01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194" + "93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C" + "858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696", + "5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a", + 626, + "02" + }, + { + 1024, + "F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C" + "F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D" + "5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977" + "CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD", + "A40D9EE456AED4C8A653FDB47B6629C0B843FE8F", + "DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE" + "700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614" + "F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7" + "2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67", + "8a9a57706f69f4f566252cdf6d5cbfdf2020150b", + 397, + "02" + }, + { + 1024, + "D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068" + "29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934" + "96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A" + "093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B", + "D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5", + "468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC" + "58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5" + "7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159" + "928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839", + "30b3599944a914a330a3f49d11ec88f555422aef", + 678, + "02" + } + }; + gpg_error_t err; + int tno; + gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; + gcry_sexp_t l1; + + for (tno = 0; tno < DIM (tbl); tno++) + { + if (verbose) + info ("generating FIPS 186-2 test key %d\n", tno); + + { + void *data; + size_t datalen; + + data = data_from_hex (tbl[tno].seed, &datalen); + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (dsa (nbits %d)(use-fips186-2)" + "(derive-parms(seed %b))))", + tbl[tno].nbits, (int)datalen, data); + gcry_free (data); + } + if (err) + die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); + + err = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (err) + { + fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); + continue; + } + + if (verbose > 1) + show_sexp ("generated key:\n", key); + + pub_key = gcry_sexp_find_token (key, "public-key", 0); + if (!pub_key) + fail ("public part missing in key %d\n", tno); + + sec_key = gcry_sexp_find_token (key, "private-key", 0); + if (!sec_key) + fail ("private part missing in key %d\n", tno); + + l1 = gcry_sexp_find_token (key, "misc-key-info", 0); + if (!l1) + fail ("misc_key_info part missing in key %d\n", tno); + seed_values = gcry_sexp_find_token (l1, "seed-values", 0); + if (!seed_values) + fail ("seed-values part missing in key %d\n", tno); + gcry_sexp_release (l1); + + extract_cmp_mpi (sec_key, "p", tbl[tno].p); + extract_cmp_mpi (sec_key, "q", tbl[tno].q); + extract_cmp_mpi (sec_key, "g", tbl[tno].g); + + extract_cmp_data (seed_values, "seed", tbl[tno].seed); + extract_cmp_int (seed_values, "counter", tbl[tno].counter); + extract_cmp_mpi (seed_values, "h", tbl[tno].h); + + gcry_sexp_release (seed_values); + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + gcry_sexp_release (key); + } +} + + + +int +main (int argc, char **argv) +{ + int debug = 0; + + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + else if (argc > 1 && !strcmp (argv[1], "--debug")) + { + verbose = 2; + debug = 1; + } + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); + /* No valuable keys are create, so we can speed up our RNG. */ + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + + check_dsa_gen_186_2 (); + + + return error_count ? 1 : 0; +} diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c index e27b84c1..d20b2bbd 100644 --- a/tests/fipsdrv.c +++ b/tests/fipsdrv.c @@ -823,6 +823,53 @@ print_buffer (const void *buffer, size_t length) } +/* Print an MPI on a line. */ +static void +print_mpi_line (gcry_mpi_t a, int no_lz) +{ + unsigned char *buf, *p; + gcry_error_t err; + int writerr = 0; + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a); + if (err) + die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err)); + + p = buf; + if (no_lz && p[0] == '0' && p[1] == '0' && p[2]) + p +=2; + + printf ("%s\n", p); + if (ferror (stdout)) + writerr++; + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + die ("writing output failed: %s\n", strerror (errno)); + gcry_free (buf); +} + + +/* Print some data on hex format on a line. */ +static void +print_data_line (const void *data, size_t datalen) +{ + const unsigned char *p = data; + int writerr = 0; + + while (data && datalen-- && !ferror (stdout) ) + printf ("%02X", *p++); + putchar ('\n'); + if (ferror (stdout)) + writerr++; + if (!writerr && fflush (stdout) == EOF) + writerr++; + if (writerr) + die ("writing output failed: %s\n", strerror (errno)); +} + + + static gcry_error_t init_external_rng_test (void **r_context, @@ -1487,6 +1534,105 @@ run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1, } + +/* Generate DSA donmain 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. */ +static void +run_dsa_pqg_gen (int keysize) +{ + gpg_error_t err; + gcry_sexp_t keyspec, key, l1, l2; + gcry_mpi_t mpi; + int idx; + const void *data; + size_t datalen; + char *string; + + /* Note that we create a complete key but don't return the x and y + values. */ + err = gcry_sexp_build (&keyspec, NULL, + "(genkey (dsa (nbits %d)(use-fips186-2)))", + keysize); + if (err) + die ("gcry_sexp_build failed for DSA domain parameter generation: %s\n", + gpg_strerror (err)); + + err = gcry_pk_genkey (&key, keyspec); + if (err) + die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err)); + + gcry_sexp_release (keyspec); + + 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; "pqg"[idx]; idx++) + { + l2 = gcry_sexp_find_token (l1, "pqg"+idx, 1); + if (!l2) + die ("no %c parameter in returned private key\n", "pqg"[idx]); + mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!mpi) + die ("no value for %c parameter in returned private key\n","pqg"[idx]); + gcry_sexp_release (l2); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + } + gcry_sexp_release (l1); + + /* Extract the seed values. */ + l1 = gcry_sexp_find_token (key, "misc-key-info", 0); + if (!l1) + die ("misc-key-info not found in genkey result\n"); + + l2 = gcry_sexp_find_token (l1, "seed-values", 0); + if (!l2) + die ("no seed-values in returned private key\n"); + gcry_sexp_release (l1); + l1 = l2; + + l2 = gcry_sexp_find_token (l1, "seed", 0); + if (!l2) + die ("no seed value in returned private key\n"); + data = gcry_sexp_nth_data (l2, 1, &datalen); + if (!data) + die ("no seed value in returned private key\n"); + print_data_line (data, datalen); + gcry_sexp_release (l2); + + l2 = gcry_sexp_find_token (l1, "counter", 0); + if (!l2) + die ("no counter value in returned private key\n"); + string = gcry_sexp_nth_string (l2, 1); + if (!string) + die ("no counter value in returned private key\n"); + printf ("%lX\n", strtoul (string, NULL, 10)); + gcry_free (string); + gcry_sexp_release (l2); + + l2 = gcry_sexp_find_token (l1, "h", 0); + if (!l2) + die ("no n value in returned private key\n"); + mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + if (!mpi) + die ("no h value in returned private key\n"); + print_mpi_line (mpi, 1); + gcry_mpi_release (mpi); + gcry_sexp_release (l2); + + gcry_sexp_release (l1); + gcry_sexp_release (key); +} + static void @@ -1502,7 +1648,8 @@ usage (int show_help) ("Usage: " PGM " [OPTIONS] MODE [FILE]\n" "Run a crypto operation using hex encoded input and output.\n" "MODE:\n" - " encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify}\n" + " encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify},\n" + " dsa-pqg-gen\n" "OPTIONS:\n" " --verbose Print additional information\n" " --binary Input and output is in binary form\n" @@ -1695,7 +1842,8 @@ main (int argc, char **argv) if (!chunksize && !mct_server && strcmp (mode_string, "random") - && strcmp (mode_string, "rsa-gen") ) + && strcmp (mode_string, "rsa-gen") + && strcmp (mode_string, "dsa-pqg-gen") ) { data = read_file (input, !binary_input, &datalen); if (!data) @@ -1933,6 +2081,15 @@ main (int argc, char **argv) signature_string); } + else if (!strcmp (mode_string, "dsa-pqg-gen")) + { + int keysize; + + 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); + } else usage (0); |