Fix for dsa signature verifciation in fipsdrv.
authorWerner Koch <wk@gnupg.org>
Wed, 21 Jan 2009 17:46:55 +0000 (17:46 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 21 Jan 2009 17:46:55 +0000 (17:46 +0000)
Other small changes.

cipher/ChangeLog
cipher/rmd160.c
doc/gcrypt.texi
tests/ChangeLog
tests/cavs_driver.pl
tests/fipsdrv.c
tests/pubkey.c

index 9952551..8c7e1b4 100644 (file)
@@ -1,3 +1,7 @@
+2009-01-06  Werner Koch  <wk@g10code.com>
+
+       * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier.
+
 2008-12-10  Werner Koch  <wk@g10code.com>
 
        * dsa.c (generate): Add arg DOMAIN and use it if specified.
@@ -3881,7 +3885,7 @@ Mon Feb 16 10:08:47 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
 
  Copyright 1998,1999,2000,2001,2002,2003,2004,2005,2006
-          2007, 2008 Free Software Foundation, Inc.
+          2007, 2008, 2009 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
index 5a0c1fc..7805bf5 100644 (file)
@@ -559,7 +559,9 @@ static gcry_md_oid_spec_t oid_spec_rmd160[] =
   {
     /* rsaSignatureWithripemd160 */
     { "1.3.36.3.3.1.2" },
-    { NULL },
+    /* TeleTrust hash algorithm.  */
+    { "1.3.36.3.2.1" },
+    { NULL }
   };
 
 gcry_md_spec_t _gcry_digest_spec_rmd160 =
index 83ba617..2cdc9af 100644 (file)
@@ -2789,8 +2789,8 @@ will be changed to implement 186-3.
 
 @item use-fips186-2
 Force the use of the FIPS 186-2 key generation algorithm instead of
-the default algorithm.  This algorithm has a slighlty different from
-FIPS 186-3 and allws only 1024 bit keys.  This flag is only meaningful
+the default algorithm.  This algorithm is slighlty different from
+FIPS 186-3 and allows only 1024 bit keys.  This flag is only meaningful
 for DSA and only required for FIPS testing backward compatibility.
 
 
index 205fdb2..20a450c 100644 (file)
@@ -1,3 +1,10 @@
+2009-01-21  Werner Koch  <wk@g10code.com>
+
+       * fipsdrv.c (run_dsa_verify): Use hash of the data.
+
+       * pubkey.c (get_dsa_key_fips186_with_seed_new): New.
+       (check_run): Call it.
+
 2008-12-11  Werner Koch  <wk@g10code.com>
 
        * fipsdrv.c (run_rsa_derive): New.
index fa80fb8..d9e2b6e 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 #
-# $Id: cavs_driver.pl 1395 2008-11-10 15:18:03Z smueller $
+# $Id: cavs_driver.pl 1488 2009-01-16 14:29:00Z smueller $
 #
 # CAVS test driver (based on the OpenSSL driver)
 # Written by: Stephan Müller <sm@atsec.com>
@@ -138,21 +138,20 @@ my $encdec;
 #
 # Derive an RSA key from the given X9.31 parameters.
 # $1: modulus size
-# $2: E   in hex form 
-# $3: Xp1 in hex form 
-# $4: Xp2 in hex form 
-# $5: Xp  in hex form 
-# $6: Xq1 in hex form 
-# $7: Xq2 in hex form 
-# $8: Xq  in hex form 
+# $2: E   in hex form
+# $3: Xp1 in hex form
+# $4: Xp2 in hex form
+# $5: Xp  in hex form
+# $6: Xq1 in hex form
+# $7: Xq2 in hex form
+# $8: Xq  in hex form
 # return: string with the calculated values in hex format, where each value
-#        is separated from the previous with a \n in the following order:
+#        is separated from the previous with a \n in the following order:
 #         P\n
 #         Q\n
 #         D\n
 my $rsa_derive;
 
-
 # Sign a message with RSA
 # $1: data to be signed in hex form
 # $2: Hash algo
@@ -241,10 +240,9 @@ my $dsa_pqggen;
 # $2: P in hex form
 # $3: Q in hex form
 # $4: G in hex form
-# $5: Y in hex form  
+# $5: Y in hex form
 my $dsa_genpubkey;
 
-
 # Verify a message with DSA
 # $1: data to be verified in hex form
 # $2: file holding the public DSA key in PEM format
@@ -378,31 +376,32 @@ sub libgcrypt_encdec($$$$$) {
 
 sub libgcrypt_rsa_derive($$$$$$$$) {
        my $n   = shift;
-        my $e   = shift;
-        my $xp1 = shift;
-        my $xp2 = shift;
-        my $xp  = shift;
-        my $xq1 = shift;
-        my $xq2 = shift;
-        my $xq  = shift;
-        my $sexp;
-        my @tmp;
-
-        $n = sprintf ("%u", $n);
-        $e = sprintf ("%u", hex($e));
-        $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")"
-                . "(rsa-use-e " . sprintf ("%u:%s", length($e), $e) . ")"
-                . "(derive-parms"
-                . "(Xp1 #$xp1#)"
-                . "(Xp2 #$xp2#)"
-                . "(Xp  #$xp#)"
-                . "(Xq1 #$xq1#)"
-                . "(Xq2 #$xq2#)"
-                . "(Xq  #$xq#))))\n";
-
-        return pipe_through_program($sexp, "fipsdrv rsa-derive");
+       my $e   = shift;
+       my $xp1 = shift;
+       my $xp2 = shift;
+       my $xp  = shift;
+       my $xq1 = shift;
+       my $xq2 = shift;
+       my $xq  = shift;
+       my $sexp;
+       my @tmp;
+
+       $n = sprintf ("%u", $n);
+       $e = sprintf ("%u", hex($e));
+       $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")"
+               . "(rsa-use-e " . sprintf ("%u:%s", length($e), $e) . ")"
+               . "(derive-parms"
+               . "(Xp1 #$xp1#)"
+               . "(Xp2 #$xp2#)"
+               . "(Xp  #$xp#)"
+               . "(Xq1 #$xq1#)"
+               . "(Xq2 #$xq2#)"
+               . "(Xq  #$xq#))))\n";
+
+       return pipe_through_program($sexp, "fipsdrv rsa-derive");
 }
 
+
 sub libgcrypt_rsa_sign($$$) {
        my $data = shift;
        my $hashalgo = shift;
@@ -510,16 +509,16 @@ sub libgcrypt_gen_dsakey($) {
        my $file = shift;
 
        my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
-        my $tmp;
-        my %ret;
+       my $tmp;
+       my %ret;
 
        die "ARCFOUR not available for DSA" if $opt{'R'};
 
-        $tmp = pipe_through_program("", $program);
+       $tmp = pipe_through_program("", $program);
        die "dsa key gen failed: file $file not created" if (! -f $file);
 
-        @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
-        return %ret;
+       @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
+       return %ret;
 }
 
 sub libgcrypt_dsa_genpubkey($$$$$) {
@@ -529,26 +528,26 @@ sub libgcrypt_dsa_genpubkey($$$$$) {
        my $g = shift;
        my $y = shift;
 
-        my $sexp;
+       my $sexp;
 
-        $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))"; 
+       $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))";
 
        open(FH, ">", $filename) or die;
        print FH $sexp;
-       close FH;  
+       close FH;
 }
 
 sub libgcrypt_dsa_sign($$) {
        my $data = shift;
        my $keyfile = shift;
-        my $tmp;
-        my %ret; 
-        
+       my $tmp;
+       my %ret;
+
        die "ARCFOUR not available for DSA" if $opt{'R'};
 
        $tmp = pipe_through_program($data, "fipsdrv --key $keyfile dsa-sign");
-        @ret{'Y', 'R', 'S'} = split(/\n/, $tmp);
-        return %ret;
+       @ret{'Y', 'R', 'S'} = split(/\n/, $tmp);
+       return %ret;
 }
 
 sub libgcrypt_dsa_verify($$$$) {
@@ -556,25 +555,23 @@ sub libgcrypt_dsa_verify($$$$) {
        my $keyfile = shift;
        my $r = shift;
        my $s = shift;
-        
-        my $ret;
+
+       my $ret;
 
        die "ARCFOUR not available for DSA" if $opt{'R'};
 
        my $sigfile = "$keyfile.sig";
        open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
-       print FH "(sig-val(dsa(r #$r)(s #$s#)))";
+       print FH "(sig-val(dsa(r #$r#)(s #$s#)))";
        close FH;
 
-       $ret = pipe_through_program($data, 
-                 "fipsdrv --verbose --key $keyfile --signature $sigfile dsa-verify");
-        unlink ($sigfile);
+       $ret = pipe_through_program($data,
+               "fipsdrv --verbose --key $keyfile --signature $sigfile dsa-verify");
+       unlink ($sigfile);
        # Parse through the output information
        return ($ret =~ /GOOD signature/);
 }
 
-
-
 ######### End of libgcrypt implementation ################
 
 ################################################################
@@ -1216,10 +1213,14 @@ sub crypto_mct($$$$$$$$) {
 
                # TDES inner loop implements logic within driver
                if ($cipher =~ /des/) {
+                       # Need to provide a dummy IV in case of ECB mode.
+                       my $iv_arg = (defined($iv) && $iv ne "")
+                                       ? bin2hex($iv)
+                                       : "00"x(length($source_data));
                        print $CI "1\n"
                                  .$iloop."\n"
                                  .bin2hex($key1)."\n"
-                                 .bin2hex($iv)."\n"
+                                 .$iv_arg."\n"
                                  .bin2hex($source_data)."\n\n" or die;
                        chomp(my $line = <$CO>);
                        $calc_data = hex2bin($line);
@@ -1228,7 +1229,7 @@ sub crypto_mct($$$$$$$$) {
                        chomp($line = <$CO>);
                        $old_old_calc_data = hex2bin($line);
                        chomp($line = <$CO>);
-                       $iv = hex2bin($line);
+                       $iv = hex2bin($line) if (defined($iv) && $iv ne "");
                        chomp($line = <$CO>);
                        $next_source = hex2bin($line);
                        # Skip over empty line.
@@ -1309,13 +1310,13 @@ sub crypto_mct($$$$$$$$) {
                } elsif (!$enc && $cipher =~ /des-ede3-cfb/) {
                        #TDES decryption CFB has a special rule
                        $source_data = $next_source;
+               } elsif ( $ciph =~ /rc4/ || $cipher eq "des-ede3" || $cipher =~ /ecb/) {
+                       #No resetting of IV as the IV is all zero set initially (i.e. no IV)
+                       $source_data = $calc_data;
                } 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;
                } else {
                        $iv = $calc_data;
                        $source_data = $old_calc_data;
@@ -1539,7 +1540,7 @@ sub dsa_sigver($$$$$$$$) {
        # but since it is not run on a security sensitive
        # system, I hope that this is fine
        my $keyfile = "dsa_sigver.tmp.$$";
-       &dsa_genpubkey($keyfile, $p, $q, $g, $y);
+       &$dsa_genpubkey($keyfile, $p, $q, $g, $y);
 
        $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n");
 
@@ -1614,7 +1615,6 @@ sub parse($$) {
        my $capital_g = "";
        my $capital_y = "";
        my $capital_r = "";
-       my $capital_s = "";
 
        my $mode = "";
 
@@ -1696,7 +1696,7 @@ sub parse($$) {
                        ##### Identify the test type
                                if ($tmpline =~ /SigVer/ && $opt{'D'} ) {
                                        $tt = 12;
-                                       die "Interface function dsa_verify or dsa_genpubey for dSA verification not defined for tested library"
+                                       die "Interface function dsa_verify or dsa_genpubkey for DSA verification not defined for tested library"
                                                if (!defined($dsa_verify) || !defined($dsa_genpubkey));
                                } elsif ($tmpline =~ /SigGen/ && $opt{'D'}) {
                                        $tt = 11;
@@ -1873,44 +1873,39 @@ sub parse($$) {
                                if ($tlen ne "");
                        $tlen=$1;
                }
-               elsif ($line =~ /^N\s*=\s*(.)/) { #DSA PQGGen
+               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
+               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
+               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
+               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
+               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
+               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";
                }
@@ -2009,7 +2004,7 @@ sub parse($$) {
                            $capital_g ne "" &&
                            $capital_y ne "" &&
                            $capital_r ne "" &&
-                           $capital_s ne "" &&
+                           $signature ne "" &&
                            $pt ne "") {
                                $out .= dsa_sigver($modulus,
                                                   $capital_p,
@@ -2017,7 +2012,7 @@ sub parse($$) {
                                                   $capital_g,
                                                   $capital_y,
                                                   $capital_r,
-                                                  $capital_s,
+                                                  $signature,
                                                   $pt);
 
                                # We do not clear the domain values PQG and
@@ -2027,7 +2022,7 @@ sub parse($$) {
                                # are already printed above
                                $capital_y = "";
                                $capital_r = "";
-                               $capital_s = "";
+                               $signature = "";
                                $pt = "";
                        }
                }
@@ -2051,7 +2046,8 @@ sub cleanup() {
        unlink("rsa_sigver.tmp.$$.sig");
        unlink("rsa_sigver.tmp.$$.der");
        unlink("rsa_sigver.tmp.$$.cnf");
-
+       unlink("dsa_siggen.tmp.$$");
+       unlink("dsa_sigver.tmp.$$");
        unlink("dsa_sigver.tmp.$$.sig");
        exit;
 }
@@ -2087,10 +2083,10 @@ sub main() {
                $state_rng =    \&libgcrypt_state_rng;
                $hmac =         \&libgcrypt_hmac;
                $dsa_pqggen =   \&libgcrypt_dsa_pqggen;
-               $gen_dsakey =   \&libgcrypt_gen_dsakey;
-               $dsa_sign =     \&libgcrypt_dsa_sign;
-               $dsa_verify =   \&libgcrypt_dsa_verify;
-                $dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
+               $gen_dsakey =   \&libgcrypt_gen_dsakey;
+               $dsa_sign =     \&libgcrypt_dsa_sign;
+               $dsa_verify =   \&libgcrypt_dsa_verify;
+               $dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
         } else {
                 die "Invalid interface option given";
         }
@@ -2121,8 +2117,6 @@ sub main() {
        # Do the job
        parse($infile, $outfile);
 
-       unlink("rsa_siggen.tmp.$$");
-
 }
 
 ###########################################
index 79059b4..963788b 100644 (file)
@@ -1915,15 +1915,11 @@ run_dsa_verify (const void *data, size_t datalen,
 {
   gpg_error_t err;
   gcry_sexp_t s_data, s_key, s_sig;
-  gcry_mpi_t tmpmpi;
+  char hash[20];
   
-  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, data, datalen, NULL);
-  if (!err)
-    {
-      err = gcry_sexp_build (&s_data, NULL,
-                             "(data (flags raw)(value %m))", tmpmpi);
-      gcry_mpi_release (tmpmpi);
-    }
+  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
+  err = gcry_sexp_build (&s_data, NULL,
+                         "(data (flags raw)(value %b))", 20, hash);
   if (err)
     die ("gcry_sexp_build failed for DSA data input: %s\n",
          gpg_strerror (err));
index 1fe0202..9e47589 100644 (file)
@@ -505,6 +505,46 @@ get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
 
 
 static void
+get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
+{
+  gcry_sexp_t key_spec, key, pub_key, sec_key;
+  int rc;
+
+  rc = gcry_sexp_new 
+    (&key_spec,
+     "(genkey"
+     "  (dsa" 
+     "    (nbits 4:1024)"
+     "    (use-fips186)"
+     "    (transient-key)"
+     "    (derive-parms"
+     "      (seed #0cb1990c1fd3626055d7a0096f8fa99807399871#))))",
+     0, 1);
+  if (rc)
+    die ("error creating S-expression: %s\n", gcry_strerror (rc));
+  rc = gcry_pk_genkey (&key, key_spec);
+  gcry_sexp_release (key_spec);
+  if (rc)
+    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    
+  if (verbose > 1 || 1)
+    show_sexp ("generated DSA key (fips 186 with seed):\n", key);
+
+  pub_key = gcry_sexp_find_token (key, "public-key", 0);
+  if (!pub_key)
+    die ("public part missing in key\n");
+
+  sec_key = gcry_sexp_find_token (key, "private-key", 0);
+  if (!sec_key)
+    die ("private part missing in key\n");
+
+  gcry_sexp_release (key);
+  *pkey = pub_key;
+  *skey = sec_key;
+}
+
+
+static void
 check_run (void)
 {
   gpg_error_t err;
@@ -592,6 +632,13 @@ check_run (void)
   /* Fixme:  Add a check function for DSA keys.  */
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+
+  if (verbose)
+    fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n");
+  get_dsa_key_fips186_with_seed_new (&pkey, &skey);
+  /* Fixme:  Add a check function for DSA keys.  */
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
 }