api: New function gcry_get_config.
[libgcrypt.git] / tests / fipsdrv.c
index 29ceedd..f9d9c45 100644 (file)
@@ -2,17 +2,17 @@
    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/>.
  */
 #include <assert.h>
 #include <unistd.h>
 
-#ifdef _GCRYPT_IN_LIBGCRYPT
-# include "../src/gcrypt.h"
-#else
+#ifndef _GCRYPT_IN_LIBGCRYPT
 # include <gcrypt.h>
 # define PACKAGE_BUGREPORT "devnull@example.org"
 # define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]"
 #endif
-
+#include "../src/gcrypt-testapi.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)
+#include "t-common.h"
 
 
-#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;
-
 /* Binary input flag.  */
 static int binary_input;
 
@@ -129,32 +107,17 @@ enum
 };
 
 /* ASN.1 Parser object.  */
-struct tag_info 
+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.  */ 
+  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)
 {
@@ -249,7 +212,7 @@ read_textline (FILE *fp)
   /* Read line but skip over initial empty lines.  */
   do
     {
-      do 
+      do
         {
           if (!fgets (line, sizeof line, fp))
             {
@@ -330,14 +293,14 @@ read_file (FILE *fp, int decode, size_t *r_length)
 #endif
   buffer = NULL;
   buflen = 0;
-  do 
+  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))
         {
@@ -379,7 +342,7 @@ read_file (FILE *fp, int decode, size_t *r_length)
 static size_t
 base64_decode (char *buffer, size_t length)
 {
-  static unsigned char const asctobin[128] = 
+  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,
@@ -391,7 +354,7 @@ base64_decode (char *buffer, size_t length)
       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 
+      0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
     };
 
   int idx = 0;
@@ -408,7 +371,7 @@ base64_decode (char *buffer, size_t length)
           for (; length && *s != '\n'; length--, s++)
             ;
           break;
-        } 
+        }
       lfseen = (*s == '\n');
     }
 
@@ -463,7 +426,7 @@ base64_decode (char *buffer, size_t length)
    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 
+static int
 parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti)
 {
   int c;
@@ -529,13 +492,13 @@ parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti)
         }
       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;
@@ -569,7 +532,7 @@ read_private_key_file (const char *fname, int show)
   fclose (fp);
 
   buflen = base64_decode (buffer, buflen);
-  
+
   /* Parse the ASN.1 structure.  */
   der = (const unsigned char*)buffer;
   derlen = buflen;
@@ -607,13 +570,13 @@ read_private_key_file (const char *fname, int show)
   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.  */ 
+  /* 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)"
@@ -622,12 +585,12 @@ read_private_key_file (const char *fname, int show)
                          keyparms[3], keyparms[4], keyparms[7] );
   if (err)
     die ("error building S-expression: %s\n", gpg_strerror (err));
-  
+
   for (idx=0; idx < n_keyparms; idx++)
     gcry_mpi_release (keyparms[idx]);
-  
+
   return s_key;
-  
+
  bad_asn1:
   die ("invalid ASN.1 structure in `%s'\n", fname);
   return NULL; /*NOTREACHED*/
@@ -661,7 +624,7 @@ read_public_key_file (const char *fname, int show)
   fclose (fp);
 
   buflen = base64_decode (buffer, buflen);
-  
+
   /* Parse the ASN.1 structure.  */
   der = (const unsigned char*)buffer;
   derlen = buflen;
@@ -673,7 +636,7 @@ read_public_key_file (const char *fname, int show)
     goto bad_asn1;
   /* We skip the description of the key parameters and assume it is RSA.  */
   der += ti.length; derlen -= ti.length;
-  
+
   if ( parse_tag (&der, &derlen, &ti)
        || ti.tag != TAG_BIT_STRING || ti.class || ti.cons || ti.ndef)
     goto bad_asn1;
@@ -715,12 +678,12 @@ read_public_key_file (const char *fname, int show)
                          keyparms[0], keyparms[1] );
   if (err)
     die ("error building S-expression: %s\n", gpg_strerror (err));
-  
+
   for (idx=0; idx < n_keyparms; idx++)
     gcry_mpi_release (keyparms[idx]);
-  
+
   return s_key;
-  
+
  bad_asn1:
   die ("invalid ASN.1 structure in `%s'\n", fname);
   return NULL; /*NOTREACHED*/
@@ -796,10 +759,10 @@ print_buffer (const void *buffer, size_t length)
 
   if (base64_output)
     {
-      static const unsigned char bintoasc[64+1] = 
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
-        "abcdefghijklmnopqrstuvwxyz" 
-        "0123456789+/"; 
+      static const unsigned char bintoasc[64+1] =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+        "abcdefghijklmnopqrstuvwxyz"
+        "0123456789+/";
       const unsigned char *p;
       unsigned char inbuf[4];
       char outbuf[4];
@@ -820,7 +783,7 @@ print_buffer (const void *buffer, size_t length)
               if (fwrite (outbuf, 4, 1, stdout) != 1)
                 writerr = 1;
               idx = 0;
-              if (++quads >= (64/4)) 
+              if (++quads >= (64/4))
                 {
                   if (fwrite ("\n", 1, 1, stdout) != 1)
                     writerr = 1;
@@ -836,8 +799,8 @@ print_buffer (const void *buffer, size_t length)
               outbuf[1] = bintoasc[((*inbuf<<4)&060)&077];
               outbuf[2] = outbuf[3] = '=';
             }
-          else 
-            { 
+          else
+            {
               outbuf[1] = bintoasc[(((*inbuf<<4)&060)
                                     |((inbuf[1]>>4)&017))&077];
               outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077];
@@ -858,7 +821,7 @@ print_buffer (const void *buffer, size_t length)
   else
     {
       const unsigned char *p = buffer;
-      
+
       if (verbose > 1)
         showhex ("sent line", buffer, length);
       while (length-- && !ferror (stdout) )
@@ -895,7 +858,7 @@ print_mpi_line (gcry_mpi_t a, int no_lz)
   p = buf;
   if (no_lz && p[0] == '0' && p[1] == '0' && p[2])
     p += 2;
-    
+
   printf ("%s\n", p);
   if (ferror (stdout))
     writerr++;
@@ -913,7 +876,7 @@ print_data_line (const void *data, size_t datalen)
 {
   const unsigned char *p = data;
   int writerr = 0;
-      
+
   while (data && datalen-- && !ferror (stdout) )
     printf ("%02X", *p++);
   putchar ('\n');
@@ -944,13 +907,13 @@ print_sexp (gcry_sexp_t a, FILE *fp)
 
 
 static gcry_error_t
-init_external_rng_test (void **r_context, 
+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 (PRIV_CTL_INIT_EXTRNG_TEST, 
+  return gcry_control (PRIV_CTL_INIT_EXTRNG_TEST,
                        r_context, flags,
                        key, keylen,
                        seed, seedlen,
@@ -966,21 +929,21 @@ run_external_rng_test (void *context, void *buffer, size_t buflen)
 static void
 deinit_external_rng_test (void *context)
 {
-  gcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context);
+  xgcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, 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 
+static int
 map_openssl_cipher_name (const char *name, int *r_mode)
 {
   static struct {
     const char *name;
     int algo;
     int mode;
-  } table[] = 
+  } table[] =
     {
       { "bf-cbc",       GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
       { "bf",           GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
@@ -1020,7 +983,7 @@ map_openssl_cipher_name (const char *name, int *r_mode)
       { "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 },
@@ -1048,7 +1011,7 @@ map_openssl_cipher_name (const char *name, int *r_mode)
    processes it and writes it out until EOF.  */
 static void
 run_encrypt_decrypt (int encrypt_mode,
-                     int cipher_algo, int cipher_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)
@@ -1063,13 +1026,13 @@ run_encrypt_decrypt (int encrypt_mode,
 
   err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0);
   if (err)
-    die ("gcry_cipher_open failed for algo %d, mode %d: %s\n", 
+    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);
+  gcry_cipher_ctl (hd, PRIV_CIPHERCTL_DISABLE_WEAK_KEY, NULL, 0);
 
   err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
   if (err)
@@ -1108,7 +1071,7 @@ run_encrypt_decrypt (int encrypt_mode,
       if (err)
         die ("gcry_cipher_%scrypt failed: %s\n",
              encrypt_mode? "en":"de", gpg_strerror (err));
-      
+
       print_buffer (outbuf, outbuflen);
     }
   while (inbuf);
@@ -1124,7 +1087,7 @@ 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))
+  if (gcry_cipher_ctl (hd, PRIV_CIPHERCTL_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");
@@ -1133,7 +1096,7 @@ get_current_iv (gcry_cipher_hd_t hd, void *buffer, size_t buflen)
 
 /* 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, 
+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)
@@ -1146,20 +1109,20 @@ run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode,
   char output[16];
   char last_output[16];
   char last_last_output[16];
-  char last_iv[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", 
+    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);
+    die ("invalid block length %d\n", (int)blocklen);
 
 
-  gcry_cipher_ctl (hd, PRIV_CTL_DISABLE_WEAK_KEY, NULL, 0);
+  gcry_cipher_ctl (hd, PRIV_CIPHERCTL_DISABLE_WEAK_KEY, NULL, 0);
 
   err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
   if (err)
@@ -1175,7 +1138,7 @@ run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode,
     }
 
   if (datalen != blocklen)
-    die ("length of input (%u) does not match block length (%u)\n", 
+    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);
@@ -1194,7 +1157,7 @@ run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode,
         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);
@@ -1243,7 +1206,7 @@ run_digest (int digest_algo,  const void *data, size_t datalen)
 
   err = gcry_md_open (&hd, digest_algo, 0);
   if (err)
-    die ("gcry_md_open failed for algo %d: %s\n", 
+    die ("gcry_md_open failed for algo %d: %s\n",
          digest_algo,  gpg_strerror (err));
 
   gcry_md_write (hd, data, datalen);
@@ -1256,7 +1219,7 @@ run_digest (int digest_algo,  const void *data, size_t datalen)
 \f
 /* Run a HMAC operation.  */
 static void
-run_hmac (int digest_algo, const void *key, size_t keylen, 
+run_hmac (int digest_algo, const void *key, size_t keylen,
           const void *data, size_t datalen)
 {
   gpg_error_t err;
@@ -1266,12 +1229,12 @@ run_hmac (int digest_algo, const void *key, size_t keylen,
 
   err = gcry_md_open (&hd, digest_algo, GCRY_MD_FLAG_HMAC);
   if (err)
-    die ("gcry_md_open failed for HMAC algo %d: %s\n", 
+    die ("gcry_md_open failed for HMAC algo %d: %s\n",
          digest_algo,  gpg_strerror (err));
 
   gcry_md_setkey (hd, key, keylen);
   if (err)
-    die ("gcry_md_setkey failed for HMAC algo %d: %s\n", 
+    die ("gcry_md_setkey failed for HMAC algo %d: %s\n",
          digest_algo,  gpg_strerror (err));
 
   gcry_md_write (hd, data, datalen);
@@ -1346,10 +1309,73 @@ run_rsa_derive (const void *data, size_t datalen)
 }
 
 
+/* Generate RSA key using the S-expression in (DATA,DATALEN).  This
+   S-expression is used directly as input to gcry_pk_genkey.  The
+   result is printed to stdout with one parameter per line in hex
+   format and in this order: e, p, q, n, d.  */
+static void
+run_rsa_keygen (const void *data, size_t datalen, int test)
+{
+  gpg_error_t err;
+  gcry_sexp_t s_keyspec, s_key, s_top, l1;
+  gcry_mpi_t mpi;
+  const char *parmlist;
+  int idx;
+
+  if (!datalen)
+    err = gpg_error (GPG_ERR_NO_DATA);
+  else
+    err = gcry_sexp_new (&s_keyspec, data, datalen, 1);
+  if (err)
+    die ("gcry_sexp_new failed for RSA key generation: %s\n",
+         gpg_strerror (err));
+
+  err = gcry_pk_genkey (&s_key, s_keyspec);
+
+  gcry_sexp_release (s_keyspec);
+
+  if (test) {
+       if (err)
+               printf("F\n");
+       else {
+               gcry_sexp_release (s_key);
+               printf("P\n");
+       }
+       return;
+  }
+
+  if (err)
+    die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
+
+  parmlist = "epqnd";
+
+  /* Parse and print the parameters.  */
+  l1 = gcry_sexp_find_token (s_key, "private-key", 0);
+  s_top = gcry_sexp_find_token (l1, "rsa", 0);
+  gcry_sexp_release (l1);
+  if (!s_top)
+    die ("private-key part not found in result\n");
+
+  for (idx=0; parmlist[idx]; idx++)
+    {
+      l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1);
+      mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+      gcry_sexp_release (l1);
+      if (!mpi)
+        die ("parameter %c missing in private-key\n", parmlist[idx]);
+      print_mpi_line (mpi, 1);
+      gcry_mpi_release (mpi);
+    }
+
+  gcry_sexp_release (s_top);
+  gcry_sexp_release (s_key);
+}
+
+
 \f
 static size_t
 compute_tag_length (size_t n)
-{     
+{
   int needed = 0;
 
   if (n < 128)
@@ -1366,7 +1392,7 @@ compute_tag_length (size_t n)
 
 static unsigned char *
 store_tag_length (unsigned char *p, int tag, size_t n)
-{     
+{
   if (tag == TAG_SEQUENCE)
     tag |= 0x20; /* constructed */
 
@@ -1394,11 +1420,11 @@ store_tag_length (unsigned char *p, int tag, size_t n)
    is:
 
        SEQUENCE {
-         INTEGER (0)  -- Unknown constant. 
+         INTEGER (0)  -- Unknown constant.
          INTEGER      -- n
          INTEGER      -- e
          INTEGER      -- d
-         INTEGER      -- p     
+         INTEGER      -- p
          INTEGER      -- q      (with p < q)
          INTEGER      -- dmp1 = d mod (p-1)
          INTEGER      -- dmq1 = d mod (q-1)
@@ -1418,7 +1444,7 @@ run_rsa_gen (int keysize, int pubexp)
   size_t derlen, needed, n;
   unsigned char *derbuf, *der;
 
-  err = gcry_sexp_build (&keyspec, NULL, 
+  err = gcry_sexp_build (&keyspec, NULL,
                          "(genkey (rsa (nbits %d)(rsa-use-e %d)))",
                          keysize, pubexp);
   if (err)
@@ -1428,7 +1454,7 @@ run_rsa_gen (int keysize, int pubexp)
   err = gcry_pk_genkey (&key, keyspec);
   if (err)
     die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
-  
+
   gcry_sexp_release (keyspec);
 
   l1 = gcry_sexp_find_token (key, "private-key", 0);
@@ -1445,7 +1471,7 @@ run_rsa_gen (int keysize, int pubexp)
 
   /* Extract the parameters from the S-expression and store them in a
      well defined order in KEYPARMS.  */
-  for (idx=0; idx < DIM(keyparms); idx++) 
+  for (idx=0; idx < DIM(keyparms); idx++)
     {
       if (keyelems[idx] == '.')
         {
@@ -1464,7 +1490,7 @@ run_rsa_gen (int keysize, int pubexp)
 
   gcry_sexp_release (key);
 
-  /* Check that p < q; if not swap p and q and recompute u.  */ 
+  /* 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]);
@@ -1478,8 +1504,8 @@ run_rsa_gen (int keysize, int pubexp)
   gcry_mpi_mod (keyparms[6], keyparms[2], keyparms[6]);
 
   /* Compute the length of the DER encoding.  */
-  needed = compute_tag_length (1) + 1;  
-  for (idx=0; idx < DIM(keyparms); idx++) 
+  needed = compute_tag_length (1) + 1;
+  for (idx=0; idx < DIM(keyparms); idx++)
     {
       err = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, keyparms[idx]);
       if (err)
@@ -1487,7 +1513,7 @@ run_rsa_gen (int keysize, int pubexp)
       keyparmslen[idx] = n;
       needed += compute_tag_length (n) + n;
     }
-  
+
   /* Store the key parameters. */
   derlen = compute_tag_length (needed) + needed;
   der = derbuf = gcry_xmalloc (derlen);
@@ -1495,10 +1521,10 @@ run_rsa_gen (int keysize, int pubexp)
   der = store_tag_length (der, TAG_SEQUENCE, needed);
   der = store_tag_length (der, TAG_INTEGER, 1);
   *der++ = 0;
-  for (idx=0; idx < DIM(keyparms); idx++) 
+  for (idx=0; idx < DIM(keyparms); idx++)
     {
       der = store_tag_length (der, TAG_INTEGER, keyparmslen[idx]);
-      err = gcry_mpi_print (GCRYMPI_FMT_STD, der, 
+      err = gcry_mpi_print (GCRYMPI_FMT_STD, der,
                            keyparmslen[idx], NULL, keyparms[idx]);
       if (err)
         die ("error formatting parameter: %s\n", gpg_strerror (err));
@@ -1506,7 +1532,7 @@ run_rsa_gen (int keysize, int pubexp)
     }
 
   /* Print the stuff.  */
-  for (idx=0; idx < DIM(keyparms); idx++) 
+  for (idx=0; idx < DIM(keyparms); idx++)
     gcry_mpi_release (keyparms[idx]);
 
   assert (der - derbuf == derlen);
@@ -1526,7 +1552,7 @@ run_rsa_gen (int keysize, int pubexp)
    encoded KEYFILE and the hash algorithm HASHALGO.  */
 static void
 run_rsa_sign (const void *data, size_t datalen,
-              int hashalgo, int pkcs1, const char *keyfile)
+              int hashalgo, int pkcs1, int pss, const char *keyfile)
 
 {
   gpg_error_t err;
@@ -1534,7 +1560,7 @@ run_rsa_sign (const void *data, size_t datalen,
   gcry_mpi_t sig_mpi = NULL;
   unsigned char *outbuf;
   size_t outlen;
-  
+
 /*   showhex ("D", data, datalen); */
   if (pkcs1)
     {
@@ -1550,6 +1576,20 @@ run_rsa_sign (const void *data, size_t datalen,
                              gcry_md_algo_name (hashalgo),
                              (int)hashsize, hash);
     }
+  else if (pss)
+    {
+      unsigned char hash[64];
+      unsigned int hashsize;
+
+      hashsize = gcry_md_get_algo_dlen (hashalgo);
+      if (!hashsize || hashsize > sizeof hash)
+        die ("digest too long for buffer or unknown hash algorithm\n");
+      gcry_md_hash_buffer (hashalgo, hash, data, datalen);
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags pss)(salt-length #00#)(hash %s %b))",
+                             gcry_md_algo_name (hashalgo),
+                             (int)hashsize, hash);
+    }
   else
     {
       gcry_mpi_t tmp;
@@ -1598,7 +1638,7 @@ run_rsa_sign (const void *data, size_t datalen,
         }
     }
   gcry_sexp_release (s_sig);
-              
+
   if (!sig_mpi)
     die ("no value in returned S-expression\n");
   err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &outbuf, &outlen, sig_mpi);
@@ -1617,12 +1657,12 @@ run_rsa_sign (const void *data, size_t datalen,
    binary signature in SIGFILE.  */
 static void
 run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1,
-                const char *keyfile, const char *sigfile)
+                int pss, const char *keyfile, const char *sigfile)
 
 {
   gpg_error_t err;
   gcry_sexp_t s_data, s_key, s_sig;
-  
+
   if (pkcs1)
     {
       unsigned char hash[64];
@@ -1637,6 +1677,20 @@ run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1,
                              gcry_md_algo_name (hashalgo),
                              (int)hashsize, hash);
     }
+  else if (pss)
+    {
+      unsigned char hash[64];
+      unsigned int hashsize;
+
+      hashsize = gcry_md_get_algo_dlen (hashalgo);
+      if (!hashsize || hashsize > sizeof hash)
+        die ("digest too long for buffer or unknown hash algorithm\n");
+      gcry_md_hash_buffer (hashalgo, hash, data, datalen);
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags pss)(salt-length #00#)(hash %s %b))",
+                             gcry_md_algo_name (hashalgo),
+                             (int)hashsize, hash);
+    }
   else
     {
       gcry_mpi_t tmp;
@@ -1680,7 +1734,7 @@ dsa_gen (int keysize)
   gpg_error_t err;
   gcry_sexp_t keyspec, key;
 
-  err = gcry_sexp_build (&keyspec, NULL, 
+  err = gcry_sexp_build (&keyspec, NULL,
                          "(genkey (dsa (nbits %d)(use-fips186-2)))",
                          keysize);
   if (err)
@@ -1690,7 +1744,7 @@ dsa_gen (int keysize)
   err = gcry_pk_genkey (&key, keyspec);
   if (err)
     die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
-  
+
   gcry_sexp_release (keyspec);
 
   return key;
@@ -1705,7 +1759,7 @@ dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
   gpg_error_t err;
   gcry_sexp_t keyspec, key;
 
-  err = gcry_sexp_build (&keyspec, NULL, 
+  err = gcry_sexp_build (&keyspec, NULL,
                          "(genkey"
                          "  (dsa"
                          "    (nbits %d)"
@@ -1720,7 +1774,34 @@ dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
   err = gcry_pk_genkey (&key, keyspec);
   if (err)
     die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
-  
+
+  gcry_sexp_release (keyspec);
+
+  return key;
+}
+
+
+/* Generate an ECDSA key on the specified curve and return the complete
+   S-expression. */
+static gcry_sexp_t
+ecdsa_gen_key (const char *curve)
+{
+  gpg_error_t err;
+  gcry_sexp_t keyspec, key;
+
+  err = gcry_sexp_build (&keyspec, NULL,
+                         "(genkey"
+                         "  (ecc"
+                         "    (use-fips186)"
+                         "    (curve %s)))",
+                         curve);
+  if (err)
+    die ("gcry_sexp_build failed for ECDSA key generation: %s\n",
+         gpg_strerror (err));
+  err = gcry_pk_genkey (&key, keyspec);
+  if (err)
+    die ("gcry_pk_genkey failed for ECDSA: %s\n", gpg_strerror (err));
+
   gcry_sexp_release (keyspec);
 
   return key;
@@ -1731,7 +1812,7 @@ dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
    is the complete key as returned by dsa_gen.  We print to stdout
    with one parameter per line in hex format using this order: p, q,
    g, seed, counter, h. */
-static void 
+static void
 print_dsa_domain_parameters (gcry_sexp_t key)
 {
   gcry_sexp_t l1, l2;
@@ -1752,7 +1833,7 @@ print_dsa_domain_parameters (gcry_sexp_t key)
   l1 = l2;
 
   /* Extract the parameters from the S-expression and print them to stdout.  */
-  for (idx=0; "pqg"[idx]; idx++) 
+  for (idx=0; "pqg"[idx]; idx++)
     {
       l2 = gcry_sexp_find_token (l1, "pqg"+idx, 1);
       if (!l2)
@@ -1819,6 +1900,46 @@ print_dsa_domain_parameters (gcry_sexp_t key)
 }
 
 
+/* Print public key Q (in octet-string format) and private key d.
+   KEY is the complete key as returned by ecdsa_gen_key.
+   with one parameter per line in hex format using this order: d, Q. */
+static void
+print_ecdsa_dq (gcry_sexp_t key)
+{
+  gcry_sexp_t l1, l2;
+  gcry_mpi_t mpi;
+  int idx;
+
+  l1 = gcry_sexp_find_token (key, "private-key", 0);
+  if (!l1)
+    die ("private key not found in genkey result\n");
+
+  l2 = gcry_sexp_find_token (l1, "ecc", 0);
+  if (!l2)
+    die ("returned private key not formed as expected\n");
+  gcry_sexp_release (l1);
+  l1 = l2;
+
+  /* Extract the parameters from the S-expression and print them to stdout.  */
+  for (idx=0; "dq"[idx]; idx++)
+    {
+      l2 = gcry_sexp_find_token (l1, "dq"+idx, 1);
+      if (!l2)
+        die ("no %c parameter in returned public key\n", "dq"[idx]);
+      mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+      if (!mpi)
+        die ("no value for %c parameter in returned private key\n","dq"[idx]);
+      gcry_sexp_release (l2);
+      if (standalone_mode)
+        printf ("%c = ", "dQ"[idx]);
+      print_mpi_line (mpi, 1);
+      gcry_mpi_release (mpi);
+    }
+
+  gcry_sexp_release (l1);
+}
+
+
 /* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
    result is printed to stdout with one parameter per line in hex
    format and in this order: p, q, g, seed, counter, h.  If SEED is
@@ -1940,7 +2061,7 @@ run_dsa_sign (const void *data, size_t datalen, const char *keyfile)
   print_mpi_line (tmpmpi, 1);
   gcry_mpi_release (tmpmpi);
   gcry_sexp_release (s_tmp);
-    
+
   s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
   tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
   if (!tmpmpi)
@@ -1998,6 +2119,138 @@ run_dsa_verify (const void *data, size_t datalen,
 }
 
 
+\f
+/* Sign DATA of length DATALEN using the key taken from the S-expression
+   encoded KEYFILE. */
+static void
+run_ecdsa_sign (const void *data, size_t datalen,
+                const char *keyfile, const int algo)
+
+{
+  gpg_error_t err;
+  gcry_sexp_t s_data, s_key, s_sig, s_tmp;
+  char hash[128];
+  gcry_mpi_t tmpmpi;
+
+  s_key = read_sexp_from_file (keyfile);
+
+  gcry_md_hash_buffer (algo, hash, data, datalen);
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
+                       gcry_md_get_algo_dlen(algo), NULL);
+  if (!err)
+    {
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags raw)(hash %s %M))",
+                             gcry_md_algo_name(algo), tmpmpi);
+      gcry_mpi_release (tmpmpi);
+    }
+  if (err)
+    die ("gcry_sexp_build failed for ECDSA data input: %s\n",
+         gpg_strerror (err));
+
+  err = gcry_pk_sign (&s_sig, s_data, s_key);
+  if (err)
+    {
+      die ("gcry_pk_signed failed: %s\n", gpg_strerror (err));
+    }
+  gcry_sexp_release (s_data);
+  gcry_sexp_release (s_key);
+
+  /* Now return the actual signature.  */
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (!s_tmp)
+    die ("no sig-val element in returned S-expression\n");
+
+  gcry_sexp_release (s_sig);
+  s_sig = s_tmp;
+  s_tmp = gcry_sexp_find_token (s_sig, "ecdsa", 0);
+  if (!s_tmp)
+    die ("no ecdsa element in returned S-expression\n");
+
+  gcry_sexp_release (s_sig);
+  s_sig = s_tmp;
+
+  s_tmp = gcry_sexp_find_token (s_sig, "r", 0);
+  tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
+  if (!tmpmpi)
+    die ("no r parameter in returned S-expression\n");
+  print_mpi_line (tmpmpi, 1);
+  gcry_mpi_release (tmpmpi);
+  gcry_sexp_release (s_tmp);
+
+  s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
+  tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
+  if (!tmpmpi)
+    die ("no s parameter in returned S-expression\n");
+  print_mpi_line (tmpmpi, 1);
+  gcry_mpi_release (tmpmpi);
+  gcry_sexp_release (s_tmp);
+
+  gcry_sexp_release (s_sig);
+}
+
+
+\f
+/* Verify DATA of length DATALEN using the public key taken from the
+   S-expression in KEYFILE against the S-expression formatted
+   signature in SIGFILE.  */
+static void
+run_ecdsa_verify (const void *data, size_t datalen,
+                const char *keyfile, const int algo, const char *sigfile)
+
+{
+  gpg_error_t err;
+  gcry_sexp_t s_data, s_key, s_sig;
+  char hash[128];
+  gcry_mpi_t tmpmpi;
+
+  s_key = read_sexp_from_file (keyfile);
+
+  gcry_md_hash_buffer (algo, hash, data, datalen);
+  /* Note that we can't simply use %b with HASH to build the
+     S-expression, because that might yield a negative value.  */
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
+                       gcry_md_get_algo_dlen(algo), NULL);
+  if (!err)
+    {
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags raw)(hash %s %M))",
+                             gcry_md_algo_name(algo), tmpmpi);
+      gcry_mpi_release (tmpmpi);
+    }
+  if (err)
+    die ("gcry_sexp_build failed for DSA data input: %s\n",
+         gpg_strerror (err));
+
+  s_sig = read_sexp_from_file (sigfile);
+
+  err = gcry_pk_verify (s_sig, s_data, s_key);
+  if (!err)
+    puts ("GOOD signature");
+  else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
+    puts ("BAD signature");
+  else
+    printf ("ERROR (%s)\n", gpg_strerror (err));
+
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_key);
+  gcry_sexp_release (s_data);
+}
+
+
+/* Generate an ECDSA key with specified domain parameters
+   and print the d and Q values, in the standard octet-string format. */
+static void
+run_ecdsa_gen_key (const char *curve)
+{
+  gcry_sexp_t key;
+
+  key = ecdsa_gen_key (curve);
+  print_ecdsa_dq (key);
+
+  gcry_sexp_release (key);
+}
+
 
 \f
 static void
@@ -2005,7 +2258,7 @@ usage (int show_help)
 {
   if (!show_help)
     {
-      fputs ("usage: " PGM 
+      fputs ("usage: " PGM
              " [OPTION] [FILE] (try --help for more information)\n", stderr);
       exit (2);
     }
@@ -2014,7 +2267,8 @@ usage (int show_help)
      "Run a crypto operation using hex encoded input and output.\n"
      "MODE:\n"
      "  encrypt, decrypt, digest, random, hmac-sha,\n"
-     "  rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n"
+     "  rsa-{derive,gen,sign,verify},\n"
+     "  dsa-{pqg-gen,gen,sign,verify}, ecdsa-{gen-key,sign,verify}\n"
      "OPTIONS:\n"
      "  --verbose        Print additional information\n"
      "  --binary         Input and output is in binary form\n"
@@ -2023,10 +2277,12 @@ usage (int show_help)
      "  --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"
+     "  --curve NAME     Select ECC curve spec 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"
+     "  --pss            Use PSS encoding with a zero length salt\n"
      "  --mct-server     Run a monte carlo test server\n"
      "  --loop           Enable random loop mode\n"
      "  --progress       Print pogress indicators\n"
@@ -2044,7 +2300,9 @@ main (int argc, char **argv)
   int no_fips = 0;
   int progress = 0;
   int use_pkcs1 = 0;
+  int use_pss = 0;
   const char *mode_string;
+  const char *curve_string = NULL;
   const char *key_string = NULL;
   const char *iv_string = NULL;
   const char *dt_string = NULL;
@@ -2160,11 +2418,24 @@ main (int argc, char **argv)
           binary_input = binary_output = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--curve"))
+        {
+          argc--; argv++;
+          if (!argc)
+            usage (0);
+          curve_string = *argv;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--pkcs1"))
         {
           use_pkcs1 = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--pss"))
+        {
+          use_pss = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--mct-server"))
         {
           mct_server = 1;
@@ -2175,12 +2446,16 @@ main (int argc, char **argv)
           standalone_mode = 1;
           argc--; argv++;
         }
-    }          
+    }
 
   if (!argc || argc > 2)
     usage (0);
+
   mode_string = *argv;
 
+  if (use_pkcs1 && use_pss)
+    die ("Only one of --pkcs or --pss may be given\n");
+
   if (!strcmp (mode_string, "rsa-derive"))
     binary_input = 1;
 
@@ -2201,29 +2476,32 @@ main (int argc, char **argv)
   if (verbose)
     fprintf (stderr, PGM ": started (mode=%s)\n", mode_string);
 
-  gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
   if (!no_fips)
-    gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+    xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
   if (!gcry_check_version ("1.4.3"))
     die ("Libgcrypt is not sufficient enough\n");
   if (verbose)
     fprintf (stderr, PGM ": using Libgcrypt %s\n", gcry_check_version (NULL));
   if (no_fips)
-    gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
   /* Most operations need some input data.  */
   if (!chunksize
       && !mct_server
       && strcmp (mode_string, "random")
       && strcmp (mode_string, "rsa-gen")
-      && strcmp (mode_string, "dsa-gen") )
+      && strcmp (mode_string, "rsa-keygen")
+      && strcmp (mode_string, "rsa-keygen-kat")
+      && strcmp (mode_string, "dsa-gen")
+      && strcmp (mode_string, "ecdsa-gen-key") )
     {
       data = read_file (input, !binary_input, &datalen);
       if (!data)
         die ("error reading%s input\n", binary_input?"":" and decoding");
       if (verbose)
-        fprintf (stderr, PGM ": %u bytes of input data\n", 
+        fprintf (stderr, PGM ": %u bytes of input data\n",
                  (unsigned int)datalen);
     }
   else
@@ -2261,7 +2539,8 @@ main (int argc, char **argv)
                   die ("no version info in input\n");
                 }
               if (atoi (key_buffer) != 1)
-                die ("unsupported input version %s\n", key_buffer);
+                die ("unsupported input version %s\n",
+                     (const char*)key_buffer);
               gcry_free (key_buffer);
               if (!(key_buffer = read_textline (input)))
                 die ("no iteration count in input\n");
@@ -2274,7 +2553,7 @@ main (int argc, char **argv)
               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,
@@ -2335,11 +2614,11 @@ main (int argc, char **argv)
       unsigned char buffer[16];
       size_t count = 0;
 
-      if (hex2bin (key_string, key, 16) < 0 )
+      if (!key_string || hex2bin (key_string, key, 16) < 0 )
         die ("value for --key are not 32 hex digits\n");
-      if (hex2bin (iv_string, seed, 16) < 0 )
+      if (!iv_string || hex2bin (iv_string, seed, 16) < 0 )
         die ("value for --iv are not 32 hex digits\n");
-      if (hex2bin (dt_string, dt, 16) < 0 )
+      if (!dt_string || hex2bin (dt_string, dt, 16) < 0 )
         die ("value for --dt are not 32 hex digits\n");
 
       /* The flag value 1 disables the dup check, so that the RNG
@@ -2348,7 +2627,7 @@ main (int argc, char **argv)
       if (err)
         die ("init external RNG test failed: %s\n", gpg_strerror (err));
 
-      do 
+      do
         {
           err = run_external_rng_test (context, buffer, sizeof buffer);
           if (err)
@@ -2357,15 +2636,15 @@ main (int argc, char **argv)
           if (progress)
             {
               if (!(++count % 1000))
-                fprintf (stderr, PGM ": %lu random bytes so far\n", 
-                         (unsigned long int)count * sizeof buffer);
+                fprintf (stderr, PGM ": %lu random bytes so far\n",
+                         (unsigned long int)(count * sizeof buffer));
             }
         }
       while (loop_mode);
-      
+
       if (progress)
         fprintf (stderr, PGM ": %lu random bytes\n",
-                         (unsigned long int)count * sizeof buffer);
+                 (unsigned long int)(count * sizeof buffer));
 
       deinit_external_rng_test (context);
     }
@@ -2406,10 +2685,24 @@ main (int argc, char **argv)
         die ("no data available (do not use --chunk)\n");
       run_rsa_derive (data, datalen);
     }
+  else if (!strcmp (mode_string, "rsa-keygen"))
+    {
+      data = read_file (input, 0, &datalen);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+      run_rsa_keygen (data, datalen, 0);
+    }
+  else if (!strcmp (mode_string, "rsa-keygen-kat"))
+    {
+      data = read_file (input, 0, &datalen);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+      run_rsa_keygen (data, datalen, 1);
+    }
   else if (!strcmp (mode_string, "rsa-gen"))
     {
       int keysize;
-      
+
       if (!binary_output)
         base64_output = 1;
 
@@ -2434,7 +2727,7 @@ main (int argc, char **argv)
       if (!data)
         die ("no data available (do not use --chunk)\n");
 
-      run_rsa_sign (data, datalen, algo, use_pkcs1, key_string);
+      run_rsa_sign (data, datalen, algo, use_pkcs1, use_pss, key_string);
 
     }
   else if (!strcmp (mode_string, "rsa-verify"))
@@ -2457,14 +2750,14 @@ main (int argc, char **argv)
       if (access (signature_string, R_OK))
         die ("option --signature needs to specify an existing file\n");
 
-      run_rsa_verify (data, datalen, algo, use_pkcs1, key_string,
+      run_rsa_verify (data, datalen, algo, use_pkcs1, use_pss, key_string,
                       signature_string);
 
     }
   else if (!strcmp (mode_string, "dsa-pqg-gen"))
     {
       int keysize;
-      
+
       keysize = keysize_string? atoi (keysize_string) : 0;
       if (keysize < 1024 || keysize > 3072)
         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
@@ -2473,7 +2766,7 @@ main (int argc, char **argv)
   else if (!strcmp (mode_string, "dsa-gen"))
     {
       int keysize;
-      
+
       keysize = keysize_string? atoi (keysize_string) : 0;
       if (keysize < 1024 || keysize > 3072)
         die ("invalid keysize specified; needs to be 1024 .. 3072\n");
@@ -2507,6 +2800,53 @@ main (int argc, char **argv)
 
       run_dsa_verify (data, datalen, key_string, signature_string);
     }
+  else if (!strcmp (mode_string, "ecdsa-gen-key"))
+    {
+      if (!curve_string)
+        die ("option --curve containing name of the specified curve is required in this mode\n");
+      run_ecdsa_gen_key (curve_string);
+    }
+  else if (!strcmp (mode_string, "ecdsa-sign"))
+    {
+      int algo;
+
+      if (!key_string)
+        die ("option --key is required in this mode\n");
+      if (access (key_string, R_OK))
+        die ("option --key needs to specify an existing keyfile\n");
+      if (!algo_string)
+        die ("use --algo to specify the digest algorithm\n");
+      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_ecdsa_sign (data, datalen, key_string, algo);
+    }
+  else if (!strcmp (mode_string, "ecdsa-verify"))
+    {
+      int algo;
+
+      if (!key_string)
+        die ("option --key is required in this mode\n");
+      if (access (key_string, R_OK))
+        die ("option --key needs to specify an existing keyfile\n");
+      if (!algo_string)
+        die ("use --algo to specify the digest algorithm\n");
+      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");
+      if (!signature_string)
+        die ("option --signature is required in this mode\n");
+      if (access (signature_string, R_OK))
+        die ("option --signature needs to specify an existing file\n");
+
+      run_ecdsa_verify (data, datalen, key_string, algo, signature_string);
+    }
   else
     usage (0);
 
@@ -2523,4 +2863,3 @@ main (int argc, char **argv)
 
   return 0;
 }
-