[svn] gcry - r1346 - in trunk: . cipher doc src tests

svn author wk cvs at cvs.gnupg.org
Thu Oct 2 20:53:32 CEST 2008


Author: wk
Date: 2008-10-02 20:53:31 +0200 (Thu, 02 Oct 2008)
New Revision: 1346

Added:
   trunk/tests/cavs_tests.sh
   trunk/tests/fipsdrv.c
Modified:
   trunk/AUTHORS
   trunk/NEWS
   trunk/cipher/rsa.c
   trunk/configure.ac
   trunk/doc/ChangeLog
   trunk/doc/announce.txt
   trunk/doc/fips-fsm.fig
   trunk/doc/gcrypt.texi
   trunk/src/ChangeLog
   trunk/src/cipher-proto.h
   trunk/src/cipher.h
   trunk/src/dumpsexp.c
   trunk/src/fips.c
   trunk/src/gcrypt-module.h
   trunk/src/gcrypt.h.in
   trunk/src/module.c
   trunk/tests/ChangeLog
   trunk/tests/Makefile.am
   trunk/tests/benchmark.c
   trunk/tests/cavs_driver.pl
   trunk/tests/fipsrngdrv.c
Log:
Add CAVS test.
Various minor fixes.
Sigbus fixes for AES.


[The diff below has been truncated]

Modified: trunk/doc/ChangeLog
===================================================================
--- trunk/doc/ChangeLog	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/doc/ChangeLog	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1,5 +1,10 @@
 2008-09-18  Werner Koch  <wk at g10code.com>
 
+	* gcrypt.texi (FIPS Mode): Add state transition Error to Error.
+	* fips-fsm.fig: Ditto.
+
+2008-09-18  Werner Koch  <wk at g10code.com>
+
 	* gcrypt.texi: Add a couple of index items.
 	(FIPS Mode): Reflect recent changes. 
 	(Controlling the library): Describe gcry_fips_mode_active.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/ChangeLog	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1,5 +1,22 @@
+2008-09-29  Werner Koch  <wk at g10code.com>
+
+	* gcrypt-module.h (GCRY_MODULE_ID_USER, GCRY_MODULE_ID_USER_LAST):
+	New.
+	* module.c (MODULE_ID_USER, MODULE_ID_USER_LAST): Define using new
+	macros.
+
+2008-09-20  Werner Koch  <wk at g10code.com>
+
+	* hmac256.c (finalize) [WORDS_BIGENDIAN]: Fix sigbus problem.
+
 2008-09-18  Werner Koch  <wk at g10code.com>
 
+	* cipher-proto.h (pk_ext_generate_t): Add args QBITS, NAME, DOMAIN.
+
+	* fips.c (fips_new_state): Allow Error => Error transition.
+
+2008-09-18  Werner Koch  <wk at g10code.com>
+
 	* gcrypt.h.in (gcry_fips_mode_active): New.
 
 	* secmem.c (_gcry_secmem_init): Factor most code out to ..

Modified: trunk/tests/ChangeLog
===================================================================
--- trunk/tests/ChangeLog	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/tests/ChangeLog	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1,5 +1,27 @@
+2008-10-02  Werner Koch  <wk at g10code.com>
+
+	* fipsdrv.c (print_buffer): Add base64 printing code.
+	(base64_decode, read_key_file,parse_tag): New.
+	(run_rsa_gen, run_rsa_sign): New.
+	(main): Add mode rsa-gen and rsa-sign.
+
+2008-09-29  Werner Koch  <wk at g10code.com>
+
+	* fipsdrv.c: Merge code from fipsrngdrv.c
+	* fipsrngdrv.c: Remove.
+
+2008-09-26  Werner Koch  <wk at g10code.com>
+
+	* Makefile.am: Distribute cavs_driver.pl.
+	* cavs_tests.sh: New. 
+	* fipsdrv.c: New.
+
 2008-09-18  Werner Koch  <wk at g10code.com>
 
+	* benchmark.c (main): Do not disable secure memory in FIPS mode.
+
+2008-09-18  Werner Koch  <wk at g10code.com>
+
 	* basic.c (main): Do not disable secure memory in FIPS mode.
 
 2008-09-16  Werner Koch  <wk at g10code.com>
@@ -604,7 +626,7 @@
 	* tsexp.c: New.
 
 	
- Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2008 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

Modified: trunk/AUTHORS
===================================================================
--- trunk/AUTHORS	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/AUTHORS	2008-10-02 18:53:31 UTC (rev 1346)
@@ -110,7 +110,12 @@
 The implementation of the Camellia cipher has been been taken from the
 original NTT provided GPL source.
 
+The CAVS testing program tests/cavs_driver.pl is not to be considered
+a part of libgcrypt proper.  We distribute it merely for convenience.
+It has a permissive license and is copyright by atsec information
+security corporation.  See the file for details.
 
+
  Copyright 1998, 1999, 2000, 2001, 2002, 2003,
            2006, 2007, 2008 Free Software Foundation, Inc.
 

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/NEWS	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1,3 +1,10 @@
+Noteworthy changes in version 1.4.4
+------------------------------------------------
+
+ * Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
+   This functionality is in Libgcrypt since 1.3.0. 
+
+
 Noteworthy changes in version 1.4.3 (2008-09-18)
 ------------------------------------------------
 

Modified: trunk/cipher/rsa.c
===================================================================
--- trunk/cipher/rsa.c	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/cipher/rsa.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -175,7 +175,8 @@
  * USE_E = 0 let Libcgrypt decide what exponent to use.
  *       = 1 request the use of a "secure" exponent; this is required by some 
  *           specification to be 65537.
- *       > 2 Try starting at this value until a working exponent is found.
+ *       > 2 Use this public exponent.  If the given exponent
+ *           is not odd one is internally added to it. 
  * TRANSIENT_KEY:  If true, generate the primes using the standard RNG.
  * Returns: 2 structures filled with all needed values
  */

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/configure.ac	2008-10-02 18:53:31 UTC (rev 1346)
@@ -26,8 +26,8 @@
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [1.4.3])
-m4_define([my_issvn], [no])
+m4_define([my_version], [1.4.4])
+m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \
           | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))

Modified: trunk/doc/announce.txt
===================================================================
--- trunk/doc/announce.txt	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/doc/announce.txt	2008-10-02 18:53:31 UTC (rev 1346)
@@ -39,22 +39,26 @@
 listed at http://www.gnupg.org/download/mirrors.html .  On the primary
 server the source file and its digital signatures is:
 
- ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.bz2 (k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.bz2 (1062k)
  ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.bz2.sig
 
 This file is bzip2 compressed.  A gzip compressed version is also
 available:
 
- ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.gz (k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.gz (1325k)
  ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.gz.sig
 
 Alternativley you may upgrade version 1.4.2 using this patch file:
 
- ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.2-1.4.3.diff.bz2 (k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.2-1.4.3.diff.bz2 (42k)
 
 The SHA-1 checksums are:
 
+bdc67c1fdcec464a94dca691615f2335a12db5ce  libgcrypt-1.4.3.tar.bz2
+3d9d583501ce951596fa7dd3667afd357ac7d056  libgcrypt-1.4.3.tar.gz
+e28b74c5824364e20ae7f147f1b89925f5426669  libgcrypt-1.4.2-1.4.3.diff.bz2
 
+
 For help on developing with Libgcrypt you should read the included
 manual and optional ask on the gcrypt-devel mailing list [1].
 

Modified: trunk/doc/fips-fsm.fig
===================================================================
--- trunk/doc/fips-fsm.fig	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/doc/fips-fsm.fig	2008-10-02 18:53:31 UTC (rev 1346)
@@ -24,8 +24,10 @@
 	1 1 2.00 120.00 240.00
 5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 3026.138 8399.825 4185 8370 3870 7605 2925 7245
 	1 1 2.00 120.00 240.00
-5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 7708.125 -2028.750 2925 5175 4815 6120 6795 6570
+5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 7663.125 -2028.750 2880 5175 4770 6120 6750 6570
 	1 1 2.00 120.00 240.00
+5 1 0 2 0 7 50 -1 -1 0.000 1 1 1 0 7717.500 7211.250 7155 7470 7740 7830 8280 7470
+	1 1 2.00 120.00 240.00
 6 3096 1593 3380 1877
 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3238 1735 142 142 3238 1735 3103 1690
 4 0 0 50 -1 13 12 0.0000 4 105 105 3157 1805 1\001
@@ -134,14 +136,18 @@
 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4192 6338 142 142 4192 6338 4057 6293
 4 0 0 50 -1 13 12 0.0000 4 105 210 4066 6399 17\001
 -6
-6 3188 5033 3486 5331
-1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3337 5182 142 142 3337 5182 3202 5137
-4 0 0 50 -1 13 12 0.0000 4 105 210 3211 5243 18\001
--6
 6 3053 4358 3351 4656
 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3202 4507 142 142 3202 4507 3067 4462
 4 0 0 50 -1 13 12 0.0000 4 105 210 3076 4568 19\001
 -6
+6 3032 5012 3330 5310
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 3181 5161 142 142 3181 5161 3046 5116
+4 0 0 50 -1 13 12 0.0000 4 105 210 3055 5222 18\001
+-6
+6 7560 7847 7858 8145
+1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 7709 7996 142 142 7709 7996 7574 7951
+4 0 0 50 -1 13 12 0.0000 4 105 210 7612 8047 20\001
+-6
 2 1 0 2 0 7 50 -1 -1 0.000 0 1 -1 1 0 2
 	1 1 2.00 120.00 240.00
 	 3420 1395 3420 2295

Modified: trunk/doc/gcrypt.texi
===================================================================
--- trunk/doc/gcrypt.texi	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/doc/gcrypt.texi	2008-10-02 18:53:31 UTC (rev 1346)
@@ -2612,7 +2612,7 @@
 @c end gcry_pk_ctl
 
 @noindent
-Libgcrypt also provides a function for generating public key
+Libgcrypt also provides a function to generate public key
 pairs:
 
 @deftypefun gcry_error_t gcry_pk_genkey (@w{gcry_sexp_t *@var{r_key}}, @w{gcry_sexp_t @var{parms}})
@@ -2624,12 +2624,12 @@
 success or an error code otherwise.
 
 @noindent
-Here is an example for @var{parms} for creating a 1024 bit RSA key:
+Here is an example for @var{parms} to create an 2048 bit RSA key:
 
 @example
 (genkey
   (rsa
-    (nbits 4:1024)))
+    (nbits 4:2048)))
 @end example
 
 @noindent
@@ -2660,10 +2660,12 @@
 @item 0
 Use a secure and fast value.  This is currently the number 41.
 @item 1
-Use a secure value as required by some specification.  This is currently
+Use a value as required by some crypto policies.  This is currently
 the number 65537.
 @item 2
 Reserved
+ at item > 2
+Use the given value.
 @end table
 
 @noindent
@@ -2696,7 +2698,27 @@
 random number generator.  This flag may be used for keys which are only
 used for a short time and do not require full cryptographic strength.
 
+ at item domain
+This is only meaningful for DLP algorithms.  If specified keys are
+generated with domain parameters taken from this list.  The exact
+format of this parameter depends on the actual algorithm.  It is
+currently only implemented for DSA using this format:
 
+ at example
+(genkey
+  (dsa
+    (domain
+      (p @var{p-mpi})
+      (q @var{q-mpi})
+      (g @var{q-mpi})
+      (seed @var{seed-mpi})
+      (counter @var{counter-mpi})
+      (h @var{h-mpi}))))
+ at end example
+
+The @code{seed}, @code{counter} and @code{h} domain parameters are
+optional and currently not used.
+
 @end table
 @c end table of parameters
 
@@ -5652,6 +5674,11 @@
 Init to Fatal-Error is triggered by non-recoverable errors in the
 initialization code.
 
+ at item 20
+Error to Error is triggered by errors while already in the Error
+state.
+
+
 @end table
 @end float
 

Modified: trunk/src/cipher-proto.h
===================================================================
--- trunk/src/cipher-proto.h	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/cipher-proto.h	2008-10-02 18:53:31 UTC (rev 1346)
@@ -43,7 +43,10 @@
 typedef gcry_err_code_t (*pk_ext_generate_t)
      (int algo,
       unsigned int nbits,
+      unsigned int qbits,
       unsigned long use_e,
+      const char *name,
+      gcry_sexp_t domain,
       unsigned int keygen_flags, 
       gcry_mpi_t *skey,
       gcry_mpi_t **retfactors);

Modified: trunk/src/cipher.h
===================================================================
--- trunk/src/cipher.h	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/cipher.h	2008-10-02 18:53:31 UTC (rev 1346)
@@ -56,11 +56,6 @@
 
 /*-- dsa.c --*/
 void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data);
-gcry_err_code_t _gcry_dsa_generate2 (int algo, unsigned int nbits,
-                                     unsigned int qbits,
-                                     unsigned long dummy,
-                                     gcry_mpi_t *skey,
-                                     gcry_mpi_t **retfactors);
 
 /*-- elgamal.c --*/
 void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb,

Modified: trunk/src/dumpsexp.c
===================================================================
--- trunk/src/dumpsexp.c	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/dumpsexp.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -263,11 +263,13 @@
 static void 
 printchr (int c)
 {
+  (void)c;
 }
 
 static void
 printhex (int c)
 {
+  (void)c;
 }
 
 

Modified: trunk/src/fips.c
===================================================================
--- trunk/src/fips.c	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/fips.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -730,6 +730,7 @@
       
     case STATE_ERROR:
       if (new_state == STATE_SHUTDOWN
+          || new_state == STATE_ERROR
           || new_state == STATE_FATALERROR
           || new_state == STATE_SELFTEST)
         ok = 1;

Modified: trunk/src/gcrypt-module.h
===================================================================
--- trunk/src/gcrypt-module.h	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/gcrypt-module.h	2008-10-02 18:53:31 UTC (rev 1346)
@@ -32,6 +32,13 @@
 #endif
 #endif
 
+/* The interfaces using the module system reserve a certain range of
+   IDs for application use.  These IDs are not valid within Libgcrypt
+   but Libgcrypt makes sure never to allocate such a module ID.  */
+#define GCRY_MODULE_ID_USER      1024 
+#define GCRY_MODULE_ID_USER_LAST 4095
+
+
 /* This type represents a `module'.  */
 typedef struct gcry_module *gcry_module_t;
 

Modified: trunk/src/gcrypt.h.in
===================================================================
--- trunk/src/gcrypt.h.in	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/gcrypt.h.in	2008-10-02 18:53:31 UTC (rev 1346)
@@ -479,7 +479,7 @@
 size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
                          size_t maxlength);
 
-/* Dumps the S-expression object A in a aformat suitable for debugging
+/* Dumps the S-expression object A in a format suitable for debugging
    to Libgcrypt's logging stream.  */
 void gcry_sexp_dump (const gcry_sexp_t a);
 
@@ -1165,7 +1165,7 @@
                                size_t *nbytes);
 
 /* Map the digest algorithm id ALGO to a string representation of the
-   algorithm name.  For unknown algorithms this functions returns
+   algorithm name.  For unknown algorithms this function returns
    "?". */
 const char *gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
 

Modified: trunk/src/module.c
===================================================================
--- trunk/src/module.c	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/src/module.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -25,8 +25,8 @@
    numbers.  */
 #define MODULE_ID_MIN 600
 #define MODULE_ID_LAST 65500
-#define MODULE_ID_USER 1024
-#define MODULE_ID_USER_LAST 4095
+#define MODULE_ID_USER GCRY_MODULE_ID_USER
+#define MODULE_ID_USER_LAST GCRY_MODULE_ID_USER_LAST
 
 #if MODULE_ID_MIN >= MODULE_ID_USER
 #error Need to implement a different search strategy

Modified: trunk/tests/Makefile.am
===================================================================
--- trunk/tests/Makefile.am	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/tests/Makefile.am	2008-10-02 18:53:31 UTC (rev 1346)
@@ -39,10 +39,6 @@
 LDADD = ../src/libgcrypt.la $(DL_LIBS)
 
 EXTRA_PROGRAMS = testapi pkbench
-noinst_PROGRAMS = $(TESTS) fipsrngdrv
+noinst_PROGRAMS = $(TESTS) fipsdrv
 
-EXTRA_DIST = README rsa-16k.key
-
-# Note: There is a file cavs-driver.pl in the SVN but we do not
-# distribute it because we have no configure tests for Perl and thus
-# we can expect that people get it from the SVN instead.
+EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl

Modified: trunk/tests/benchmark.c
===================================================================
--- trunk/tests/benchmark.c	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/tests/benchmark.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1054,8 +1054,10 @@
       fprintf (stderr, PGM ": version mismatch\n");
       exit (1);
     }
-  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
 
+  if (!gcry_fips_mode_active ())
+    gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+
   if (use_random_daemon)
     gcry_control (GCRYCTL_USE_RANDOM_DAEMON, 1);
 

Modified: trunk/tests/cavs_driver.pl
===================================================================
--- trunk/tests/cavs_driver.pl	2008-09-30 17:58:22 UTC (rev 1345)
+++ trunk/tests/cavs_driver.pl	2008-10-02 18:53:31 UTC (rev 1346)
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 #
-# $Id: cavs_driver.pl 1236 2008-09-17 13:00:06Z smueller $
+# Id: cavs_driver.pl 1236 2008-09-17 13:00:06Z smueller
 #
 # CAVS test driver (based on the OpenSSL driver)
 # Written by: Stephan Müller <sm at atsec.com>
@@ -282,12 +282,87 @@
 ###########################################################
 ###### libgcrypt implementation
 ###########################################################
+sub libgcrypt_encdec($$$$$) {
+	my $key=shift;
+	my $iv=shift;
+	my $cipher=shift;
+	my $enc = (shift) ? "encrypt" : "decrypt";
+	my $data=shift;
+
+	my $program="fipsdrv --no-fips --key $key --iv $iv --algo $cipher $enc";
+
+	return pipe_through_program($data,$program);
+}
+
+
+sub libgcrypt_rsa_sign($$$) {
+	my $data = shift;
+	my $hashalgo = shift;
+	my $keyfile = shift;
+
+	die "ARCFOUR not available for RSA" if $opt{'R'};
+	return pipe_through_program($data,
+                  "fipsdrv --verbose --algo $hashalgo --key $keyfile rsa-sign");
+}
+
+
+sub libgcrypt_rsa_verify($$$$) {
+	my $data = shift;
+	my $cipher = shift;
+	my $keyfile = shift;
+	my $sigfile = shift;
+
+	$data = hex2bin($data);
+	die "ARCFOUR not available for RSA" if $opt{'R'};
+	$data = pipe_through_program($data,
+		"fipsdrv --key $keyfile rsa-verify");
+
+	# Parse through the OpenSSL output information
+	return ($data =~ /OK/);
+}
+
+
+sub libgcrypt_gen_rsakey($$) {
+	my $keylen = shift;
+	my $file = shift;
+
+	die "ARCFOUR not available for RSA" if $opt{'R'};
+	my @args = ("fipsdrv --keysize $keylen rsa-gen > $file");
+        system(@args) == 0
+		or die "system @args failed: $?";
+	die "system @args failed: file $file not created" if (! -f $file);
+}
+
+
+sub libgcrypt_hash($$) {
+	my $pt = shift;
+	my $hashalgo = shift;
+
+        my $program = "fipsdrv --no-fips --algo $hashalgo 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";
+	my $bufsize = shift;
+	my $key = shift;
+	my $iv = shift;
+
+	my $program="fipsdrv --no-fips --binary --key ".bin2hex($key)." --iv ".bin2hex($iv)." --algo '$cipher' --chunk '$bufsize' $enc";
+	return $program;
+}
+
+
 sub libgcrypt_state_rng($$$) {
 	my $key = shift;
 	my $dt = shift;
 	my $v = shift;
 
-	return "fipsrngdrv --binary --loop $key $v $dt";
+	return "fipsdrv --binary --progress --loop --key $key --iv $v --dt $dt random";
 }
 
 sub libgcrypt_hmac($$$$) {
@@ -296,8 +371,8 @@
 	my $msg = shift;
 	my $hashtype = shift;
 
-	die "libgcrypt HMAC test not yet implemented: key $key, maclen $maclen, msg $msg, hashtype $hashtype";
-	
+	my $program = "fipsdrv --no-fips --key $key --algo $hashtype hmac-sha";
+	return pipe_through_program($msg, $program);
 }
 
 ######### End of libgcrypt implementation ################
@@ -941,12 +1016,12 @@
                         $old_calc_data = $calc_data;
 
 			# $calc_data = AES($key, $calc_data);
-			#print STDERR "source_data=", bin2hex($source_data), "\n";
+		        #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";
+		        #print STDERR "len=$len, bufsize=$bufsize\n";
 			die if $len ne $bufsize;
-			#print STDERR "calc_data=", bin2hex($calc_data), "\n";
+		        #print STDERR "calc_data=", bin2hex($calc_data), "\n";
 
 			if ( (!$enc && $ciph =~ /des/) ||
 			     $ciph =~ /rc4/ ) {
@@ -1158,10 +1233,12 @@
 sub usage() {
 
 	print STDERR "Usage:
-$0 [-R] <CAVS-test vector file>
+$0 [-R] [-I name] <CAVS-test vector file>
 
--R  execution of ARCFOUR instead of OpenSSL";
-
+-R       execution of ARCFOUR instead of OpenSSL
+-I NAME  Use interface style NAME:
+            openssl     OpenSSL (default)
+            libgcrypt   Libgcrypt";
 }
 
 # Parser of CAVS test vector file
@@ -1548,22 +1625,32 @@
 
 	usage() unless @ARGV;
 
-	getopts("R", \%opt) or die "bad option";
+	getopts("RI:", \%opt) or die "bad option";
 
 	##### Set library
 
-	#print STDERR "Using OpenSSL interface functions\n";
-	#$encdec =		\&openssl_encdec;
-	#$rsa_sign =		\&openssl_rsa_sign;
-	#$rsa_verify =		\&openssl_rsa_verify;
-	#$gen_rsakey =		\&openssl_gen_rsakey;
-	#$hash =		\&openssl_hash;
-	#$state_cipher =	\&openssl_state_cipher;
+        if ( ! defined $opt{'I'} || $opt{'I'} eq 'openssl' ) {
+	        print STDERR "Using OpenSSL interface functions\n";
+                $encdec =	\&openssl_encdec;
+                $rsa_sign =	\&openssl_rsa_sign;
+                $rsa_verify =	\&openssl_rsa_verify;
+                $gen_rsakey =	\&openssl_gen_rsakey;
+                $hash =		\&openssl_hash;
+                $state_cipher =	\&openssl_state_cipher;
+        } elsif ( $opt{'I'} eq 'libgcrypt' ) {
+                print STDERR "Using libgcrypt interface functions\n";
+                $encdec =	\&libgcrypt_encdec;
+                $rsa_sign =	\&libgcrypt_rsa_sign;
+                $rsa_verify =	\&libgcrypt_rsa_verify;
+                $gen_rsakey =	\&libgcrypt_gen_rsakey;
+                $hash =		\&libgcrypt_hash;
+                $state_cipher =	\&libgcrypt_state_cipher;
+                $state_rng =	\&libgcrypt_state_rng;
+                $hmac =		\&libgcrypt_hmac;
+        } else {
+                die "Invalid interface option given"; 
+        }
 
-	print STDERR "Using libgcrypt interface functions\n";
-	$state_rng =	\&libgcrypt_state_rng;
-	$hmac =		\&libgcrypt_hmac;
-
 	my $infile=$ARGV[0];
 	die "Error: Test vector file $infile not found" if (! -f $infile);
 


Property changes on: trunk/tests/cavs_driver.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/tests/cavs_tests.sh
===================================================================
--- trunk/tests/cavs_tests.sh	                        (rev 0)
+++ trunk/tests/cavs_tests.sh	2008-10-02 18:53:31 UTC (rev 1346)
@@ -0,0 +1,125 @@
+#!/bin/sh
+# Run FIPS CAVS tests
+# Copyright 2008 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
+# modifications, as long as this notice is preserved.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Instructions:
+#
+# 1. Cd to the libgcrypt/tests directory
+#
+# 2. Unpack the test vector tarball into subdirectory named "cavs". 
+#    An example directory layout after unpacking might be:
+#      libgcrypt/tests/cavs/AES/req/CBCGFSbox128.req
+#      libgcrypt/tests/cavs/AES/req/CFB128MCT128.req
+#
+#    Note that below the "cavs" directory there should only be one
+#    directory part named "req".  Further avoid directory part
+#    names "resp".
+#
+# 3. Run this script from the libgcrypt/tests directory:
+#      ./cavs_tests.sh
+#
+# 4. Send the result file cavs/CAVS_results-*.zip to the testing lab.
+#
+
+# Stop script if something unexpected happens.
+set -e
+
+# A global flag to keep track of errors.
+errors_seen_file="$(pwd)/.#cavs_test.errors_seen.tmp"
+[ -f "$errors_seen_file" ] && rm "$errors_seen_file"
+continue_mode=no
+[ "$1" = "--continue" ] && continue_mode=yes
+
+
+# Function to run one test.  
+# The argument is the request file name.
+function run_one_test () {
+    local reqfile="$1"
+    local rspfile
+    local tmprspfile
+    local respdir
+
+    tmprspfile=$(echo "$reqfile" | sed 's,.req$,.rsp,')
+    rspfile=$(echo "$tmprspfile" | sed 's,/req/,/resp/,' )
+    respdir=$(dirname "$rspfile")
+    [ -f "$tmprspfile" ] && rm "$tmprspfile"
+    [ -d "$respdir" ] || mkdir "$respdir"
+    [ -f "$rspfile" ] &&  rm "$rspfile"
+    
+    if ./cavs_driver.pl -I libgcrypt "$reqfile"; then
+        echo "failed test: $reqfile" >&2
+        : >"$errors_seen_file"
+    elif [ -f "$tmprspfile" ]; then
+        mv "$tmprspfile" "$rspfile"
+    else 
+        echo "failed test: $reqfile" >&2
+        : >"$errors_seen_file"
+    fi
+}
+
+
+
+# Save date and system architecure to construct the output archive name
+DATE=$(date +%Y%m%d)
+ARCH=$(arch || echo unknown)
+result_file="CAVS_results-$ARCH-$DATE.zip"
+
+for f in fipsdrv fipsrngdrv cavs_driver.pl; do
+    if [ ! -f "./$f" ]; then
+      echo "required program \"$f\" missing in current directory" >&2
+      exit 2
+    fi
+done
+if [ ! -d cavs ]; then
+    echo "required directory \"cavs\" missing below current directory" >&2
+    exit 2
+fi
+if [ ! zip -h >/dev/null 2>&1 ]; then
+    echo "required program \"zip\" is not installed on this system" >&2
+    exit 2
+fi
+
+# Set the PATH to this directory so that the perl script is able to
+# find the test drivers.
+PATH=.:$PATH
+
+# Check whether there are any stale response files
+find cavs -type f -name "*.rsp" | ( while read f ; do
+    echo "Stale response file: $f" >&2
+    any=yes
+done
+if [ "$any" = "yes" ]; then
+    echo "Stale response files found" >&2
+    if [ "$continue_mode" != "yes" ]; then
+       echo "use option --continue if that is not a problem" >&2
+       exit 1
+    fi
+fi
+) || exit 1
+
+
+# Find all test files and run the tests.
+find cavs -type f -name "*.req" | while read f ; do
+    echo "Running test file $f" >&2
+    run_one_test "$f"
+done
+
+if [ -f "$errors_seen_file" ]; then
+    rm "$errors_seen_file"
+    echo "Error enountered - not packing up response file" >&2
+    exit 1
+fi
+
+echo "Packing up all response files" >&2
+cd cavs
+find . -type f -name "*rsp" -print | zip -@ "$result_file"
+
+echo "Result file is: cavs/$result_file" >&2


Property changes on: trunk/tests/cavs_tests.sh
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/tests/fipsdrv.c
===================================================================
--- trunk/tests/fipsdrv.c	                        (rev 0)
+++ trunk/tests/fipsdrv.c	2008-10-02 18:53:31 UTC (rev 1346)
@@ -0,0 +1,1458 @@
+/* fipsdrv.c  -  A driver to help with FIPS CAVS 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 <errno.h>
+#include <ctype.h>
+#ifndef HAVE_W32_SYSTEM
+# include <signal.h>
+#endif
+#include <assert.h>
+#include <unistd.h>
+
+#include <gcrypt.h>
+
+#define PGM "fipsdrv"
+
+#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)
+
+
+/* Verbose mode flag.  */
+static int verbose;
+
+/* Binary input flag.  */
+static int binary_input;
+
+/* Binary output flag.  */
+static int binary_output;
+
+/* Base64 output flag.  */
+static int base64_output;
+
+/* We need to know whetehr we are in loop_mode.  */
+static int loop_mode;
+
+/* ASN.1 classes.  */
+enum
+{
+  UNIVERSAL = 0,
+  APPLICATION = 1,
+  ASNCONTEXT = 2,
+  PRIVATE = 3
+};
+
+
+/* ASN.1 tags.  */
+enum
+{
+  TAG_NONE = 0,
+  TAG_BOOLEAN = 1,
+  TAG_INTEGER = 2,
+  TAG_BIT_STRING = 3,
+  TAG_OCTET_STRING = 4,
+  TAG_NULL = 5,
+  TAG_OBJECT_ID = 6,
+  TAG_OBJECT_DESCRIPTOR = 7,
+  TAG_EXTERNAL = 8,
+  TAG_REAL = 9,
+  TAG_ENUMERATED = 10,
+  TAG_EMBEDDED_PDV = 11,
+  TAG_UTF8_STRING = 12,
+  TAG_REALTIVE_OID = 13,
+  TAG_SEQUENCE = 16,
+  TAG_SET = 17,
+  TAG_NUMERIC_STRING = 18,
+  TAG_PRINTABLE_STRING = 19,
+  TAG_TELETEX_STRING = 20,
+  TAG_VIDEOTEX_STRING = 21,
+  TAG_IA5_STRING = 22,
+  TAG_UTC_TIME = 23,
+  TAG_GENERALIZED_TIME = 24,
+  TAG_GRAPHIC_STRING = 25,
+  TAG_VISIBLE_STRING = 26,
+  TAG_GENERAL_STRING = 27,
+  TAG_UNIVERSAL_STRING = 28,
+  TAG_CHARACTER_STRING = 29,
+  TAG_BMP_STRING = 30
+};
+
+/* ASN.1 Parser object.  */
+struct tag_info 
+{
+  int class;             /* Object class.  */
+  unsigned long tag;     /* The tag of the object.  */
+  unsigned long length;  /* Length of the values.  */
+  int nhdr;              /* Length of the header (TL).  */
+  unsigned int ndef:1;   /* The object has an indefinite length.  */
+  unsigned int cons:1;   /* This is a constructed object.  */ 
+};
+
+
+
+/* Print a error message and exit the process with an error code.  */
+static void
+die (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  fputs (PGM ": ", stderr);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  exit (1);
+}
+
+
+static void
+showhex (const char *prefix, const void *buffer, size_t length)
+{
+  const unsigned char *p = buffer;
+
+  if (prefix)
+    fprintf (stderr, PGM ": %s: ", prefix);
+  while (length-- )
+    fprintf (stderr, "%02X", *p++);
+  if (prefix)
+    putc ('\n', stderr);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and store that at BUFFER.  BUFFER needs to be of
+   LENGTH bytes.  The function checks that the STRING will convert
+   exactly to LENGTH bytes. The string is delimited by either end of
+   string or a white space character.  The function returns -1 on
+   error or the length of the parsed string.  */
+static int
+hex2bin (const char *string, void *buffer, size_t length)
+{
+  int i;
+  const char *s = string;
+
+  for (i=0; i < length; )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return -1;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[i++] = xtoi_2 (s);
+      s += 2;
+    }
+  if (*s && (!my_isascii (*s) || !isspace (*s)) )
+    return -1;             /* Not followed by Nul or white space.  */
+  if (i != length)
+    return -1;             /* Not of expected length.  */
+  if (*s)
+    s++; /* Skip the delimiter. */
+  return s - string;
+}
+
+
+/* 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 *
+hex2buffer (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))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+/* 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
+   be hex encoded and the decoded content is returned. */
+static void *
+read_file (FILE *fp, int decode, size_t *r_length)
+{
+  char *buffer;
+  size_t buflen;
+  size_t nread, bufsize = 0;
+
+  *r_length = 0;
+#define NCHUNK 8192
+#ifdef HAVE_DOSISH_SYSTEM
+  setmode (fileno(fp), O_BINARY);
+#endif
+  buffer = NULL;
+  buflen = 0;
+  do 
+    {
+      bufsize += NCHUNK;
+      if (!buffer)
+        buffer = gcry_xmalloc (bufsize);
+      else
+        buffer = gcry_xrealloc (buffer, bufsize);
+      
+      nread = fread (buffer + buflen, 1, NCHUNK, fp);
+      if (nread < NCHUNK && ferror (fp))
+        {
+          gcry_free (buffer);
+          return NULL;
+        }
+      buflen += nread;
+    }
+  while (nread == NCHUNK);
+#undef NCHUNK
+  if (decode)
+    {
+      const char *s;
+      char *p;
+
+      for (s=buffer,p=buffer,nread=0; nread+1 < buflen; s += 2, nread +=2 )
+        {
+          if (!hexdigitp (s) || !hexdigitp (s+1))
+            {
+              gcry_free (buffer);
+              return NULL;  /* Invalid hex digits. */
+            }
+          *(unsigned char*)p++ = xtoi_2 (s);
+        }
+      if (nread != buflen)
+        {
+          gcry_free (buffer);
+          return NULL;  /* Odd number of hex digits. */
+        }
+      buflen = p - buffer;
+    }
+
+  *r_length = buflen;
+  return buffer;
+}
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Returns
+   the new length of the buffer.  Dies on error.  */
+static size_t
+base64_decode (char *buffer, size_t length)
+{
+  static unsigned char const asctobin[128] = 
+    {
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+      0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+      0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+      0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+      0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+      0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff 
+    };
+
+  int idx = 0;
+  unsigned char val = 0;
+  int c = 0;
+  char *d, *s;
+  int lfseen = 1;
+
+  /* Find BEGIN line.  */
+  for (s=buffer; length; length--, s++)
+    {
+      if (lfseen && *s == '-' && length > 11 && !memcmp (s, "-----BEGIN ", 11))
+        {
+          for (; length && *s != '\n'; length--, s++)
+            ;
+          break;
+        } 
+      lfseen = (*s == '\n');
+    }
+
+  /* Decode until pad character or END line.  */
+  for (d=buffer; length; length--, s++)
+    {
+      if (lfseen && *s == '-' && length > 9 && !memcmp (s, "-----END ", 9))
+        break;
+      if ((lfseen = (*s == '\n')) || *s == ' ' || *s == '\r' || *s == '\t')
+        continue;
+      if (*s == '=')
+        {
+          /* Pad character: stop */
+          if (idx == 1)
+            *d++ = val;
+          break;
+        }
+
+      if ( (*s & 0x80) || (c = asctobin[*(unsigned char *)s]) == 0xff)
+        die ("invalid base64 character %02X at pos %d detected\n",
+             *(unsigned char*)s, (int)(s-buffer));
+
+      switch (idx)
+        {
+        case 0:
+          val = c << 2;
+          break;
+        case 1:
+          val |= (c>>4)&3;
+          *d++ = val;
+          val = (c<<4)&0xf0;
+          break;
+        case 2:
+          val |= (c>>2)&15;
+          *d++ = val;
+          val = (c<<6)&0xc0;
+          break;
+        case 3:
+          val |= c&0x3f;
+          *d++ = val;
+          break;
+        }
+      idx = (idx+1) % 4;
+    }
+
+  return d - buffer;
+}
+
+
+/* Parse the buffer at the address BUFFER which consists of the number
+   of octets as stored at BUFLEN.  Return the tag and the length part
+   from the TLV triplet.  Update BUFFER and BUFLEN on success.  Checks
+   that the encoded length does not exhaust the length of the provided
+   buffer. */
+static int 
+parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti)
+{
+  int c;
+  unsigned long tag;
+  const unsigned char *buf = *buffer;
+  size_t length = *buflen;
+
+  ti->length = 0;
+  ti->ndef = 0;
+  ti->nhdr = 0;
+
+  /* Get the tag */
+  if (!length)
+    return -1; /* Premature EOF.  */
+  c = *buf++; length--;
+  ti->nhdr++;
+
+  ti->class = (c & 0xc0) >> 6;
+  ti->cons  = !!(c & 0x20);
+  tag       = (c & 0x1f);
+
+  if (tag == 0x1f)
+    {
+      tag = 0;
+      do
+        {
+          tag <<= 7;
+          if (!length)
+            return -1; /* Premature EOF.  */
+          c = *buf++; length--;
+          ti->nhdr++;
+          tag |= (c & 0x7f);
+        }
+      while ( (c & 0x80) );
+    }
+  ti->tag = tag;
+
+  /* Get the length */
+  if (!length)
+    return -1; /* Premature EOF. */
+  c = *buf++; length--;
+  ti->nhdr++;
+
+  if ( !(c & 0x80) )
+    ti->length = c;
+  else if (c == 0x80)
+    ti->ndef = 1;
+  else if (c == 0xff)
+    return -1; /* Forbidden length value.  */
+  else
+    {
+      unsigned long len = 0;
+      int count = c & 0x7f;
+
+      for (; count; count--)
+        {
+          len <<= 8;
+          if (!length)
+            return -1; /* Premature EOF.  */
+          c = *buf++; length--;
+          ti->nhdr++;
+          len |= (c & 0xff);
+        }
+      ti->length = len;
+    }
+  
+  if (ti->class == UNIVERSAL && !ti->tag)
+    ti->length = 0;
+
+  if (ti->length > length)
+    return -1; /* Data larger than buffer.  */
+  
+  *buffer = buf;
+  *buflen = length;
+  return 0;
+}
+
+
+/* Read the file FNAME assuming it is a PEM encoded private key file
+   and return an S-expression.  With SHOW set, the key parameters are
+   printed.  */
+static gcry_sexp_t
+read_key_file (const char *fname, int show)
+{
+  gcry_error_t err;
+  FILE *fp;
+  char *buffer;
+  size_t buflen;
+  const unsigned char *der;
+  size_t derlen;
+  struct tag_info ti;
+  gcry_mpi_t keyparms[8];
+  int idx;
+  gcry_sexp_t s_key;
+
+  fp = fopen (fname, binary_input?"rb":"r");
+  if (!fp)
+    die ("can't open `%s': %s\n", fname, strerror (errno));
+  buffer = read_file (fp, 0, &buflen);
+  if (!buffer)
+    die ("error reading `%s'\n", fname);
+  fclose (fp);
+
+  buflen = base64_decode (buffer, buflen);
+  
+  /* Parse the ASN.1 structure.  */
+  der = (const unsigned char*)buffer;
+  derlen = buflen;
+  if ( parse_tag (&der, &derlen, &ti)
+       || ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef)
+    goto bad_asn1;
+  if ( parse_tag (&der, &derlen, &ti)
+       || ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
+    goto bad_asn1;
+  if (ti.length != 1 || *der)
+    goto bad_asn1;  /* The value of the first integer is no 0. */
+  der += ti.length; derlen += ti.length;
+
+  for (idx=0; idx < DIM(keyparms); idx++)
+    {
+      if ( parse_tag (&der, &derlen, &ti)
+           || ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
+        goto bad_asn1;
+      if (show)
+        {
+          char prefix[2];
+
+          prefix[0] = idx < 8? "nedpq12u"[idx] : '?';
+          prefix[1] = 0;
+          showhex (prefix, der, ti.length);
+        }
+      err = gcry_mpi_scan (keyparms+idx, GCRYMPI_FMT_USG, der, ti.length,NULL);
+      if (err)
+        die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err));
+      der += ti.length; derlen += ti.length;
+    }
+  if (idx != DIM(keyparms))
+    die ("not enough RSA key parameters\n");
+
+  gcry_free (buffer);
+
+  /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
+  /* First check that p < q; if not swap p and q and recompute u.  */ 
+  if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0)
+    {
+      gcry_mpi_swap (keyparms[3], keyparms[4]);
+      gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]);
+    }
+
+  /* Build the S-expression.  */
+  err = gcry_sexp_build (&s_key, NULL,
+                        "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
+                         keyparms[0], keyparms[1], keyparms[2],
+                         keyparms[3], keyparms[4], keyparms[7] );
+  if (err)
+    die ("error building S-expression: %s\n", gpg_strerror (err));
+
+  for (idx=0; idx < DIM(keyparms); idx++)
+    gcry_mpi_release (keyparms[idx]);
+
+  return s_key;
+
+ bad_asn1:
+  die ("invalid ASN.1 structure in `%s'\n", fname);
+  return NULL; /*NOTREACHED*/
+}
+
+
+static void
+print_buffer (const void *buffer, size_t length)
+{
+  int writerr = 0;
+
+  if (base64_output)
+    {
+      static const unsigned char bintoasc[64+1] = 
+        ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
+         "abcdefghijklmnopqrstuvwxyz" 
+         "0123456789+/"); 
+      const unsigned char *p;
+      unsigned char inbuf[4];
+      char outbuf[4];
+      int idx, quads;
+
+      idx = quads = 0;
+      for (p = buffer; length; p++, length--)
+        {
+          inbuf[idx++] = *p;
+          if (idx > 2)
+            {
+              outbuf[0] = bintoasc[(*inbuf>>2)&077];
+              outbuf[1] = bintoasc[(((*inbuf<<4)&060)
+                                    |((inbuf[1] >> 4)&017))&077];
+              outbuf[2] = bintoasc[(((inbuf[1]<<2)&074)
+                                    |((inbuf[2]>>6)&03))&077];
+              outbuf[3] = bintoasc[inbuf[2]&077];
+              if (fwrite (outbuf, 4, 1, stdout) != 1)
+                writerr = 1;
+              idx = 0;
+              if (++quads >= (64/4)) 
+                {
+                  if (fwrite ("\n", 1, 1, stdout) != 1)
+                    writerr = 1;
+                  quads = 0;
+                }
+            }
+        }
+      if (idx)
+        {
+          outbuf[0] = bintoasc[(*inbuf>>2)&077];
+          if (idx == 1)
+            {
+              outbuf[1] = bintoasc[((*inbuf<<4)&060)&077];
+              outbuf[2] = outbuf[3] = '=';
+            }
+          else 
+            { 
+              outbuf[1] = bintoasc[(((*inbuf<<4)&060)
+                                    |((inbuf[1]>>4)&017))&077];
+              outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077];
+              outbuf[3] = '=';
+            }
+          if (fwrite (outbuf, 4, 1, stdout) != 1)
+            writerr = 1;
+          quads++;
+        }
+      if (quads && fwrite ("\n", 1, 1, stdout) != 1)
+        writerr = 1;
+    }
+  else if (binary_output)
+    {
+      if (fwrite (buffer, length, 1, stdout) != 1)
+        writerr++;
+    }
+  else
+    {
+      const unsigned char *p = buffer;
+      
+      while (length-- && !ferror (stdout) )
+        printf ("%02X", *p++);
+      if (ferror (stdout))
+        writerr++;
+    }
+  if (!writerr && fflush (stdout) == EOF)
+    writerr++;
+  if (writerr)
+    {
+#ifndef HAVE_W32_SYSTEM
+      if (loop_mode && errno == EPIPE)
+        loop_mode = 0;
+      else
+#endif
+        die ("writing output failed: %s\n", strerror (errno));
+    }
+}
+
+
+
+static gcry_error_t
+init_external_rng_test (void **r_context, 
+                    unsigned int flags,
+                    const void *key, size_t keylen,
+                    const void *seed, size_t seedlen,
+                    const void *dt, size_t dtlen)
+{
+  return gcry_control (58, 
+                       r_context, flags,
+                       key, keylen,
+                       seed, seedlen,
+                       dt, dtlen);
+}
+
+static gcry_error_t
+run_external_rng_test (void *context, void *buffer, size_t buflen)
+{
+  return gcry_control (59, context, buffer, buflen);
+}
+
+static void
+deinit_external_rng_test (void *context)
+{
+  gcry_control (60, context);
+}
+
+
+/* Given an OpenSSL cipher name NAME, return the Libgcrypt algirithm
+   identified and store the libgcrypt mode at R_MODE.  Returns 0 on
+   error.  */
+static int 
+map_openssl_cipher_name (const char *name, int *r_mode)
+{
+  static struct {
+    const char *name;
+    int algo;
+    int mode;
+  } table[] = 
+    {
+      { "bf-cbc",       GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
+      { "bf",           GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
+      { "bf-cfb",       GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB },
+      { "bf-ecb",       GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB },
+      { "bf-ofb",       GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB },
+
+      { "cast-cbc",     GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
+      { "cast",         GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
+      { "cast5-cbc",    GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
+      { "cast5-cfb",    GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CFB },
+      { "cast5-ecb",    GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_ECB },
+      { "cast5-ofb",    GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_OFB },
+
+      { "des-cbc",      GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC },
+      { "des",          GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC },
+      { "des-cfb",      GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB },
+      { "des-ofb",      GCRY_CIPHER_DES, GCRY_CIPHER_MODE_OFB },
+      { "des-ecb",      GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB },
+
+      { "des-ede3-cbc", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC },
+      { "des-ede3    ", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB },
+      { "des3        ", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC },
+      { "des-ede3-cfb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CFB },
+      { "des-ede3-ofb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_OFB },
+
+      { "rc4",          GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM },
+
+      { "aes-128-cbc",  GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC },
+      { "aes-128",      GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC },
+      { "aes-128-cfb",  GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB },
+      { "aes-128-ecb",  GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB },
+      { "aes-128-ofb",  GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_OFB },
+
+      { "aes-192-cbc",  GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC },
+      { "aes-192",      GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC },
+      { "aes-192-cfb",  GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB },
+      { "aes-192-ecb",  GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB },
+      { "aes-192-ofb",  GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB },
+      
+      { "aes-256-cbc",  GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC },
+      { "aes-256",      GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC },
+      { "aes-256-cfb",  GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB },
+      { "aes-256-ecb",  GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB },
+      { "aes-256-ofb",  GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB },
+
+      { NULL, 0 , 0 }
+    };
+  int idx;
+
+  for (idx=0; table[idx].name; idx++)
+    if (!strcmp (name, table[idx].name))
+      {
+        *r_mode = table[idx].mode;
+        return table[idx].algo;
+      }
+  *r_mode = 0;
+  return 0;
+}
+
+
+
+/* Run an encrypt or decryption operations.  If DATA is NULL the
+   function reads its input in chunks of size DATALEN from fp and
+   processes it and writes it out until EOF.  */
+static void
+run_encrypt_decrypt (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, FILE *fp)
+{
+  gpg_error_t err;
+  gcry_cipher_hd_t hd;
+  void *outbuf;
+  size_t outbuflen;
+  void *inbuf;
+  size_t inbuflen;
+
+  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));
+
+  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));
+
+  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));
+
+  inbuf = data? NULL : gcry_xmalloc (datalen);
+  outbuflen = datalen;
+  outbuf = gcry_xmalloc (outbuflen);
+
+  do
+    {
+      if (inbuf)
+        {
+          int nread = fread (inbuf, 1, datalen, fp);
+          if (nread < (int)datalen && ferror (fp))
+            die ("error reading input\n");
+          data = inbuf;
+          inbuflen = nread;
+        }
+      else
+        inbuflen = datalen;
+
+      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);
+
+  gcry_cipher_close (hd);
+  gcry_free (outbuf);
+  gcry_free (inbuf);
+}
+
+
+
+/* Run a digest operation.  */




More information about the Gnupg-commits mailing list