Add a method to disable the weak key detection.
authorWerner Koch <wk@gnupg.org>
Wed, 5 Nov 2008 17:21:57 +0000 (17:21 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 5 Nov 2008 17:21:57 +0000 (17:21 +0000)
Add a method to return the current input block.
Use this in the FIPS driver.

12 files changed:
NEWS
cipher/ChangeLog
cipher/cipher.c
cipher/des.c
src/ChangeLog
src/cipher-proto.h
src/cipher.h
src/fips.c
src/gcrypt.h.in
src/global.c
tests/ChangeLog
tests/fipsdrv.c

diff --git a/NEWS b/NEWS
index 76dada3..9587a01 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,7 @@ Noteworthy changes in version 1.4.4
 ------------------------------------------------
 
  * Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
 ------------------------------------------------
 
  * Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
-   This functionality is in Libgcrypt since 1.3.0. 
+   This functionality has been in Libgcrypt since 1.3.0. 
 
  * MD5 may now be used in non-enforced fips mode.
 
 
  * MD5 may now be used in non-enforced fips mode.
 
index 6e24cfc..3ec9050 100644 (file)
@@ -1,3 +1,14 @@
+2008-11-05  Werner Koch  <wk@g10code.com>
+
+       * cipher.c (gcry_cipher_handle): Add field EXTRASPEC.
+       (gcry_cipher_open): Set it.
+       (gcry_cipher_ctl): Add private control code to disable weak key
+       detection and to return the current input block.
+       * des.c (_tripledes_ctx): Add field FLAGS.
+       (do_tripledes_set_extra_info): New.
+       (_gcry_cipher_extraspec_tripledes): Add new function.
+       (do_tripledes_setkey): Disable weak key detection.
+
 2008-10-24  Werner Koch  <wk@g10code.com>
 
        * md.c (digest_table): Allow MD5 in fips mode.
 2008-10-24  Werner Koch  <wk@g10code.com>
 
        * md.c (digest_table): Allow MD5 in fips mode.
index 77682ce..2c33ee9 100644 (file)
@@ -161,6 +161,7 @@ struct gcry_cipher_handle
   size_t actual_handle_size;     /* Allocated size of this handle. */
   size_t handle_offset;          /* Offset to the malloced block.  */
   gcry_cipher_spec_t *cipher;
   size_t actual_handle_size;     /* Allocated size of this handle. */
   size_t handle_offset;          /* Offset to the malloced block.  */
   gcry_cipher_spec_t *cipher;
+  cipher_extra_spec_t *extraspec;
   gcry_module_t module;
 
   /* The algorithm id.  This is a hack required because the module
   gcry_module_t module;
 
   /* The algorithm id.  This is a hack required because the module
@@ -669,6 +670,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
 {
   int secure = (flags & GCRY_CIPHER_SECURE);
   gcry_cipher_spec_t *cipher = NULL;
 {
   int secure = (flags & GCRY_CIPHER_SECURE);
   gcry_cipher_spec_t *cipher = NULL;
+  cipher_extra_spec_t *extraspec = NULL;
   gcry_module_t module = NULL;
   gcry_cipher_hd_t h = NULL;
   gcry_err_code_t err = 0;
   gcry_module_t module = NULL;
   gcry_cipher_hd_t h = NULL;
   gcry_err_code_t err = 0;
@@ -694,7 +696,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
          _gcry_module_release (module);
        }
       else
          _gcry_module_release (module);
        }
       else
-       cipher = (gcry_cipher_spec_t *) module->spec;
+        {
+          cipher = (gcry_cipher_spec_t *) module->spec;
+          extraspec = module->extraspec;
+        }
     }
   else
     err = GPG_ERR_CIPHER_ALGO;
     }
   else
     err = GPG_ERR_CIPHER_ALGO;
@@ -731,7 +736,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
        break;
 
       case GCRY_CIPHER_MODE_NONE:
        break;
 
       case GCRY_CIPHER_MODE_NONE:
-        /* This mode may be used for debbuging.  It copies the main
+        /* This mode may be used for debugging.  It copies the main
            text verbatim to the ciphertext.  We do not allow this in
            fips mode or if no debug flag has been set.  */
        if (fips_mode () || !_gcry_get_debug_flag (0))
            text verbatim to the ciphertext.  We do not allow this in
            fips mode or if no debug flag has been set.  */
        if (fips_mode () || !_gcry_get_debug_flag (0))
@@ -783,6 +788,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle,
           h->actual_handle_size = size - off;
           h->handle_offset = off;
          h->cipher = cipher;
           h->actual_handle_size = size - off;
           h->handle_offset = off;
          h->cipher = cipher;
+         h->extraspec = extraspec;
          h->module = module;
           h->algo = algo;
          h->mode = mode;
          h->module = module;
           h->algo = algo;
          h->mode = mode;
@@ -1681,6 +1687,38 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
        rc = GPG_ERR_INV_ARG;
       break;
 
        rc = GPG_ERR_INV_ARG;
       break;
 
+    case 61:  /* Disable weak key detection (private).  */
+      if (h->extraspec->set_extra_info)
+        rc = h->extraspec->set_extra_info 
+          (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
+      else
+        rc = GPG_ERR_NOT_SUPPORTED;
+      break;
+
+    case 62: /* Return current input vector (private).  */
+      /* This is the input block as used in CFB and OFB mode which has
+         initially been set as IV.  The returned format is: 
+           1 byte  Actual length of the block in bytes.
+           n byte  The block.
+         If the provided buffer is too short, an error is returned. */
+      if (buflen < (1 + h->cipher->blocksize))
+        rc = GPG_ERR_TOO_SHORT;
+      else
+        {
+          unsigned char *ivp;
+          unsigned char *dst = buffer;
+          int n = h->unused;
+          
+          if (!n)
+            n = h->cipher->blocksize;
+          gcry_assert (n <= h->cipher->blocksize);
+          *dst++ = n;
+          ivp = h->u_iv.iv + h->cipher->blocksize - n;
+          while (n--)
+            *dst++ = *ivp++;
+        }
+      break;
+
     default:
       rc = GPG_ERR_INV_OP;
     }
     default:
       rc = GPG_ERR_INV_OP;
     }
index 5839df1..f91df77 100644 (file)
@@ -1,5 +1,6 @@
 /* des.c - DES and Triple-DES encryption/decryption Algorithm
 /* des.c - DES and Triple-DES encryption/decryption Algorithm
- * Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2001, 2002, 2003,
+ *               2008  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -152,6 +153,9 @@ typedef struct _tripledes_ctx
   {
     u32 encrypt_subkeys[96];
     u32 decrypt_subkeys[96];
   {
     u32 encrypt_subkeys[96];
     u32 decrypt_subkeys[96];
+    struct {
+      int no_weak_key;
+    } flags;
   }
 tripledes_ctx[1];
 
   }
 tripledes_ctx[1];
 
@@ -1013,7 +1017,9 @@ do_tripledes_setkey ( void *context, const byte *key, unsigned keylen )
 
   tripledes_set3keys ( ctx, key, key+8, key+16);
 
 
   tripledes_set3keys ( ctx, key, key+8, key+16);
 
-  if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
+  if (ctx->flags.no_weak_key)
+    ; /* Detection has been disabled.  */
+  else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16))
     {
       _gcry_burn_stack (64);
       return GPG_ERR_WEAK_KEY;
     {
       _gcry_burn_stack (64);
       return GPG_ERR_WEAK_KEY;
@@ -1024,6 +1030,30 @@ do_tripledes_setkey ( void *context, const byte *key, unsigned keylen )
 }
 
 
 }
 
 
+static gcry_err_code_t
+do_tripledes_set_extra_info (void *context, int what,
+                             const void *buffer, size_t buflen)
+{
+  struct _tripledes_ctx *ctx = (struct _tripledes_ctx *)context;
+  gpg_err_code_t ec = 0;
+
+  (void)buffer;
+  (void)buflen;
+
+  switch (what)
+    {
+    case CIPHER_INFO_NO_WEAK_KEY:
+      ctx->flags.no_weak_key = 1;
+      break;
+
+    default:
+      ec = GPG_ERR_INV_OP; 
+      break;
+    }
+  return ec;
+}
+
+
 static void
 do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf )
 {
 static void
 do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf )
 {
@@ -1161,5 +1191,6 @@ gcry_cipher_spec_t _gcry_cipher_spec_tripledes =
 
 cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = 
   {
 
 cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = 
   {
-    run_selftests
+    run_selftests,
+    do_tripledes_set_extra_info
   };
   };
index 86fd72d..c255fda 100644 (file)
@@ -1,3 +1,10 @@
+2008-11-05  Werner Koch  <wk@g10code.com>
+
+       * cipher.h (CIPHER_INFO_NO_WEAK_KEY): New.
+
+       * cipher-proto.h (cipher_set_extra_info_t): New.
+       (cipher_extra_spec): Add field SET_EXTRA_INFO.
+
 2008-10-30  Werner Koch  <wk@g10code.com>
 
        * g10lib.h (GCC_ATTR_FORMAT_ARG): New.
 2008-10-30  Werner Koch  <wk@g10code.com>
 
        * g10lib.h (GCC_ATTR_FORMAT_ARG): New.
index 43ed088..975a2a1 100644 (file)
@@ -55,6 +55,10 @@ typedef gcry_err_code_t (*pk_ext_generate_t)
 typedef gpg_err_code_t (*pk_comp_keygrip_t)
      (gcry_md_hd_t md, gcry_sexp_t keyparm);
 
 typedef gpg_err_code_t (*pk_comp_keygrip_t)
      (gcry_md_hd_t md, gcry_sexp_t keyparm);
 
+/* The type used to convey additional information to a cipher.  */
+typedef gpg_err_code_t (*cipher_set_extra_info_t)
+     (void *c, int what, const void *buffer, size_t buflen);
+
 
 /* Extra module specification structures.  These are used for internal
    modules which provide more functions than available through the
 
 /* Extra module specification structures.  These are used for internal
    modules which provide more functions than available through the
@@ -62,6 +66,7 @@ typedef gpg_err_code_t (*pk_comp_keygrip_t)
 typedef struct cipher_extra_spec
 {
   selftest_func_t selftest;
 typedef struct cipher_extra_spec
 {
   selftest_func_t selftest;
+  cipher_set_extra_info_t set_extra_info;
 } cipher_extra_spec_t;
 
 typedef struct md_extra_spec
 } cipher_extra_spec_t;
 
 typedef struct md_extra_spec
index 3e0ba9d..f84d9ad 100644 (file)
@@ -29,6 +29,8 @@
 #define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
 #define PUBKEY_FLAG_TRANSIENT_KEY  (1 << 1)
 
 #define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
 #define PUBKEY_FLAG_TRANSIENT_KEY  (1 << 1)
 
+#define CIPHER_INFO_NO_WEAK_KEY    1
+
 #include "cipher-proto.h"
 
 
 #include "cipher-proto.h"
 
 
index f2d898b..6e0c9ec 100644 (file)
@@ -262,8 +262,8 @@ unlock_fsm (void)
 int
 _gcry_fips_mode (void)
 {
 int
 _gcry_fips_mode (void)
 {
-  /* No locking is required becuase we have the requirement that this
-     variable is only intialized once with no other threads
+  /* No locking is required because we have the requirement that this
+     variable is only initialized once with no other threads
      existing.  */
   return !no_fips_mode_required;
 }
      existing.  */
   return !no_fips_mode_required;
 }
index ae34d10..864a300 100644 (file)
@@ -410,7 +410,7 @@ enum gcry_ctl_cmds
     GCRYCTL_FIPS_MODE_P = 55,
     GCRYCTL_FORCE_FIPS_MODE = 56,
     GCRYCTL_SELFTEST = 57
     GCRYCTL_FIPS_MODE_P = 55,
     GCRYCTL_FORCE_FIPS_MODE = 56,
     GCRYCTL_SELFTEST = 57
-    /* Note: 58, 59 and 60 are used internally.  */
+    /* Note: 58 .. 62 are used internally.  */
   };
 
 /* Perform various operations defined by CMD. */
   };
 
 /* Perform various operations defined by CMD. */
index 3177a02..d2361de 100644 (file)
@@ -529,7 +529,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       err = _gcry_fips_run_selftests (1);
       break;
 
       err = _gcry_fips_run_selftests (1);
       break;
 
-    case 58:
+    case 58:  /* Init external random test.  */
       {
         void **rctx        = va_arg (arg_ptr, void **);
         unsigned int flags = va_arg (arg_ptr, unsigned int);
       {
         void **rctx        = va_arg (arg_ptr, void **);
         unsigned int flags = va_arg (arg_ptr, unsigned int);
@@ -546,7 +546,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
                                                  seed, seedlen, dt, dtlen);
       }
       break;
                                                  seed, seedlen, dt, dtlen);
       }
       break;
-    case 59:
+    case 59:  /* Run external random test.  */
       {
         void *ctx     = va_arg (arg_ptr, void *);
         void *buffer  = va_arg (arg_ptr, void *);
       {
         void *ctx     = va_arg (arg_ptr, void *);
         void *buffer  = va_arg (arg_ptr, void *);
@@ -557,7 +557,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
           err = _gcry_random_run_external_test (ctx, buffer, buflen);
       }
       break;
           err = _gcry_random_run_external_test (ctx, buffer, buflen);
       }
       break;
-    case 60:
+    case 60:  /* Deinit external random test.  */
       {
         void *ctx = va_arg (arg_ptr, void *);
         _gcry_random_deinit_external_test (ctx);
       {
         void *ctx = va_arg (arg_ptr, void *);
         _gcry_random_deinit_external_test (ctx);
index d0198cd..c438778 100644 (file)
@@ -1,3 +1,7 @@
+2008-11-05  Werner Koch  <wk@g10code.com>
+
+       * fipsdrv.c (run_encrypt_decrypt): Disable weak key detection.
+
 2008-10-31  Werner Koch  <wk@g10code.com>
 
        * fipsdrv.c (run_rsa_sign): Buffer needs to be larger for SHA512.
 2008-10-31  Werner Koch  <wk@g10code.com>
 
        * fipsdrv.c (run_rsa_sign): Buffer needs to be larger for SHA512.
index 6d83aaf..fdffdbb 100644 (file)
 #define DIMof(type,member)   DIM(((type *)0)->member)
 
 
 #define DIMof(type,member)   DIM(((type *)0)->member)
 
 
+#define PRIV_CTL_INIT_EXTRNG_TEST   58
+#define PRIV_CTL_RUN_EXTRNG_TEST    59
+#define PRIV_CTL_DEINIT_EXTRNG_TEST 60
+#define PRIV_CTL_DISABLE_WEAK_KEY   61
+#define PRIV_CTL_GET_INPUT_VECTOR   62
+
+
 /* Verbose mode flag.  */
 static int verbose;
 
 /* Verbose mode flag.  */
 static int verbose;
 
@@ -63,6 +70,10 @@ static int base64_output;
 /* We need to know whetehr we are in loop_mode.  */
 static int loop_mode;
 
 /* 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
 {
 /* ASN.1 classes.  */
 enum
 {
@@ -747,7 +758,7 @@ init_external_rng_test (void **r_context,
                     const void *seed, size_t seedlen,
                     const void *dt, size_t dtlen)
 {
                     const void *seed, size_t seedlen,
                     const void *dt, size_t dtlen)
 {
-  return gcry_control (58
+  return gcry_control (PRIV_CTL_INIT_EXTRNG_TEST
                        r_context, flags,
                        key, keylen,
                        seed, seedlen,
                        r_context, flags,
                        key, keylen,
                        seed, seedlen,
@@ -757,13 +768,13 @@ init_external_rng_test (void **r_context,
 static gcry_error_t
 run_external_rng_test (void *context, void *buffer, size_t buflen)
 {
 static gcry_error_t
 run_external_rng_test (void *context, void *buffer, size_t buflen)
 {
-  return gcry_control (59, context, buffer, buflen);
+  return gcry_control (PRIV_CTL_RUN_EXTRNG_TEST, context, buffer, buflen);
 }
 
 static void
 deinit_external_rng_test (void *context)
 {
 }
 
 static void
 deinit_external_rng_test (void *context)
 {
-  gcry_control (60, context);
+  gcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context);
 }
 
 
 }
 
 
@@ -856,12 +867,18 @@ run_encrypt_decrypt (int encrypt_mode,
   size_t outbuflen;
   void *inbuf;
   size_t inbuflen;
   size_t outbuflen;
   void *inbuf;
   size_t inbuflen;
+  size_t blocklen;
 
   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_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);
+  assert (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",
   err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
   if (err)
     die ("gcry_cipher_setkey failed with keylen %u: %s\n",
@@ -877,7 +894,7 @@ run_encrypt_decrypt (int encrypt_mode,
 
   inbuf = data? NULL : gcry_xmalloc (datalen);
   outbuflen = datalen;
 
   inbuf = data? NULL : gcry_xmalloc (datalen);
   outbuflen = datalen;
-  outbuf = gcry_xmalloc (outbuflen);
+  outbuf = gcry_xmalloc (outbuflen < blocklen? blocklen:outbuflen);
 
   do
     {
 
   do
     {
@@ -892,14 +909,52 @@ run_encrypt_decrypt (int encrypt_mode,
       else
         inbuflen = datalen;
 
       else
         inbuflen = datalen;
 
-      if (encrypt_mode)
-        err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
+      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, 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');
+
+              iptr += ilen;
+              inbuflen -= ilen;
+             }
+          while (inbuflen);
+        }
       else
       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);
+        {
+          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);
 
     }
   while (inbuf);
 
@@ -1301,20 +1356,21 @@ usage (int show_help)
      "MODE:\n"
      "  encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify}\n"
      "OPTIONS:\n"
      "MODE:\n"
      "  encrypt, decrypt, digest, random, hmac-sha, rsa-{gen,sign,verify}\n"
      "OPTIONS:\n"
-     "  --verbose        print additional information\n"
-     "  --binary         input and output is in binary form\n"
-     "  --no-fips        do not force FIPS mode\n"
-     "  --key KEY        use the hex encoded KEY\n"
-     "  --iv IV          use the hex encoded IV\n"
-     "  --dt DT          use the hex encoded DT for the RNG\n"
-     "  --algo NAME      use algorithm NAME\n"
-     "  --keysize N      use a keysize of N bits\n"
-     "  --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"
-     "  --loop           enable random loop mode\n"
-     "  --progress       print pogress indicators\n"
-     "  --help           print this text\n"
+     "  --verbose        Print additional information\n"
+     "  --binary         Input and output is in binary form\n"
+     "  --no-fips        Do not force FIPS mode\n"
+     "  --key KEY        Use the hex encoded KEY\n"
+     "  --iv IV          Use the hex encoded IV\n"
+     "  --dt DT          Use the hex encoded DT for the RNG\n"
+     "  --algo NAME      Use algorithm NAME\n"
+     "  --keysize N      Use a keysize of N bits\n"
+     "  --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"
+     "  --loop           Enable random loop mode\n"
+     "  --progress       Print pogress indicators\n"
+     "  --help           Print this text\n"
      "With no FILE, or when FILE is -, read standard input.\n"
      "Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
   exit (0);
      "With no FILE, or when FILE is -, read standard input.\n"
      "Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
   exit (0);
@@ -1448,6 +1504,11 @@ main (int argc, char **argv)
           use_pkcs1 = 1;
           argc--; argv++;
         }
           use_pkcs1 = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--print-ivs"))
+        {
+          print_ivs = 1;
+          argc--; argv++;
+        }
     }          
 
   if (!argc || argc > 2)
     }          
 
   if (!argc || argc > 2)