[svn] gcry - r1356 - trunk/tests

svn author wk cvs at cvs.gnupg.org
Fri Nov 7 17:07:02 CET 2008


Author: wk
Date: 2008-11-07 17:07:02 +0100 (Fri, 07 Nov 2008)
New Revision: 1356

Modified:
   trunk/tests/ChangeLog
   trunk/tests/cavs_driver.pl
   trunk/tests/fipsdrv.c
Log:
Implement mct server mode for fips driver and use it in the CAVS tests to
speed up things and to get hold of intermediate values we could not easily
retrieve with the old implementaion.


Modified: trunk/tests/ChangeLog
===================================================================
--- trunk/tests/ChangeLog	2008-11-05 19:13:22 UTC (rev 1355)
+++ trunk/tests/ChangeLog	2008-11-07 16:07:02 UTC (rev 1356)
@@ -1,3 +1,10 @@
+2008-11-07  Werner Koch  <wk at g10code.com>
+
+	* fipsdrv.c (run_cipher_mct_loop, get_current_iv): New.
+	(read_textline, read_hexline, skip_to_empty_line): New.
+	(main): New option --mct-server.
+	* cavs_driver.pl: Update from upstream and adjust to new fipsdrv.
+
 2008-11-05  Werner Koch  <wk at g10code.com>
 
 	* fipsdrv.c (run_encrypt_decrypt): Disable weak key detection.

Modified: trunk/tests/cavs_driver.pl
===================================================================
--- trunk/tests/cavs_driver.pl	2008-11-05 19:13:22 UTC (rev 1355)
+++ trunk/tests/cavs_driver.pl	2008-11-07 16:07:02 UTC (rev 1356)
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 #
-# $Id: cavs_driver.pl 1243 2008-09-18 18:42:57Z smueller $
+# $Id: cavs_driver.pl 1383 2008-10-30 11:45:31Z smueller $
 #
 # CAVS test driver (based on the OpenSSL driver)
 # Written by: Stephan Müller <sm at atsec.com>
@@ -206,8 +206,12 @@
 	my $enc = (shift) ? "-e" : "-d";
 	my $data=shift;
 
+	# We only invoke the driver with the IV parameter, if we have
+	# an IV, otherwise, we skip it
+	$iv = "-iv $iv" if ($iv);
+
 	$data=hex2bin($data);
-	my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc -iv $iv";
+	my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc $iv";
 	$program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given
 	$data=pipe_through_program($data,$program);
 	return bin2hex($data);
@@ -269,9 +273,15 @@
 	my $key = shift;
 	my $iv = shift;
 
+        #FIXME: Implement the inner loop right here.
+
 	my $enc = $encdec ? "-e": "-d";
 
-	my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." -iv ".bin2hex($iv);
+	# 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 $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." $iv";
 	#for ARCFOUR, no IV must be given
 	$out = "rc4 -k " . bin2hex($key) if $opt{'R'};
 	return $out;
@@ -289,11 +299,14 @@
 	my $enc = (shift) ? "encrypt" : "decrypt";
 	my $data=shift;
 
-        $iv = "--iv $iv" if ($iv);
+	# We only invoke the driver with the IV parameter, if we have
+	# an IV, otherwise, we skip it
+	$iv = "--iv $iv" if ($iv);
 
 	my $program="fipsdrv --key $key $iv --algo $cipher $enc";
 
 	return pipe_through_program($data,$program);
+
 }
 
 sub libgcrypt_rsa_sign($$$) {
@@ -302,8 +315,9 @@
 	my $keyfile = shift;
 
 	die "ARCFOUR not available for RSA" if $opt{'R'};
+
 	return pipe_through_program($data,
-		"fipsdrv --verbose --pkcs1 --algo $hashalgo --key $keyfile rsa-sign");
+		"fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign");
 }
 
 sub libgcrypt_rsa_verify($$$$) {
@@ -314,7 +328,7 @@
 
 	die "ARCFOUR not available for RSA" if $opt{'R'};
 	$data = pipe_through_program($data,
-		"fipsdrv --verbose --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify");
+		"fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify");
 
 	# Parse through the output information
 	return ($data =~ /GOOD signature/);
@@ -348,9 +362,7 @@
 	my $key = shift;
 	my $iv = shift;
 
-        $iv = "--iv $iv" if ($iv);
-
-	my $program="fipsdrv --binary --key ".bin2hex($key)." $iv ".bin2hex($iv)." --algo '$cipher' --chunk '$bufsize' $enc";
+	my $program="fipsdrv --algo '$cipher' --mct-server $enc";
 	return $program;
 }
 
@@ -359,7 +371,7 @@
 	my $dt = shift;
 	my $v = shift;
 
-	return "fipsdrv --binary --progress --loop --key $key --iv $v --dt $dt random";
+	return "fipsdrv --binary --loop --key $key --iv $v --dt $dt random";
 }
 
 sub libgcrypt_hmac($$$$) {
@@ -930,7 +942,9 @@
 	my $out = "";
 	$out .= "Len = $len\n" if (defined($len));
 	$out .= "Msg = $pt\n";
-	$out .= "MD = " . &$hash($pt, $cipher);
+
+	$pt = "" if(!$len);
+	$out .= "MD = " . &$hash($pt, $cipher) . "\n";
 	return $out;
 }
 
@@ -994,6 +1008,8 @@
         my $source_data = hex2bin(shift);
 	my $cipher = shift;
         my $enc = shift;
+        my $line;
+        my $next_source;
 
 	my $out = "";
 
@@ -1009,7 +1025,17 @@
 	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;
+
 		$out .= "COUNT = $i\n";
 		if (defined($key2)) {
 			$out .= "$keytype = ". bin2hex($key1). "\n";
@@ -1032,43 +1058,40 @@
                 } else {
                         $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n";
                 }
-                my ($CO, $CI);
-		my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
-                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]
-                for (my $j = 0; $j < $iloop; ++$j) {
-			$old_old_calc_data = $old_calc_data;
-                        $old_calc_data = $calc_data;
+                print $CI "1\n"
+                          .$iloop."\n"
+                          .bin2hex($key1)."\n"
+                          .bin2hex($iv)."\n"
+                          .bin2hex($source_data)."\n\n" or die;
+                
+                # fixme: We should skip over empty lines here.
 
-			# $calc_data = AES($key, $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";
+                chomp($line = <$CO>); #print STDERR "        calc=$line\n";
+                $calc_data = hex2bin($line);
 
-			if ( (!$enc && $ciph =~ /des/) ||
-			     $ciph =~ /rc4/ ) {
-				#TDES in decryption mode and RC4 have a special rule
-				$source_data = $calc_data;
-			} else {
-	                        $source_data = $old_calc_data;
-			}
-                }
-                close $CO;
-                close $CI;
-                waitpid $pid, 0;
+                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>;
+
+
                 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";
@@ -1106,18 +1129,25 @@
 			die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing";
 		}
 
-		if (! $enc && $ciph =~ /des/ ) {
-			#TDES in decryption mode has a special rule
-			$iv = $old_calc_data;
-			$source_data = $calc_data;
-		} elsif ( $ciph =~ /rc4/ ) {
+                if ($ciph =~ /des/) {
+                    $iv = $ov;
+                    if ($cipher =~ /des-ede3-ofb/) {
+                        $source_data = $source_data ^ $next_source;
+                    } else {
+                        $source_data = $next_source;
+                    }
+		} 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;
 		}
+
         }
+        close $CO;
+        close $CI;
+        waitpid $pid, 0;
 
 	return $out;
 }
@@ -1133,13 +1163,14 @@
 	my $out = "";
 
 	$out .= "Seed = $pt\n\n";
-	
+
         for (my $j=0; $j<100; ++$j) {
 		$out .= "COUNT = $j\n";
 		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;
@@ -1164,10 +1195,10 @@
 	my $keyfile = shift;
 
 	my $out = "";
-	
+
 	$out .= "SHAAlg = $cipher\n";
 	$out .= "Msg = $data\n";
-	$out .= "S = " . &$rsa_sign($data, $cipher, $keyfile) . "\n";
+	$out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n";
 
 	return $out;
 }
@@ -1204,7 +1235,7 @@
 	print FH hex2bin($signature);
 	close FH;
 
-	$out .= "Result = " . (&$rsa_verify($data, $cipher, $keyfile, $sigfile) ? "P\n" : "F\n");
+	$out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n");
 
 	unlink($keyfile);
 	unlink($sigfile);
@@ -1392,44 +1423,50 @@
 				}
 			}
 
-
+			if ($tt == 0) {
 			##### Identify the test type
-			if ($tmpline =~ /Hash sizes tested/) {
-				$tt = 9;
-				die "Interface function hmac for HMAC testing not defined for tested library"
-					if (!defined($hmac));
-			} elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
-				$tt = 8;
-				die "Interface function state_rng for RNG MCT not defined for tested library"
-					if (!defined($state_rng));
-			} elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
-				$tt = 7;
-				die "Interface function state_rng for RNG KAT not defined for tested library"
-					if (!defined($state_rng));
-			} elsif ($tmpline =~ /SigVer/ ) {
-				$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/ ) {
-				$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));
-			} elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher eq "sha") {
-				$tt = 4;
-				die "Interface function hash for Hashing not defined for tested library"
-					if (!defined($hash));
-			} elsif ($tmpline =~ /Monte|MCT|Carlo/) {
-				$tt = 2;
-				die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
-					if (!defined($state_cipher));
-			} elsif ($cipher =~ /^sha\d+/ && $tt!=5 && $tt!=6) {
-				$tt = 3;
-				die "Interface function hash for Hashing not defined for tested library"
-					if (!defined($hash));
-			} else {
-				$tt = 1;
-				die "Interface function encdec for Encryption/Decryption not defined for tested library"
-					if (!defined($encdec));
+				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/) {
+					$tt = 9;
+					die "Interface function hmac for HMAC testing not defined for tested library"
+						if (!defined($hmac));
+				} elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
+					$tt = 8;
+					die "Interface function state_rng for RNG MCT not defined for tested library"
+						if (!defined($state_rng));
+				} elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
+					$tt = 7;
+					die "Interface function state_rng for RNG KAT not defined for tested library"
+						if (!defined($state_rng));
+				} elsif ($tmpline =~ /SigVer/ ) {
+					$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/ ) {
+					$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));
+				} elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher =~ /^sha/) {
+					$tt = 4;
+					die "Interface function hash for Hashing not defined for tested library"
+						if (!defined($hash));
+				} elsif ($tmpline =~ /Monte|MCT|Carlo/) {
+					$tt = 2;
+					die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
+						if (!defined($state_cipher));
+				} elsif ($cipher =~ /^sha/) {
+					$tt = 3;
+					die "Interface function hash for Hashing not defined for tested library"
+						if (!defined($hash));
+				} else {
+					$tt = 1;
+					die "Interface function encdec for Encryption/Decryption not defined for tested library"
+						if (!defined($encdec));
+				}
 			}
 		}
 
@@ -1449,12 +1486,20 @@
 		}
 
 		# Get the test data
-		if ($line =~ /^(KEY|KEYs|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
+		if ($line =~ /^(KEY|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
 			die "KEY seen twice - input file crap" if ($key1 ne "");
 			$keytype=$1;
 			$key1=$2;
 			$key1 =~ s/\s//g; #replace potential white spaces
 		}
+		elsif ($line =~ /^(KEYs)\s*=\s*(.*)/) { # found in ciphers and RNG
+			die "KEY seen twice - input file crap" if ($key1 ne "");
+			$keytype=$1;
+			$key1=$2;
+			$key1 =~ s/\s//g; #replace potential white spaces
+			$key2 = $key1;
+			$key3 = $key1;
+		}
 		elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES
 			die "First key not set, but got already second key - input file crap" if ($key1 eq "");
 			die "KEY2 seen twice - input file crap" if (defined($key2));

Modified: trunk/tests/fipsdrv.c
===================================================================
--- trunk/tests/fipsdrv.c	2008-11-05 19:13:22 UTC (rev 1355)
+++ trunk/tests/fipsdrv.c	2008-11-07 16:07:02 UTC (rev 1356)
@@ -70,9 +70,6 @@
 /* We need to know whetehr we are in loop_mode.  */
 static int loop_mode;
 
-/* If true the input vectors are printed before and after encryption
-   and decryption.  */
-static int print_ivs;
 
 /* ASN.1 classes.  */
 enum
@@ -212,6 +209,78 @@
   return buffer;
 }
 
+
+static char *
+read_textline (FILE *fp)
+{
+  char line[256];
+  char *p;
+  int any = 0;
+
+  /* Read line but skip over initial empty lines.  */
+  do
+    {
+      do 
+        {
+          if (!fgets (line, sizeof line, fp))
+            {
+              if (feof (fp))
+                return NULL;
+              die ("error reading input line: %s\n", strerror (errno));
+            }
+          p = strchr (line, '\n');
+          if (p)
+            *p = 0;
+          p = line + (*line? (strlen (line)-1):0);
+          for ( ;p > line; p--)
+            if (my_isascii (*p) && isspace (*p))
+              *p = 0;
+        }
+      while (!any && !*line);
+      any = 1;
+    }
+  while (*line == '#');  /* Always skip comment lines.  */
+  return gcry_xstrdup (line);
+}
+
+static char *
+read_hexline (FILE *fp, size_t *retlen)
+{
+  char *line, *p;
+
+  line = read_textline (fp);
+  if (!line)
+    return NULL;
+  p = hex2buffer (line, retlen);
+  if (!p)
+    die ("error decoding hex string on input\n");
+  gcry_free (line);
+  return p;
+}
+
+static void
+skip_to_empty_line (FILE *fp)
+{
+  char line[256];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      p = strchr (line, '\n');
+      if (p)
+        *p =0;
+    }
+  while (*line);
+}
+
+
+
 /* Read a file from stream FP into a newly allocated buffer and return
    that buffer.  The valid length of the buffer is stored at R_LENGTH.
    Returns NULL on failure.  If decode is set, the file is assumed to
@@ -909,58 +978,131 @@
       else
         inbuflen = datalen;
 
-      if (print_ivs)
-        {
-          /* If we want to print the input vectors we need to pass the
-             data block by block to the encryption function.  */
-          unsigned char tmp[17];
-          const unsigned char *iptr = data;
-          size_t ilen;
-          
-          do
-            {
-              ilen = inbuflen > blocklen? blocklen : inbuflen;
-              
-              if (gcry_cipher_ctl (hd, PRIV_CTL_GET_INPUT_VECTOR,
-                                   tmp, sizeof tmp))
-                die ("error getting input block\n");
-              print_buffer (tmp+1, *tmp);
-              putchar ('\n');
+      if (encrypt_mode)
+        err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
+      else
+        err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen);
+      if (err)
+        die ("gcry_cipher_%scrypt failed: %s\n",
+             encrypt_mode? "en":"de", gpg_strerror (err));
+      
+      print_buffer (outbuf, outbuflen);
+    }
+  while (inbuf);
 
-              if (encrypt_mode)
-                err = gcry_cipher_encrypt (hd, outbuf, blocklen, iptr, ilen);
-              else
-                err = gcry_cipher_decrypt (hd, outbuf, blocklen, iptr, ilen);
-              if (err)
-                die ("gcry_cipher_%scrypt failed: %s\n",
-                     encrypt_mode? "en":"de", gpg_strerror (err));
-              
-              print_buffer (outbuf, blocklen);
-              putchar ('\n');
+  gcry_cipher_close (hd);
+  gcry_free (outbuf);
+  gcry_free (inbuf);
+}
 
-              iptr += ilen;
-              inbuflen -= ilen;
-             }
-          while (inbuflen);
-        }
+
+static void
+get_current_iv (gcry_cipher_hd_t hd, void *buffer, size_t buflen)
+{
+  unsigned char tmp[17];
+
+  if (gcry_cipher_ctl (hd, PRIV_CTL_GET_INPUT_VECTOR, tmp, sizeof tmp))
+    die ("error getting current input vector\n");
+  if (buflen > *tmp)
+    die ("buffer too short to store the current input vector\n");
+  memcpy (buffer, tmp+1, *tmp);
+}
+
+/* Run the inner loop of the CAVS monte carlo test.  */
+static void
+run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode, 
+                     const void *iv_buffer, size_t iv_buflen,
+                     const void *key_buffer, size_t key_buflen,
+                     const void *data, size_t datalen, int iterations)
+{
+  gpg_error_t err;
+  gcry_cipher_hd_t hd;
+  size_t blocklen;
+  int count;
+  char input[16];
+  char output[16];
+  char last_output[16];
+  char last_last_output[16];
+  char last_iv[16]; 
+
+
+  err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0);
+  if (err)
+    die ("gcry_cipher_open failed for algo %d, mode %d: %s\n", 
+         cipher_algo, cipher_mode, gpg_strerror (err));
+
+  blocklen = gcry_cipher_get_algo_blklen (cipher_algo);
+  if (!blocklen || blocklen > sizeof output)
+    die ("invalid block length %d\n", blocklen);
+
+
+  gcry_cipher_ctl (hd, PRIV_CTL_DISABLE_WEAK_KEY, NULL, 0);
+
+  err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
+  if (err)
+    die ("gcry_cipher_setkey failed with keylen %u: %s\n",
+         (unsigned int)key_buflen, gpg_strerror (err));
+
+  if (iv_buffer)
+    {
+      err = gcry_cipher_setiv (hd, iv_buffer, iv_buflen);
+      if (err)
+        die ("gcry_cipher_setiv failed with ivlen %u: %s\n",
+             (unsigned int)iv_buflen, gpg_strerror (err));
+    }
+
+  if (datalen != blocklen)
+    die ("length of input (%u) does not match block length (%u)\n", 
+         (unsigned int)datalen, (unsigned int)blocklen);
+  memcpy (input, data, datalen);
+  memset (output, 0, sizeof output);
+  for (count=0; count < iterations; count++)
+    {
+      memcpy (last_last_output, last_output, sizeof last_output);
+      memcpy (last_output, output, sizeof output);
+
+      get_current_iv (hd, last_iv, blocklen);
+
+      if (encrypt_mode)
+        err = gcry_cipher_encrypt (hd, output, blocklen, input, blocklen);
       else
+        err = gcry_cipher_decrypt (hd, output, blocklen, input, blocklen);
+      if (err)
+        die ("gcry_cipher_%scrypt failed: %s\n",
+             encrypt_mode? "en":"de", gpg_strerror (err));
+
+  
+      if (encrypt_mode && (cipher_mode == GCRY_CIPHER_MODE_CFB
+                           || cipher_mode == GCRY_CIPHER_MODE_CBC))
+        memcpy (input, last_iv, blocklen);
+      else if (cipher_mode == GCRY_CIPHER_MODE_OFB)
+        memcpy (input, last_iv, blocklen);
+      else if (!encrypt_mode && cipher_mode == GCRY_CIPHER_MODE_CFB)
         {
-          if (encrypt_mode)
-            err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
-          else
-            err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen);
-          if (err)
-            die ("gcry_cipher_%scrypt failed: %s\n",
-                 encrypt_mode? "en":"de", gpg_strerror (err));
-          
-          print_buffer (outbuf, outbuflen);
+          /* Reconstruct the output vector.  */
+          int i;
+          for (i=0; i < blocklen; i++)
+            input[i] ^= output[i];
         }
+      else
+        memcpy (input, output, blocklen);
     }
-  while (inbuf);
 
+  print_buffer (output, blocklen);
+  putchar ('\n');
+  print_buffer (last_output, blocklen);
+  putchar ('\n');
+  print_buffer (last_last_output, blocklen);
+  putchar ('\n');
+  get_current_iv (hd, last_iv, blocklen);
+  print_buffer (last_iv, blocklen); /* Last output vector.  */
+  putchar ('\n');
+  print_buffer (input, blocklen);   /* Next input text. */
+  putchar ('\n');
+  putchar ('\n');
+  fflush (stdout);
+
   gcry_cipher_close (hd);
-  gcry_free (outbuf);
-  gcry_free (inbuf);
 }
 
 
@@ -1367,7 +1509,7 @@
      "  --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"
-     "  --print-ivs      Print input vectors\n"
+     "  --mct-server     Run a monte carlo test server\n"
      "  --loop           Enable random loop mode\n"
      "  --progress       Print pogress indicators\n"
      "  --help           Print this text\n"
@@ -1395,6 +1537,7 @@
   void *data;
   size_t datalen;
   size_t chunksize = 0;
+  int mct_server = 0;
 
 
   if (argc)
@@ -1504,9 +1647,9 @@
           use_pkcs1 = 1;
           argc--; argv++;
         }
-      else if (!strcmp (*argv, "--print-ivs"))
+      else if (!strcmp (*argv, "--mct-server"))
         {
-          print_ivs = 1;
+          mct_server = 1;
           argc--; argv++;
         }
     }          
@@ -1544,6 +1687,7 @@
 
   /* Most operations need some input data.  */
   if (!chunksize
+      && !mct_server
       && strcmp (mode_string, "random")
       && strcmp (mode_string, "rsa-gen") )
     {
@@ -1564,7 +1708,8 @@
   if (!strcmp (mode_string, "encrypt") || !strcmp (mode_string, "decrypt"))
     {
       int cipher_algo, cipher_mode;
-      void  *iv_buffer, *key_buffer;
+      void  *iv_buffer = NULL;
+      void *key_buffer = NULL;
       size_t iv_buflen,  key_buflen;
 
       if (!algo_string)
@@ -1572,30 +1717,70 @@
       cipher_algo = map_openssl_cipher_name (algo_string, &cipher_mode);
       if (!cipher_algo)
         die ("cipher algorithm `%s' is not supported\n", algo_string);
-      if (cipher_mode != GCRY_CIPHER_MODE_ECB)
+      if (mct_server)
         {
-          if (!iv_string)
-            die ("option --iv is required in this mode\n");
-          iv_buffer = hex2buffer (iv_string, &iv_buflen);
-          if (!iv_buffer)
-            die ("invalid value for IV\n");
+          int iterations;
+
+          for (;;)
+            {
+              gcry_free (key_buffer); key_buffer = NULL;
+              gcry_free (iv_buffer); iv_buffer = NULL;
+              gcry_free (data); data = NULL;
+              if (!(key_buffer = read_textline (input)))
+                {
+                  if (feof (input))
+                    break;
+                  die ("no version info in input\n");
+                }
+              if (atoi (key_buffer) != 1)
+                die ("unsupported input version %s\n", key_buffer);
+              gcry_free (key_buffer);
+              if (!(key_buffer = read_textline (input)))
+                die ("no iteration count in input\n");
+              iterations = atoi (key_buffer);
+              gcry_free (key_buffer);
+              if (!(key_buffer = read_hexline (input, &key_buflen)))
+                die ("no key in input\n");
+              if (!(iv_buffer = read_hexline (input, &iv_buflen)))
+                die ("no IV in input\n");
+              if (!(data = read_hexline (input, &datalen)))
+                die ("no data in input\n");
+              skip_to_empty_line (input);
+              
+              run_cipher_mct_loop ((*mode_string == 'e'),
+                                   cipher_algo, cipher_mode,
+                                   iv_buffer, iv_buflen,
+                                   key_buffer, key_buflen,
+                                   data, datalen, iterations);
+            }
         }
       else
         {
-          iv_buffer = NULL;
-          iv_buflen = 0;
+          if (cipher_mode != GCRY_CIPHER_MODE_ECB)
+            {
+              if (!iv_string)
+                die ("option --iv is required in this mode\n");
+              iv_buffer = hex2buffer (iv_string, &iv_buflen);
+              if (!iv_buffer)
+                die ("invalid value for IV\n");
+            }
+          else
+            {
+              iv_buffer = NULL;
+              iv_buflen = 0;
+            }
+          if (!key_string)
+            die ("option --key is required in this mode\n");
+          key_buffer = hex2buffer (key_string, &key_buflen);
+          if (!key_buffer)
+            die ("invalid value for KEY\n");
+
+          run_encrypt_decrypt ((*mode_string == 'e'),
+                               cipher_algo, cipher_mode,
+                               iv_buffer, iv_buflen,
+                               key_buffer, key_buflen,
+                               data, data? datalen:chunksize, input);
         }
-      if (!key_string)
-        die ("option --key is required in this mode\n");
-      key_buffer = hex2buffer (key_string, &key_buflen);
-      if (!key_buffer)
-        die ("invalid value for KEY\n");
-
-      run_encrypt_decrypt ((*mode_string == 'e'),
-                           cipher_algo, cipher_mode,
-                           iv_buffer, iv_buflen,
-                           key_buffer, key_buflen,
-                           data, data? datalen:chunksize, input);
       gcry_free (key_buffer);
       gcry_free (iv_buffer);
     }
@@ -1608,6 +1793,8 @@
       algo = gcry_md_map_name (algo_string);
       if (!algo)
         die ("digest algorithm `%s' is not supported\n", algo_string);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
 
       run_digest (algo, data, datalen);
     }




More information about the Gnupg-commits mailing list