A lot of cleanups as well as minor API changes.
[libgcrypt.git] / cipher / pubkey.c
index 8aa13c2..228b0d0 100644 (file)
@@ -66,7 +66,7 @@ static struct pubkey_table_entry
 static gcry_module_t pubkeys_registered;
 
 /* This is the lock protecting PUBKEYS_REGISTERED.  */
-static ath_mutex_t pubkeys_registered_lock;
+static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;;
 
 /* Flag to check wether the default pubkeys have already been
    registered.  */
@@ -93,12 +93,19 @@ static gcry_err_code_t
 dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
                 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
+  (void)algorithm;
+  (void)nbits;
+  (void)dummy;
+  (void)skey;
+  (void)retfactors;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
 static gcry_err_code_t
 dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
 {
+  (void)algorithm;
+  (void)skey;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -106,6 +113,11 @@ static gcry_err_code_t
 dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
                gcry_mpi_t *pkey, int flags)
 {
+  (void)algorithm;
+  (void)resarr;
+  (void)data;
+  (void)pkey;
+  (void)flags;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -113,6 +125,11 @@ static gcry_err_code_t
 dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
                gcry_mpi_t *skey, int flags)
 {
+  (void)algorithm;
+  (void)result;
+  (void)data;
+  (void)skey;
+  (void)flags;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -120,6 +137,10 @@ static gcry_err_code_t
 dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
             gcry_mpi_t *skey)
 {
+  (void)algorithm;
+  (void)resarr;
+  (void)data;
+  (void)skey;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -128,12 +149,20 @@ dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
               gcry_mpi_t *pkey,
              int (*cmp) (void *, gcry_mpi_t), void *opaquev)
 {
+  (void)algorithm;
+  (void)hash;
+  (void)data;
+  (void)pkey;
+  (void)cmp;
+  (void)opaquev;
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
 static unsigned
 dummy_get_nbits (int algorithm, gcry_mpi_t *pkey)
 {
+  (void)algorithm;
+  (void)pkey;
   return 0;
 }
 
@@ -174,7 +203,7 @@ gcry_pk_lookup_func_name (void *spec, void *data)
 {
   gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec;
   char *name = (char *) data;
-  char **aliases = pubkey->aliases;
+  const char **aliases = pubkey->aliases;
   int ret = stricmp (name, pubkey->name);
 
   while (ret && *aliases)
@@ -467,7 +496,8 @@ pubkey_get_nenc (int algorithm)
 
 
 static gcry_err_code_t
-pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e,
+pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
+                 unsigned long use_e,
                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
@@ -479,8 +509,13 @@ pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e,
   pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
   if (pubkey)
     {
-      err = ((gcry_pk_spec_t *) pubkey->spec)->generate 
-        (algorithm, nbits, use_e, skey, retfactors);
+      /* Hack to pass QBITS to the DSA generation.  */
+      if (qbits && pubkey->spec == &_gcry_pubkey_spec_dsa)
+        err = _gcry_dsa_generate2
+          (algorithm, nbits, qbits, 0, skey, retfactors);
+      else
+        err = ((gcry_pk_spec_t *) pubkey->spec)->generate 
+          (algorithm, nbits, use_e, skey, retfactors);
       _gcry_module_release (pubkey);
     }
   ath_mutex_unlock (&pubkeys_registered_lock);
@@ -786,7 +821,15 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
     }
 
     {
-      char *name_terminated = gcry_xmalloc (n + 1);
+      char *name_terminated;
+
+      name_terminated = gcry_malloc (n + 1);
+      if (!name_terminated)
+        {
+          err = gpg_err_code_from_errno (errno);
+          gcry_sexp_release (list);
+          return err;
+        }
       memcpy (name_terminated, name, n);
       name_terminated[n] = 0;
 
@@ -876,7 +919,17 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
     }
       
     {
-      char *name_terminated = gcry_xmalloc (n + 1);
+      char *name_terminated;
+
+      name_terminated = gcry_malloc (n + 1);
+      if (!name_terminated)
+        {
+          err = gcry_err_code_from_errno (errno);
+         gcry_sexp_release (l2);
+         gcry_sexp_release (list);
+          return err;
+        }
+          
       memcpy (name_terminated, name, n);
       name_terminated[n] = 0;
       
@@ -1026,7 +1079,14 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
     }
 
   {
-    char *name_terminated = gcry_xmalloc (n + 1);
+    char *name_terminated;
+
+    name_terminated = gcry_malloc (n + 1);
+    if (!name_terminated)
+      {
+        err = gcry_err_code_from_errno (errno);
+        goto leave;
+      }
     memcpy (name_terminated, name, n);
     name_terminated[n] = 0;
     
@@ -1240,15 +1300,16 @@ sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
           static struct { const char *name; int algo; } hashnames[] = 
           { { "sha1",   GCRY_MD_SHA1 },
             { "md5",    GCRY_MD_MD5 },
-            { "rmd160", GCRY_MD_RMD160 },
             { "sha256", GCRY_MD_SHA256 },
+            { "ripemd160", GCRY_MD_RMD160 },
+            { "rmd160", GCRY_MD_RMD160 },
             { "sha384", GCRY_MD_SHA384 },
             { "sha512", GCRY_MD_SHA512 },
             { "md2",    GCRY_MD_MD2 },
             { "md4",    GCRY_MD_MD4 },
             { "tiger",  GCRY_MD_TIGER },
             { "haval",  GCRY_MD_HAVAL },
-            { NULL }
+            { NULL, 0 }
           };
           int algo;
           byte asn[100];
@@ -1391,7 +1452,12 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
     goto leave;
 
   /* Now we can encrypt DATA to CIPH. */
-  ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph));
+  ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
+  if (!ciph)
+    {
+      rc = gpg_err_code_from_errno (errno);
+      goto leave;
+    }
   rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags);
   mpi_free (data);
   data = NULL;
@@ -1407,7 +1473,12 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
     void **arg_list;
     
     /* Build the string.  */
-    string = p = gcry_xmalloc (needed);
+    string = p = gcry_malloc (needed);
+    if (!string)
+      {
+        rc = gpg_err_code_from_errno (errno);
+        goto leave;
+      }
     p = stpcpy ( p, "(enc-val(" );
     p = stpcpy ( p, algo_name );
     for (i=0; algo_elems[i]; i++ )
@@ -1609,7 +1680,12 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
   if (rc)
     goto leave;
 
-  result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result));
+  result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
+  if (!result)
+    {
+      rc = gpg_err_code_from_errno (errno);
+      goto leave;
+    }
   rc = pubkey_sign (module->mod_id, result, hash, skey);
   if (rc)
     goto leave;
@@ -1625,7 +1701,12 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
     needed += 10 * nelem;
 
     /* Build the string. */
-    string = p = gcry_xmalloc (needed);
+    string = p = gcry_malloc (needed);
+    if (!string)
+      {
+        rc = gpg_err_code_from_errno (errno);
+        goto leave;
+      }
     p = stpcpy (p, "(sig-val(");
     p = stpcpy (p, algo_name);
     for (i = 0; algo_elems[i]; i++)
@@ -1816,6 +1897,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   gcry_mpi_t skey[10], *factors = NULL;
   unsigned int nbits = 0;
   unsigned long use_e = 0;
+  unsigned int qbits;
   char *name_terminated;
 
   REGISTER_DEFAULT_PUBKEYS;
@@ -1847,7 +1929,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
       goto leave;
     }
 
-  name_terminated = gcry_xmalloc (n + 1);
+  name_terminated = gcry_malloc (n + 1);
+  if (!name_terminated)
+    {
+      rc = gpg_err_code_from_errno (errno);
+      goto leave;
+    }
   memcpy (name_terminated, name, n);
   name_terminated[n] = 0;
   ath_mutex_lock (&pubkeys_registered_lock);
@@ -1890,6 +1977,28 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   else
     use_e = 65537; /* Not given, use the value generated by old versions. */
 
+  /* Handle the optional qbits element. */
+  l2 = gcry_sexp_find_token (list, "qbits", 0);
+  if (l2)
+    {
+      char buf[50];
+
+      name = gcry_sexp_nth_data (l2, 1, &n);
+      if ((! name) || (n >= DIM (buf) - 1))
+        {
+          rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
+          goto leave;
+        }
+      memcpy (buf, name, n);
+      buf[n] = 0;
+      qbits = (unsigned int)strtoul (buf, NULL, 0);
+      gcry_sexp_release (l2);
+      l2 = NULL;
+    }
+  else
+    qbits = 0;
+
+  /* Now parse the required nbits element. */
   l2 = gcry_sexp_find_token (list, "nbits", 0);
   gcry_sexp_release (list);
   list = l2;
@@ -1908,13 +2017,18 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
       goto leave;
     }
   
-  name_terminated = gcry_xmalloc (n + 1);
+  name_terminated = gcry_malloc (n + 1);
+  if (!name_terminated)
+    {
+      rc = gpg_err_code_from_errno (errno);
+      goto leave;
+    }
   memcpy (name_terminated, name, n);
   name_terminated[n] = 0;
   nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
   gcry_free (name_terminated);
 
-  rc = pubkey_generate (module->mod_id, nbits, use_e, skey, &factors);
+  rc = pubkey_generate (module->mod_id, nbits, qbits, use_e, skey, &factors);
   if (rc)
     goto leave;
 
@@ -1935,7 +2049,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
 
     /* Build the string. */
     nelem = 0;
-    string = p = gcry_xmalloc (needed);
+    string = p = gcry_malloc (needed);
+    if (!string)
+      {
+        rc = gpg_err_code_from_errno (errno);
+        goto leave;
+      }
     p = stpcpy (p, "(key-data");
     p = stpcpy (p, "(public-key(");
     p = stpcpy (p, algo_name);
@@ -2103,7 +2222,9 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
     goto fail; /* Invalid structure of object. */
 
   {
-    char *name_terminated = gcry_xmalloc (n + 1);
+    char *name_terminated = gcry_malloc (n + 1);
+    if (!name_terminated)
+      goto fail;
     memcpy (name_terminated, name, n);
     name_terminated[n] = 0;
     ath_mutex_lock (&pubkeys_registered_lock);