]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Use the PKCS #1 1.5 encoding provided by nettle (2.5) for encryption and signatures.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 9 May 2012 16:02:12 +0000 (18:02 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 22 May 2012 07:20:20 +0000 (09:20 +0200)
28 files changed:
NEWS
doc/cha-cert-auth2.texi
lib/abstract_int.h
lib/algorithms.h
lib/algorithms/sign.c
lib/auth/rsa.c
lib/auth/rsa_export.c
lib/crypto-backend.h
lib/ext/signature.c
lib/gnutls_pk.c
lib/gnutls_pk.h
lib/gnutls_privkey.c
lib/gnutls_pubkey.c
lib/gnutls_sig.c
lib/gnutls_sig.h
lib/includes/gnutls/abstract.h
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
lib/nettle/pk.c
lib/opencdk/main.h
lib/opencdk/pubkey.c
lib/opencdk/seskey.c
lib/openpgp/privkey.c
lib/x509/privkey.c
lib/x509/verify.c
lib/x509/x509.c
lib/x509/x509_int.h
tests/x509sign-verify.c

diff --git a/NEWS b/NEWS
index 4afa452712eb41a3f6e2a9de45b409a90916d0aa..81e46e01ae5cb9e98ae69ce0f00ee7e88e02dcfe 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ See the end for copying conditions.
 
 * Version 3.1.0 (unreleased)
 
+** libgnutls: Use the PKCS #1 1.5 encoding provided by nettle (2.5)
+for encryption and signatures.
+
 ** libgnutls: When decoding a PKCS #11 URL the pin-source field
 is assumed to be a file that stores the pin. Based on patch
 by David Smith.
@@ -39,7 +42,7 @@ with openssl.
 in pkcs12 decoding tests.
 
 ** API and ABI modifications:
-No changes since last version.
+gnutls_pubkey_verify_hash2: Added
 
 
 * Version 3.0.18 (released 2012-04-02)
index 9ebb74a0af716a01a6f4b9ad175fe1de3ebef1f7..0c731a3753f20c97555ee5f5cd72f0a9445ba159 100644 (file)
@@ -616,7 +616,7 @@ The abstract key types can be used to access signing and
 signature verification operations with the underlying keys.
 
 @showfuncdesc{gnutls_pubkey_verify_data2}
-@showfuncdesc{gnutls_pubkey_verify_hash}
+@showfuncdesc{gnutls_pubkey_verify_hash2}
 @showfuncdesc{gnutls_pubkey_encrypt_data}
 
 @showfuncdesc{gnutls_privkey_sign_data}
index ca2be2b853883891aedc2d9460d423d698ea6606..ad859e55d641b1f8c97ec17b594f6babb443ef38 100644 (file)
@@ -36,10 +36,12 @@ int
 _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
                                  gnutls_pk_params_st * params);
 
-int pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk, 
-                       const gnutls_datum_t * hash,
-                       const gnutls_datum_t * signature,
-                       gnutls_pk_params_st * issuer_params);
+int
+pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
+                           gnutls_digest_algorithm_t algo,
+                           const gnutls_datum_t * hash,
+                           const gnutls_datum_t * signature,
+                           gnutls_pk_params_st * issuer_params);
 
 int pubkey_verify_data (gnutls_pk_algorithm_t pk,
                         gnutls_digest_algorithm_t algo,
index e2600c605abbc3c15a224953bb433b66a801eb3d..9fe0272541541df895a2a36895bfc534bbbdd1c5 100644 (file)
@@ -106,8 +106,6 @@ enum encipher_type _gnutls_kx_encipher_type (gnutls_kx_algorithm_t algorithm);
 
 /* Functions for sign algorithms. */
 gnutls_sign_algorithm_t _gnutls_x509_oid2sign_algorithm (const char *oid);
-gnutls_sign_algorithm_t _gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk,
-                                                 gnutls_digest_algorithm_t mac);
 gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk (gnutls_sign_algorithm_t sign);
 const char *_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t,
                                       gnutls_digest_algorithm_t mac);
index ab81b830d38a7812a8acf527133275ff081728d3..b422c4c5c0be3df8c812d8ee3df87675f7e96afd 100644 (file)
@@ -134,12 +134,12 @@ static gnutls_sign_algorithm_t supported_sign[MAX_ALGOS] = {0};
 
 /**
  * gnutls_sign_get_id:
- * @name: is a MAC algorithm name
+ * @name: is a sign algorithm name
  *
  * The names are compared in a case insensitive way.
  *
  * Returns: return a #gnutls_sign_algorithm_t value corresponding to
- *   the specified cipher, or %GNUTLS_SIGN_UNKNOWN on error.
+ *   the specified algorithm, or %GNUTLS_SIGN_UNKNOWN on error.
  **/
 gnutls_sign_algorithm_t
 gnutls_sign_get_id (const char *name)
@@ -178,12 +178,22 @@ _gnutls_x509_oid2sign_algorithm (const char *oid)
   return ret;
 }
 
+/**
+ * gnutls_pk_to_sign:
+ * @pk: is a public key algorithm
+ * @hash: a hash algorithm
+ *
+ * This function maps public key and hash algorithms combinations
+ * to signature algorithms.
+ *
+ * Returns: return a #gnutls_sign_algorithm_t value, or %GNUTLS_SIGN_UNKNOWN on error.
+ **/
 gnutls_sign_algorithm_t
-_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t mac)
+gnutls_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash)
 {
   gnutls_sign_algorithm_t ret = 0;
 
-  GNUTLS_SIGN_LOOP (if (pk == p->pk && mac == p->mac)
+  GNUTLS_SIGN_LOOP (if (pk == p->pk && hash == p->mac)
                     {
                     ret = p->id; break;}
   );
@@ -200,7 +210,7 @@ _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
   gnutls_sign_algorithm_t sign;
   const char *ret = NULL;
 
-  sign = _gnutls_x509_pk_to_sign (pk, mac);
+  sign = gnutls_pk_to_sign (pk, mac);
   if (sign == GNUTLS_SIGN_UNKNOWN)
     return NULL;
 
index 77a61f98141061aa8969df2e3247bf6ceb3c8108..f728503b89f57d1e5247db4619bbb8582c1a377c 100644 (file)
@@ -298,8 +298,8 @@ _gnutls_gen_rsa_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
     }
 
   ret =
-       _gnutls_pkcs1_rsa_encrypt (&sdata, &session->key->key,
-                                  &params, 2);
+       _gnutls_pk_encrypt (GNUTLS_PK_RSA, &sdata, &session->key->key,
+                                  &params);
 
   gnutls_pk_params_release(&params);
 
index f93211d8319fca0265bad0cd55f774dec1b38277..df78deaae6b95a75deaf05a99cbf40915133588d 100644 (file)
@@ -159,7 +159,7 @@ proc_rsa_export_client_kx (gnutls_session_t session, uint8_t * data,
       return ret;
     }
 
-  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, 2);     /* btype==2 */
+  ret = _gnutls_pk_decrypt (GNUTLS_PK_RSA, &plaintext, &ciphertext, params);
 
   if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
     {
index 1044f00ea9bbb6b6075754ea7b2117c668849a22..58c7530c0efb56a5668a50af872e6378c5ffe6e2 100644 (file)
                  const gnutls_datum_t * data,
                  const gnutls_pk_params_st * priv);
     int (*verify) (gnutls_pk_algorithm_t, const gnutls_datum_t * data,
-                   const gnutls_datum_t * signature,
+                   const gnutls_datum_t * sig,
                    const gnutls_pk_params_st * pub);
+    /* given a signature and the public parameters,
+     * suggest a hash algorithm */
+    int (*hash_algorithm) (gnutls_pk_algorithm_t, 
+                   const gnutls_datum_t * sig,
+                   gnutls_pk_params_st * issuer_params,
+                   gnutls_digest_algorithm_t*);
+    /* sanity checks the public key parameters */
     int (*verify_params) (gnutls_pk_algorithm_t, 
                           const gnutls_pk_params_st * pub);
     int (*generate) (gnutls_pk_algorithm_t, unsigned int nbits,
index 4fe9795d8e26343f0c3c430f50d203854a0227fa..47724da4e8131709bfd563708f55a451b3710f11 100644 (file)
@@ -27,6 +27,7 @@
 #include "gnutls_int.h"
 #include "gnutls_errors.h"
 #include "gnutls_num.h"
+#include <gnutls/gnutls.h>
 #include <ext/signature.h>
 #include <gnutls_state.h>
 #include <gnutls_num.h>
@@ -264,7 +265,7 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert)
       || priv->sign_algorithms_size == 0)
     /* none set, allow SHA-1 only */
     {
-      return _gnutls_x509_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1);
+      return gnutls_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1);
     }
 
   for (i = 0; i < priv->sign_algorithms_size; i++)
index 738f1accf2ce4a341ff17b4c456641b56c6831ba..8c3b9d3eaee7b4b408af1d591554471a3337c65c 100644 (file)
 #include <x509/common.h>
 #include <random.h>
 
-/* Do PKCS-1 RSA encryption. 
- * params is modulus, public exp.
- */
-int
-_gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
-                           const gnutls_datum_t * plaintext,
-                           gnutls_pk_params_st * params, 
-                           unsigned btype)
-{
-  unsigned int i, pad;
-  int ret;
-  uint8_t *edata, *ps;
-  size_t k, psize;
-  size_t mod_bits;
-  gnutls_datum_t to_encrypt, encrypted;
-
-  mod_bits = _gnutls_mpi_get_nbits (params->params[0]);
-  k = mod_bits / 8;
-  if (mod_bits % 8 != 0)
-    k++;
-
-  if (plaintext->size > k - 11)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_PK_ENCRYPTION_FAILED;
-    }
-
-  edata = gnutls_malloc (k);
-  if (edata == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  /* EB = 00||BT||PS||00||D 
-   * (use block type 'btype')
-   */
-
-  edata[0] = 0;
-  edata[1] = btype;
-  psize = k - 3 - plaintext->size;
-
-  ps = &edata[2];
-  switch (btype)
-    {
-    case 2:
-      /* using public key */
-      if (params->params_nr < RSA_PUBLIC_PARAMS)
-        {
-          gnutls_assert ();
-          gnutls_free (edata);
-          return GNUTLS_E_INTERNAL_ERROR;
-        }
-
-      ret = _gnutls_rnd (GNUTLS_RND_RANDOM, ps, psize);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          gnutls_free (edata);
-          return ret;
-        }
-      for (i = 0; i < psize; i++)
-        while (ps[i] == 0)
-          {
-            ret = _gnutls_rnd (GNUTLS_RND_RANDOM, &ps[i], 1);
-            if (ret < 0)
-              {
-                gnutls_assert ();
-                gnutls_free (edata);
-                return ret;
-              }
-          }
-      break;
-    case 1:
-      /* using private key */
-
-      if (params->params_nr < RSA_PRIVATE_PARAMS)
-        {
-          gnutls_assert ();
-          gnutls_free (edata);
-          return GNUTLS_E_INTERNAL_ERROR;
-        }
-
-      for (i = 0; i < psize; i++)
-        ps[i] = 0xff;
-      break;
-    default:
-      gnutls_assert ();
-      gnutls_free (edata);
-      return GNUTLS_E_INTERNAL_ERROR;
-    }
-
-  ps[psize] = 0;
-  memcpy (&ps[psize + 1], plaintext->data, plaintext->size);
-
-  to_encrypt.data = edata;
-  to_encrypt.size = k;
-
-  if (btype == 2)               /* encrypt */
-    ret =
-      _gnutls_pk_encrypt (GNUTLS_PK_RSA, &encrypted, &to_encrypt, params);
-  else                          /* sign */
-    ret =
-      _gnutls_pk_sign (GNUTLS_PK_RSA, &encrypted, &to_encrypt, params);
-
-  gnutls_free (edata);
-
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  psize = encrypted.size;
-  if (psize < k)
-    {
-      /* padding psize */
-      pad = k - psize;
-      psize = k;
-    }
-  else if (psize == k)
-    {
-      /* pad = 0; 
-       * no need to do anything else
-       */
-      ciphertext->data = encrypted.data;
-      ciphertext->size = encrypted.size;
-      return 0;
-    }
-  else
-    {                           /* psize > k !!! */
-      /* This is an impossible situation */
-      gnutls_assert ();
-      _gnutls_free_datum (&encrypted);
-      return GNUTLS_E_INTERNAL_ERROR;
-    }
-
-  ciphertext->data = gnutls_malloc (psize);
-  if (ciphertext->data == NULL)
-    {
-      gnutls_assert ();
-      ret = GNUTLS_E_MEMORY_ERROR;
-      goto cleanup;
-    }
-
-  memcpy (&ciphertext->data[pad], encrypted.data, encrypted.size);
-  for (i = 0; i < pad; i++)
-    ciphertext->data[i] = 0;
-
-  ciphertext->size = k;
-
-  ret = 0;
-
-cleanup:
-  _gnutls_free_datum (&encrypted);
-
-  return ret;
-}
-
-
-/* Do PKCS-1 RSA decryption. 
- * params is modulus, public exp., private key
- * Can decrypt block type 1 and type 2 packets.
- */
-int
-_gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
-                           const gnutls_datum_t * ciphertext,
-                           gnutls_pk_params_st* params,
-                           unsigned btype)
-{
-  unsigned int k, i;
-  int ret;
-  size_t esize, mod_bits;
-
-  mod_bits = _gnutls_mpi_get_nbits (params->params[0]);
-  k = mod_bits / 8;
-  if (mod_bits % 8 != 0)
-    k++;
-
-  esize = ciphertext->size;
-
-  if (esize != k)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_PK_DECRYPTION_FAILED;
-    }
-
-  /* we can use btype to see if the private key is
-   * available.
-   */
-  if (btype == 2)
-    {
-      ret =
-        _gnutls_pk_decrypt (GNUTLS_PK_RSA, plaintext, ciphertext, params);
-    }
-  else
-    {
-      ret =
-        _gnutls_pk_encrypt (GNUTLS_PK_RSA, plaintext, ciphertext, params);
-    }
-
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  /* EB = 00||BT||PS||00||D
-   * (use block type 'btype')
-   *
-   * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
-   * avoid attacks similar to the one described by Bleichenbacher in:
-   * "Chosen Ciphertext Attacks against Protocols Based on RSA
-   * Encryption Standard PKCS #1".
-   */
-  if (plaintext->data[0] != 0 || plaintext->data[1] != btype)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (plaintext);
-      return GNUTLS_E_DECRYPTION_FAILED;
-    }
-
-  ret = GNUTLS_E_DECRYPTION_FAILED;
-  switch (btype)
-    {
-    case 2:
-      for (i = 2; i < plaintext->size; i++)
-        {
-          if (plaintext->data[i] == 0)
-            {
-              ret = 0;
-              break;
-            }
-        }
-      break;
-    case 1:
-      for (i = 2; i < plaintext->size; i++)
-        {
-          if (plaintext->data[i] == 0 && i > 2)
-            {
-              ret = 0;
-              break;
-            }
-          if (plaintext->data[i] != 0xff)
-            {
-              _gnutls_handshake_log ("PKCS #1 padding error");
-              _gnutls_free_datum (plaintext);
-              /* PKCS #1 padding error.  Don't use
-                 GNUTLS_E_PKCS1_WRONG_PAD here.  */
-              break;
-            }
-        }
-      break;
-    default:
-      gnutls_assert ();
-      _gnutls_free_datum (plaintext);
-      break;
-    }
-
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (plaintext);
-      return GNUTLS_E_DECRYPTION_FAILED;
-    }
-
-  i++;
-  memmove (plaintext->data, &plaintext->data[i], esize - i);
-  plaintext->size = esize - i;
-
-  return 0;
-}
-
-
-int
-_gnutls_rsa_verify (const gnutls_datum_t * vdata,
-                    const gnutls_datum_t * ciphertext, 
-                    gnutls_pk_params_st * params,
-                    int btype)
-{
-
-  gnutls_datum_t plain;
-  int ret;
-
-  /* decrypt signature */
-  if ((ret =
-       _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params,
-                                  btype)) < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  if (plain.size != vdata->size)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (&plain);
-      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-    }
-
-  if (memcmp (plain.data, vdata->data, plain.size) != 0)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (&plain);
-      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-    }
-
-  _gnutls_free_datum (&plain);
-
-  return 0;                     /* ok */
-}
-
 /* encodes the Dss-Sig-Value structure
  */
 int
@@ -506,3 +194,172 @@ _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk,
                                         NULL, pk, params);
 
 }
+
+/* Writes the digest information and the digest in a DER encoded
+ * structure. The digest info is allocated and stored into the info structure.
+ */
+int
+encode_ber_digest_info (gnutls_digest_algorithm_t hash,
+                        const gnutls_datum_t * digest,
+                        gnutls_datum_t * output)
+{
+  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
+  int result;
+  const char *algo;
+  uint8_t *tmp_output;
+  int tmp_output_size;
+
+  algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
+  if (algo == NULL)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Hash algorithm: %d has no OID\n", hash);
+      return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+    }
+
+  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
+                                     "GNUTLS.DigestInfo",
+                                     &dinfo)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  /* Write an ASN.1 NULL in the parameters field.  This matches RFC
+     3279 and RFC 4055, although is arguable incorrect from a historic
+     perspective (see those documents for more information).
+     Regardless of what is correct, this appears to be what most
+     implementations do.  */
+  result = asn1_write_value (dinfo, "digestAlgorithm.parameters",
+                             ASN1_NULL, ASN1_NULL_SIZE);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  tmp_output_size = 0;
+  asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL);
+
+  tmp_output = gnutls_malloc (tmp_output_size);
+  if (tmp_output == NULL)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  asn1_delete_structure (&dinfo);
+
+  output->size = tmp_output_size;
+  output->data = tmp_output;
+
+  return 0;
+}
+
+/* Reads the digest information.
+ * we use DER here, although we should use BER. It works fine
+ * anyway.
+ */
+int
+decode_ber_digest_info (const gnutls_datum_t * info,
+                        gnutls_digest_algorithm_t * hash,
+                        uint8_t * digest, unsigned int *digest_size)
+{
+  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
+  int result;
+  char str[1024];
+  int len;
+
+  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
+                                     "GNUTLS.DigestInfo",
+                                     &dinfo)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  len = sizeof (str) - 1;
+  result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  *hash = _gnutls_x509_oid_to_digest (str);
+
+  if (*hash == GNUTLS_DIG_UNKNOWN)
+    {
+
+      _gnutls_debug_log ("verify.c: HASH OID: %s\n", str);
+
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return GNUTLS_E_UNKNOWN_ALGORITHM;
+    }
+
+  len = sizeof (str) - 1;
+  result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
+  /* To avoid permitting garbage in the parameters field, either the
+     parameters field is not present, or it contains 0x05 0x00. */
+  if (!(result == ASN1_ELEMENT_NOT_FOUND ||
+        (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
+         memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  len = *digest_size;
+  result = asn1_read_value (dinfo, "digest", digest, &len);
+  
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      *digest_size = len;
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  *digest_size = len;
+  asn1_delete_structure (&dinfo);
+
+  return 0;
+}
+
index 189c61c33382cc86fe549898bf13a8c75b567c4b..ee2b80bf7b94890b6b519ec3527ea0f7b4b388ea 100644 (file)
@@ -33,6 +33,7 @@ extern gnutls_crypto_pk_st _gnutls_pk_ops;
 #define _gnutls_pk_verify_params( algo, params) _gnutls_pk_ops.verify_params( algo, params)
 #define _gnutls_pk_derive( algo, out, pub, priv) _gnutls_pk_ops.derive( algo, out, pub, priv)
 #define _gnutls_pk_generate( algo, bits, priv) _gnutls_pk_ops.generate( algo, bits, priv)
+#define _gnutls_pk_hash_algorithm( pk, sig, params, hash) _gnutls_pk_ops.hash_algorithm(pk, sig, params, hash)
 
 inline static int
 _gnutls_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction,
@@ -46,19 +47,6 @@ _gnutls_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction,
 int _gnutls_pk_params_copy (gnutls_pk_params_st * dst, const gnutls_pk_params_st * src);
 
 /* The internal PK interface */
-int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
-                               const gnutls_datum_t * plaintext,
-                               gnutls_pk_params_st * params,
-                               unsigned btype);
-int _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
-                               const gnutls_datum_t * ciphertext,
-                               gnutls_pk_params_st* params,
-                               unsigned btype);
-int _gnutls_rsa_verify (const gnutls_datum_t * vdata,
-                        const gnutls_datum_t * ciphertext, 
-                        gnutls_pk_params_st*,
-                        int btype);
-
 int
 _gnutls_encode_ber_rs (gnutls_datum_t * sig_value, bigint_t r, bigint_t s);
 
@@ -66,6 +54,16 @@ int
 _gnutls_decode_ber_rs (const gnutls_datum_t * sig_value, bigint_t * r,
                        bigint_t * s);
 
+int
+encode_ber_digest_info (gnutls_digest_algorithm_t hash,
+                        const gnutls_datum_t * digest,
+                        gnutls_datum_t * output);
+
+int
+decode_ber_digest_info (const gnutls_datum_t * info,
+                        gnutls_digest_algorithm_t * hash,
+                        uint8_t * digest, unsigned int *digest_size);
+
 int _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk,
                                    gnutls_pk_params_st*,
                                    gnutls_digest_algorithm_t * dig,
index 9cb820ed565cd3c4041781709a099008427f0882..3b4446350b43bbfdc7d6e5459d0ac8560b9a799c 100644 (file)
@@ -562,7 +562,7 @@ uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
  * together with a hash functions.  Different hash functions may be
  * used for the RSA algorithm, but only the SHA family for the DSA keys.
  *
- * Use gnutls_pubkey_get_preferred_hash_algorithm() to determine
+ * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
  * the hash algorithm.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
@@ -623,7 +623,7 @@ cleanup:
  * together with a hash functions.  Different hash functions may be
  * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
  *
- * Use gnutls_pubkey_get_preferred_hash_algorithm() to determine
+ * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
  * the hash algorithm.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
@@ -701,9 +701,8 @@ _gnutls_privkey_sign_hash (gnutls_privkey_t key,
                                                hash, signature);
 #endif
     case GNUTLS_PRIVKEY_X509:
-      return _gnutls_soft_sign (key->key.x509->pk_algorithm,
-                                &key->key.x509->params,
-                                hash, signature);
+      return _gnutls_pk_sign (key->key.x509->pk_algorithm,
+                              signature, hash, &key->key.x509->params);
     case GNUTLS_PRIVKEY_EXT:
       if (key->key.ext.sign_func == NULL)
         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
@@ -735,23 +734,16 @@ gnutls_privkey_decrypt_data (gnutls_privkey_t key,
                              const gnutls_datum_t * ciphertext,
                              gnutls_datum_t * plaintext)
 {
-  if (key->pk_algorithm != GNUTLS_PK_RSA)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
   switch (key->type)
     {
 #ifdef ENABLE_OPENPGP
     case GNUTLS_PRIVKEY_OPENPGP:
       return _gnutls_openpgp_privkey_decrypt_data (key->key.openpgp, flags,
-                                                  ciphertext, plaintext);
+                                                   ciphertext, plaintext);
 #endif
     case GNUTLS_PRIVKEY_X509:
-      return _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext,
-                                        &key->key.x509->params,
-                                        2);
+      return _gnutls_pk_decrypt (key->pk_algorithm, plaintext, ciphertext,
+                                 &key->key.x509->params);
 #ifdef ENABLE_PKCS11
     case GNUTLS_PRIVKEY_PKCS11:
       return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11,
index 6496537ca727052add09674e022667418c695985..ab7a6672648a9ebc98be91f9e8cd25537f99caf7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * GnuTLS PKCS#11 support
+ * GnuTLS public key support
  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
  * 
  * Author: Nikos Mavrogiannopoulos
@@ -1305,7 +1305,8 @@ gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key,
  * parameters from the certificate.
  *
  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
- * is returned, and zero or positive code on success.
+ * is returned, and zero or positive code on success. Use gnutls_pubkey_verify_data2()
+ * instead of this function.
  *
  * Since: 2.12.0
  **/
@@ -1350,10 +1351,10 @@ gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey, unsigned int flags,
  **/
 int
 gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey, 
-                           gnutls_sign_algorithm_t algo,
-                           unsigned int flags,
-                          const gnutls_datum_t * data,
-                          const gnutls_datum_t * signature)
+                            gnutls_sign_algorithm_t algo,
+                            unsigned int flags,
+                           const gnutls_datum_t * data,
+                           const gnutls_datum_t * signature)
 {
   int ret;
 
@@ -1363,8 +1364,8 @@ gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = pubkey_verify_data( pubkey->pk_algorithm, _gnutls_sign_get_hash_algorithm(algo), data, signature,
-    &pubkey->params);
+  ret = pubkey_verify_data( pubkey->pk_algorithm, _gnutls_sign_get_hash_algorithm(algo), 
+                            data, signature, &pubkey->params);
   if (ret < 0)
     {
       gnutls_assert();
@@ -1382,7 +1383,8 @@ gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey,
  * @signature: contains the signature
  *
  * This function will verify the given signed digest, using the
- * parameters from the public key.
+ * parameters from the public key. Use gnutls_pubkey_verify_hash2()
+ * instead of this function.
  *
  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
  * is returned, and zero or positive code on success.
@@ -1393,6 +1395,40 @@ int
 gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
                            const gnutls_datum_t * hash,
                            const gnutls_datum_t * signature)
+{
+gnutls_digest_algorithm_t algo;
+int ret;
+
+  ret = gnutls_pubkey_get_verify_algorithm (key, signature, &algo);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  return gnutls_pubkey_verify_hash2(key, gnutls_pk_to_sign(key->pk_algorithm, algo),
+                                    flags, hash, signature);
+}
+
+/**
+ * gnutls_pubkey_verify_hash2:
+ * @key: Holds the public key
+ * @algo: The signature algorithm used
+ * @flags: should be 0 for now
+ * @hash: holds the hash digest to be verified
+ * @signature: contains the signature
+ *
+ * This function will verify the given signed digest, using the
+ * parameters from the public key.
+ *
+ * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
+ * is returned, and zero or positive code on success.
+ *
+ * Since: 3.0
+ **/
+int
+gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key, 
+                            gnutls_sign_algorithm_t algo,
+                            unsigned int flags,
+                            const gnutls_datum_t * hash,
+                            const gnutls_datum_t * signature)
 {
   if (key == NULL)
     {
@@ -1401,11 +1437,11 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
     }
 
   if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA)
-    return _gnutls_rsa_verify (hash, signature, &key->params, 1);
+    return _gnutls_pk_verify (GNUTLS_PK_RSA, hash, signature, &key->params);
   else
     {
-      return pubkey_verify_hashed_data (key->pk_algorithm, hash, signature,
-                       &key->params);
+      return pubkey_verify_hashed_data (key->pk_algorithm, _gnutls_sign_get_hash_algorithm(algo),
+                                        hash, signature, &key->params);
     }
 }
 
@@ -1426,18 +1462,17 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
  **/
 int
 gnutls_pubkey_encrypt_data (gnutls_pubkey_t key, unsigned int flags,
-                           const gnutls_datum_t * plaintext,
-                           gnutls_datum_t * ciphertext)
+                            const gnutls_datum_t * plaintext,
+                            gnutls_datum_t * ciphertext)
 {
-  if (key == NULL || key->pk_algorithm != GNUTLS_PK_RSA)
+  if (key == NULL)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  return _gnutls_pkcs1_rsa_encrypt (ciphertext, plaintext,
-                                    &key->params,
-                                    2);
+  return _gnutls_pk_encrypt (key->pk_algorithm, ciphertext, 
+                             plaintext, &key->params);
 }
 
 /**
@@ -1535,48 +1570,24 @@ _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
  * params[1] is public key
  */
 static int
-_pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
+_pkcs1_rsa_verify_sig (gnutls_digest_algorithm_t hash,
+                       const gnutls_datum_t * text,
                        const gnutls_datum_t * prehash,
                        const gnutls_datum_t * signature, 
                        gnutls_pk_params_st * params)
 {
-  gnutls_digest_algorithm_t hash = GNUTLS_DIG_UNKNOWN;
   int ret;
-  uint8_t digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
+  uint8_t md[MAX_HASH_SIZE], *cmp;
   unsigned int digest_size;
+  gnutls_datum_t d, di;
   digest_hd_st hd;
-  gnutls_datum_t decrypted;
 
-  ret =
-    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, 1);
-  if (ret < 0)
+  digest_size = _gnutls_hash_get_algo_len (hash);
+  if (prehash)
     {
-      gnutls_assert ();
-      return ret;
-    }
-
-  /* decrypted is a BER encoded data of type DigestInfo
-   */
-
-  digest_size = sizeof (digest);
-  if ((ret =
-       decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) != 0)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (&decrypted);
-      return ret;
-    }
-
-  _gnutls_free_datum (&decrypted);
-
-  if (digest_size != _gnutls_hash_get_algo_len (hash))
-    {
-      gnutls_assert ();
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
+      if (prehash->data == NULL || prehash->size != digest_size)
+        return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-  if (prehash && prehash->data && prehash->size == digest_size)
-    {
       cmp = prehash->data;
     }
   else
@@ -1599,29 +1610,39 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
 
       cmp = md;
     }
+    
+  d.data = cmp;
+  d.size = digest_size;
 
-  if (memcmp (cmp, digest, digest_size) != 0)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-    }
+  /* decrypted is a BER encoded data of type DigestInfo
+   */
 
-  return 0;
+  ret = encode_ber_digest_info (hash, &d, &di);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  ret = _gnutls_pk_verify (GNUTLS_PK_RSA, &di, signature, params);
+
+  _gnutls_free_datum (&di);
+  
+  return ret;
 }
 
 /* Hashes input data and verifies a signature.
  */
 static int
-dsa_verify_hashed_data (const gnutls_datum_t * hash,
+dsa_verify_hashed_data (gnutls_pk_algorithm_t pk,
+                gnutls_digest_algorithm_t algo,
+                const gnutls_datum_t * hash,
                 const gnutls_datum_t * signature,
-                gnutls_pk_algorithm_t pk,
                 gnutls_pk_params_st* params)
 {
   gnutls_datum_t digest;
-  unsigned int algo;
   unsigned int hash_len;
 
-  algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
+  if (algo == GNUTLS_DIG_UNKNOWN)
+    algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
+  else hash_len = _gnutls_hash_get_algo_len(algo);
 
   /* SHA1 or better allowed */
   if (!hash->data || hash->size < hash_len)
@@ -1672,9 +1693,10 @@ dsa_verify_data (gnutls_pk_algorithm_t pk,
  */
 int
 pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
-                   const gnutls_datum_t * hash,
-                   const gnutls_datum_t * signature,
-                   gnutls_pk_params_st * issuer_params)
+                           gnutls_digest_algorithm_t hash_algo,
+                           const gnutls_datum_t * hash,
+                           const gnutls_datum_t * signature,
+                           gnutls_pk_params_st * issuer_params)
 {
 
   switch (pk)
@@ -1682,7 +1704,7 @@ pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
     case GNUTLS_PK_RSA:
 
       if (_pkcs1_rsa_verify_sig
-          (NULL, hash, signature, issuer_params) != 0)
+          (hash_algo, NULL, hash, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -1693,7 +1715,7 @@ pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
 
     case GNUTLS_PK_EC:
     case GNUTLS_PK_DSA:
-      if (dsa_verify_hashed_data(hash, signature, pk, issuer_params) != 0)
+      if (dsa_verify_hashed_data(pk, hash_algo, hash, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -1713,7 +1735,7 @@ pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
  */
 int
 pubkey_verify_data (gnutls_pk_algorithm_t pk,
-                    gnutls_digest_algorithm_t algo,
+                    gnutls_digest_algorithm_t hash_algo,
                     const gnutls_datum_t * data,
                     const gnutls_datum_t * signature,
                     gnutls_pk_params_st * issuer_params)
@@ -1724,7 +1746,7 @@ pubkey_verify_data (gnutls_pk_algorithm_t pk,
     case GNUTLS_PK_RSA:
 
       if (_pkcs1_rsa_verify_sig
-          (data, NULL, signature, issuer_params) != 0)
+          (hash_algo, data, NULL, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -1735,7 +1757,7 @@ pubkey_verify_data (gnutls_pk_algorithm_t pk,
 
     case GNUTLS_PK_EC:
     case GNUTLS_PK_DSA:
-      if (dsa_verify_data(pk, algo, data, signature, issuer_params) != 0)
+      if (dsa_verify_data(pk, hash_algo, data, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
index afed87ffb0b40c8b45c447b172f20606a6b8f768..c576655e1041de14040f0a7e3a4d65237566bc02 100644 (file)
@@ -45,10 +45,6 @@ sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
                   const gnutls_datum_t * hash_concat,
                   gnutls_datum_t * signature);
 
-static int
-encode_ber_digest_info (gnutls_digest_algorithm_t hash,
-                        const gnutls_datum_t * digest,
-                        gnutls_datum_t * output);
 
 /* While this is currently equal to the length of RSA/SHA512
  * signature, it should also be sufficient for DSS signature and any
@@ -163,41 +159,6 @@ _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_pcert_st* cert,
 
 }
 
-
-/* This will create a PKCS1 or DSA signature, using the given parameters, and the
- * given data. The output will be allocated and be put in signature.
- */
-int
-_gnutls_soft_sign (gnutls_pk_algorithm_t algo, gnutls_pk_params_st * params,
-                   const gnutls_datum_t * data,
-                   gnutls_datum_t * signature)
-{
-  int ret;
-
-  switch (algo)
-    {
-    case GNUTLS_PK_RSA:
-      /* encrypt */
-      if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params, 1)) < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      break;
-    default:
-      ret = _gnutls_pk_sign( algo, signature, data, params);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    }
-
-  return 0;
-}
-
 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
  * Cert is the certificate of the corresponding private key. It is only checked if
  * it supports signing.
@@ -270,9 +231,10 @@ es_cleanup:
 
 static int
 verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert,
-                    const gnutls_datum_t * hash_concat,
-                    gnutls_datum_t * signature, size_t sha1pos,
-                    gnutls_pk_algorithm_t pk_algo)
+                 const gnutls_datum_t * hash_concat,
+                 gnutls_datum_t * signature, size_t sha1pos,
+                 gnutls_sign_algorithm_t sign_algo,
+                 gnutls_pk_algorithm_t pk_algo)
 {
   int ret;
   gnutls_datum_t vdata;
@@ -309,12 +271,9 @@ verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert,
         flags = GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA;
       else
         flags = 0;
-
-
       break;
     case GNUTLS_PK_DSA:
     case GNUTLS_PK_EC:
-
       vdata.data = &hash_concat->data[sha1pos];
       vdata.size = hash_concat->size - sha1pos;
 
@@ -326,8 +285,8 @@ verify_tls_hash (gnutls_protocol_t ver, gnutls_pcert_st* cert,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  ret = gnutls_pubkey_verify_hash(cert->pubkey, flags, &vdata,
-    signature);
+  ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, flags, 
+                                   &vdata, signature);
 
   if (ret < 0)
     return gnutls_assert_val(ret);
@@ -344,7 +303,7 @@ int
 _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert,
                                const gnutls_datum_t * params,
                                gnutls_datum_t * signature,
-                               gnutls_sign_algorithm_t algo)
+                               gnutls_sign_algorithm_t sign_algo)
 {
   gnutls_datum_t dconcat;
   int ret;
@@ -357,17 +316,17 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert,
   if (_gnutls_version_has_selectable_sighash (ver))
     {
       _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n",
-                    session, gnutls_sign_algorithm_get_name (algo));
+                    session, gnutls_sign_algorithm_get_name (sign_algo));
 
-      ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, algo);
+      ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, sign_algo);
       if (ret < 0)
         return gnutls_assert_val(ret);
 
-      ret = _gnutls_session_sign_algo_enabled (session, algo);
+      ret = _gnutls_session_sign_algo_enabled (session, sign_algo);
       if (ret < 0)
         return gnutls_assert_val(ret);
 
-      hash_algo = _gnutls_sign_get_hash_algorithm (algo);
+      hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);
     }
   else
     {
@@ -420,7 +379,8 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert,
   ret = verify_tls_hash (ver, cert, &dconcat, signature,
                             dconcat.size -
                             _gnutls_hash_get_algo_len (hash_algo),
-                            _gnutls_sign_get_pk_algorithm (algo));
+                            sign_algo,
+                            _gnutls_sign_get_pk_algorithm (sign_algo));
   if (ret < 0)
     {
       gnutls_assert ();
@@ -465,7 +425,7 @@ _gnutls_handshake_verify_crt_vrfy12 (gnutls_session_t session,
   dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
 
   ret =
-    verify_tls_hash (ver, cert, &dconcat, signature, 0, pk);
+    verify_tls_hash (ver, cert, &dconcat, signature, 0, sign_algo, pk);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -498,7 +458,7 @@ _gnutls_handshake_verify_crt_vrfy (gnutls_session_t session,
 
   if (_gnutls_version_has_selectable_sighash(ver))
     return _gnutls_handshake_verify_crt_vrfy12 (session, cert, signature,
-                                                 sign_algo);
+                                                sign_algo);
 
   ret =
     _gnutls_hash_init (&td_md5, GNUTLS_DIG_MD5);
@@ -560,7 +520,8 @@ _gnutls_handshake_verify_crt_vrfy (gnutls_session_t session,
 
   ret =
     verify_tls_hash (ver, cert, &dconcat, signature, 16,
-                        gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL));
+                     GNUTLS_SIGN_UNKNOWN,
+                     gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL));
   if (ret < 0)
     {
       gnutls_assert ();
@@ -788,170 +749,3 @@ pk_prepare_hash (gnutls_pk_algorithm_t pk,
   return 0;
 }
 
-/* Reads the digest information.
- * we use DER here, although we should use BER. It works fine
- * anyway.
- */
-int
-decode_ber_digest_info (const gnutls_datum_t * info,
-                        gnutls_digest_algorithm_t * hash,
-                        uint8_t * digest, unsigned int *digest_size)
-{
-  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
-  int result;
-  char str[1024];
-  int len;
-
-  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
-                                     "GNUTLS.DigestInfo",
-                                     &dinfo)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = asn1_der_decoding (&dinfo, info->data, info->size, NULL);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  len = sizeof (str) - 1;
-  result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  *hash = _gnutls_x509_oid_to_digest (str);
-
-  if (*hash == GNUTLS_DIG_UNKNOWN)
-    {
-
-      _gnutls_debug_log ("verify.c: HASH OID: %s\n", str);
-
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return GNUTLS_E_UNKNOWN_ALGORITHM;
-    }
-
-  len = sizeof (str) - 1;
-  result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len);
-  /* To avoid permitting garbage in the parameters field, either the
-     parameters field is not present, or it contains 0x05 0x00. */
-  if (!(result == ASN1_ELEMENT_NOT_FOUND ||
-        (result == ASN1_SUCCESS && len == ASN1_NULL_SIZE &&
-         memcmp (str, ASN1_NULL, ASN1_NULL_SIZE) == 0)))
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  len = *digest_size;
-  result = asn1_read_value (dinfo, "digest", digest, &len);
-  
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      *digest_size = len;
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  *digest_size = len;
-  asn1_delete_structure (&dinfo);
-
-  return 0;
-}
-
-/* Writes the digest information and the digest in a DER encoded
- * structure. The digest info is allocated and stored into the info structure.
- */
-static int
-encode_ber_digest_info (gnutls_digest_algorithm_t hash,
-                        const gnutls_datum_t * digest,
-                        gnutls_datum_t * output)
-{
-  ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
-  int result;
-  const char *algo;
-  uint8_t *tmp_output;
-  int tmp_output_size;
-
-  algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash);
-  if (algo == NULL)
-    {
-      gnutls_assert ();
-      _gnutls_debug_log ("Hash algorithm: %d has no OID\n", hash);
-      return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
-    }
-
-  if ((result = asn1_create_element (_gnutls_get_gnutls_asn (),
-                                     "GNUTLS.DigestInfo",
-                                     &dinfo)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  /* Write an ASN.1 NULL in the parameters field.  This matches RFC
-     3279 and RFC 4055, although is arguable incorrect from a historic
-     perspective (see those documents for more information).
-     Regardless of what is correct, this appears to be what most
-     implementations do.  */
-  result = asn1_write_value (dinfo, "digestAlgorithm.parameters",
-                             ASN1_NULL, ASN1_NULL_SIZE);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  result = asn1_write_value (dinfo, "digest", digest->data, digest->size);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  tmp_output_size = 0;
-  asn1_der_coding (dinfo, "", NULL, &tmp_output_size, NULL);
-
-  tmp_output = gnutls_malloc (tmp_output_size);
-  if (output->data == NULL)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  result = asn1_der_coding (dinfo, "", tmp_output, &tmp_output_size, NULL);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  asn1_delete_structure (&dinfo);
-
-  output->size = tmp_output_size;
-  output->data = tmp_output;
-
-  return 0;
-}
index cd4981d945e22c1d331593849cb588ceac095f07..25ef26a5c20954a59528f9e306a550da43fdbbcd 100644 (file)
@@ -48,11 +48,6 @@ int _gnutls_handshake_verify_data (gnutls_session_t session,
                                    gnutls_datum_t * signature,
                                    gnutls_sign_algorithm_t algo);
 
-int _gnutls_soft_sign (gnutls_pk_algorithm_t algo,
-                       gnutls_pk_params_st* params,
-                       const gnutls_datum_t * data,
-                       gnutls_datum_t * signature);
-
 int pk_prepare_hash (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
                      gnutls_datum_t * output);
 int pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
@@ -64,9 +59,5 @@ _gnutls_privkey_sign_hash (gnutls_privkey_t key,
                            const gnutls_datum_t * hash,
                            gnutls_datum_t * signature);
 
-int
-decode_ber_digest_info (const gnutls_datum_t * info,
-                        gnutls_digest_algorithm_t * hash,
-                        uint8_t * digest, unsigned int *digest_size);
 
 #endif
index b89da86c3074d5a0f8ab05fd47c4b36fef4c30c8..a99c92cb660cfa34dd70368079d30e7113992bd4 100644 (file)
@@ -141,6 +141,13 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
                            const gnutls_datum_t * hash,
                            const gnutls_datum_t * signature);
 int
+gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key, 
+                            gnutls_sign_algorithm_t algo,
+                            unsigned int flags,
+                            const gnutls_datum_t * hash,
+                            const gnutls_datum_t * signature);
+
+int
 gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key,
                                     const gnutls_datum_t * signature,
                                     gnutls_digest_algorithm_t * hash);
index e9d92fd507ee853a51594abaf381e0643eba917e..50cc22df22210261471f7999b00806cd6bb84fcc 100644 (file)
@@ -770,10 +770,11 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
   gnutls_cipher_algorithm_t gnutls_cipher_get (gnutls_session_t session);
   gnutls_kx_algorithm_t gnutls_kx_get (gnutls_session_t session);
   gnutls_mac_algorithm_t gnutls_mac_get (gnutls_session_t session);
-    gnutls_compression_method_t
+  gnutls_compression_method_t
     gnutls_compression_get (gnutls_session_t session);
-    gnutls_certificate_type_t
+  gnutls_certificate_type_t
     gnutls_certificate_type_get (gnutls_session_t session);
+
   int gnutls_sign_algorithm_get_requested (gnutls_session_t session,
                                            size_t indx,
                                            gnutls_sign_algorithm_t * algo);
@@ -791,6 +792,10 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
                                                 type);
   const char *gnutls_pk_get_name (gnutls_pk_algorithm_t algorithm);
   const char *gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm);
+  
+  gnutls_sign_algorithm_t gnutls_pk_to_sign (gnutls_pk_algorithm_t pk,
+                                             gnutls_digest_algorithm_t d);
+
 #define gnutls_sign_algorithm_get_name gnutls_sign_get_name
 
   gnutls_mac_algorithm_t gnutls_mac_get_id (const char *name);
index c7385ad5d18d3e863f63ad3eb9bb1ab6dd7625c6..74986337345d06519c289956b9071012aac9fd09 100644 (file)
@@ -795,6 +795,8 @@ GNUTLS_3_1_0 {
        gnutls_x509_trust_list_add_system_trust;
        gnutls_x509_trust_list_add_trust_file;
        gnutls_x509_trust_list_add_trust_mem;
+       gnutls_pubkey_verify_hash2;
+       gnutls_pk_to_sign;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
index d7e9a057cc42d05e83899a1ad5891dc1ed31bf4f..5932188c6d6c3ec0d7030d8f17992fc25ded102e 100644 (file)
@@ -30,6 +30,7 @@
 #include <gnutls_errors.h>
 #include <gnutls_datum.h>
 #include <gnutls_global.h>
+#include <gnutls_sig.h>
 #include <gnutls_num.h>
 #include <x509/x509_int.h>
 #include <x509/common.h>
@@ -78,7 +79,16 @@ _rsa_params_to_privkey (const gnutls_pk_params_st * pk_params,
   memcpy (&priv->c, pk_params->params[5], sizeof (mpz_t));
   memcpy (&priv->a, pk_params->params[6], sizeof (mpz_t));
   memcpy (&priv->b, pk_params->params[7], sizeof (mpz_t));
+  priv->size = nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[RSA_MODULUS]));
+}
 
+static void
+_rsa_params_to_pubkey (const gnutls_pk_params_st * pk_params,
+                       struct rsa_public_key *pub)
+{
+  memcpy (&pub->n, pk_params->params[RSA_MODULUS], sizeof (mpz_t));
+  memcpy (&pub->e, pk_params->params[RSA_PUB], sizeof (mpz_t));
+  pub->size = nettle_mpz_sizeinbase_256_u(pub->n);
 }
 
 static void 
@@ -192,25 +202,26 @@ _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
                          const gnutls_pk_params_st * pk_params)
 {
   int ret;
+  mpz_t p;
+        
+  mpz_init(p);
 
   switch (algo)
     {
     case GNUTLS_PK_RSA:
       {
-        bigint_t p;
+        struct rsa_public_key pub;
+        
+        _rsa_params_to_pubkey (pk_params, &pub);
 
-        if (_gnutls_mpi_scan_nz (&p, plaintext->data, plaintext->size) != 0)
+        ret = rsa_encrypt(&pub, NULL, rnd_func, plaintext->size, plaintext->data, p);
+        if (ret == 0)
           {
-            gnutls_assert ();
-            return GNUTLS_E_MPI_SCAN_FAILED;
+            ret = gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
+            goto cleanup;
           }
 
-        mpz_powm (p, p, TOMPZ (pk_params->params[1]) /*e */ ,
-                  TOMPZ (pk_params->params[0] /*m */ ));
-
         ret = _gnutls_mpi_dprint_size (p, ciphertext, plaintext->size);
-        _gnutls_mpi_release (&p);
-
         if (ret < 0)
           {
             gnutls_assert ();
@@ -229,74 +240,10 @@ _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
 
 cleanup:
 
+  mpz_clear(p);
   return ret;
 }
 
-/* returns the blinded c and the inverse of a random
- * number r;
- */
-static bigint_t
-rsa_blind (bigint_t c, bigint_t e, bigint_t n, bigint_t * _ri)
-{
-  bigint_t nc = NULL, r = NULL, ri = NULL;
-
-  /* nc = c*(r^e)
-   * ri = r^(-1)
-   */
-  nc = _gnutls_mpi_alloc_like (n);
-  if (nc == NULL)
-    {
-      gnutls_assert ();
-      return NULL;
-    }
-
-  ri = _gnutls_mpi_alloc_like (n);
-  if (nc == NULL)
-    {
-      gnutls_assert ();
-      goto fail;
-    }
-
-  r = _gnutls_mpi_randomize (NULL, _gnutls_mpi_get_nbits (n),
-                             GNUTLS_RND_NONCE);
-  if (r == NULL)
-    {
-      gnutls_assert ();
-      goto fail;
-    }
-
-  /* invert r */
-  if (mpz_invert (ri, r, n) == 0)
-    {
-      gnutls_assert ();
-      goto fail;
-    }
-
-  /* r = r^e */
-
-  _gnutls_mpi_powm (r, r, e, n);
-
-  _gnutls_mpi_mulm (nc, c, r, n);
-
-  *_ri = ri;
-
-  _gnutls_mpi_release (&r);
-
-  return nc;
-fail:
-  _gnutls_mpi_release (&nc);
-  _gnutls_mpi_release (&r);
-  return NULL;
-}
-
-/* c = c*ri mod n
- */
-static inline void
-rsa_unblind (bigint_t c, bigint_t ri, bigint_t n)
-{
-  _gnutls_mpi_mulm (c, c, ri, n);
-}
-
 static int
 _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo,
                          gnutls_datum_t * plaintext,
@@ -305,44 +252,44 @@ _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo,
 {
   int ret;
 
+  plaintext->data = NULL;
+
   /* make a sexp from pkey */
   switch (algo)
     {
     case GNUTLS_PK_RSA:
       {
         struct rsa_private_key priv;
-        bigint_t c, ri, nc;
+        struct rsa_public_key pub;
+        unsigned length;
+        bigint_t c;
+
+        memset(&priv, 0, sizeof(priv));
+        _rsa_params_to_privkey (pk_params, &priv);
+        _rsa_params_to_pubkey (pk_params, &pub);
 
         if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0)
           {
-            gnutls_assert ();
-            return GNUTLS_E_MPI_SCAN_FAILED;
+            ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED);
+            goto cleanup;
           }
 
-        nc = rsa_blind (c, pk_params->params[1] /*e */ ,
-                        pk_params->params[0] /*m */ , &ri);
-        _gnutls_mpi_release (&c);
-        if (nc == NULL)
+        length = pub.size;
+        plaintext->data = gnutls_malloc(length);
+        if (plaintext->data == NULL)
           {
-            gnutls_assert ();
-            return GNUTLS_E_MEMORY_ERROR;
+            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+            goto cleanup;
           }
+        
+        ret = rsa_decrypt_tr(&pub, &priv, NULL, rnd_func, &length, plaintext->data,
+                             TOMPZ(c));
+        _gnutls_mpi_release (&c);
+        plaintext->size = length;
 
-        memset(&priv, 0, sizeof(priv));
-        _rsa_params_to_privkey (pk_params, &priv);
-
-        rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc));
-
-        rsa_unblind (nc, ri, pk_params->params[0] /*m */ );
-
-        ret = _gnutls_mpi_dprint_size (nc, plaintext, ciphertext->size);
-
-        _gnutls_mpi_release (&nc);
-        _gnutls_mpi_release (&ri);
-
-        if (ret < 0)
+        if (ret == 0)
           {
-            gnutls_assert ();
+            ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
             goto cleanup;
           }
 
@@ -357,6 +304,8 @@ _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo,
   ret = 0;
 
 cleanup:
+  if (ret < 0)
+    gnutls_free(plaintext->data);
 
   return ret;
 }
@@ -460,38 +409,25 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
     case GNUTLS_PK_RSA:
       {
         struct rsa_private_key priv;
-        bigint_t hash, nc, ri;
-
-        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
-          {
-            gnutls_assert ();
-            return GNUTLS_E_MPI_SCAN_FAILED;
-          }
+        mpz_t s;
 
         memset(&priv, 0, sizeof(priv));
         _rsa_params_to_privkey (pk_params, &priv);
-
-        nc = rsa_blind (hash, pk_params->params[1] /*e */ ,
-                        pk_params->params[0] /*m */ , &ri);
-
-        _gnutls_mpi_release (&hash);
-
-        if (nc == NULL)
+        
+        mpz_init(s);
+// XXX change with _tr
+        ret = rsa_pkcs1_sign(&priv, vdata->size, vdata->data, s);
+        if (ret == 0)
           {
-            gnutls_assert ();
-            ret = GNUTLS_E_MEMORY_ERROR;
+            gnutls_assert();
+            ret = GNUTLS_E_PK_SIGN_FAILED;
             goto rsa_fail;
           }
 
-        rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc));
-
-        rsa_unblind (nc, ri, pk_params->params[0] /*m */ );
-
-        ret = _gnutls_mpi_dprint (nc, signature);
+        ret = _gnutls_mpi_dprint (s, signature);
 
 rsa_fail:
-        _gnutls_mpi_release (&nc);
-        _gnutls_mpi_release (&ri);
+        mpz_clear(s);
 
         if (ret < 0)
           {
@@ -514,35 +450,6 @@ cleanup:
   return ret;
 }
 
-static int
-_int_rsa_verify (const gnutls_pk_params_st * pk_params,
-                 bigint_t m, bigint_t s)
-{
-  int res;
-
-  mpz_t m1;
-
-  if ((mpz_sgn (TOMPZ (s)) <= 0)
-      || (mpz_cmp (TOMPZ (s), TOMPZ (pk_params->params[0])) >= 0))
-    return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-
-  mpz_init (m1);
-
-  mpz_powm (m1, TOMPZ (s), TOMPZ (pk_params->params[1]),
-            TOMPZ (pk_params->params[0]));
-
-  res = !mpz_cmp (TOMPZ (m), m1);
-
-  mpz_clear (m1);
-
-  if (res == 0)
-    res = GNUTLS_E_PK_SIG_VERIFY_FAILED;
-  else
-    res = 0;
-
-  return res;
-}
-
 static int
 _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
                         const gnutls_datum_t * vdata,
@@ -625,13 +532,9 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
       }
     case GNUTLS_PK_RSA:
       {
-        bigint_t hash;
-
-        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
-          {
-            gnutls_assert ();
-            return GNUTLS_E_MPI_SCAN_FAILED;
-          }
+        struct rsa_public_key pub;
+        
+        _rsa_params_to_pubkey (pk_params, &pub);
 
         ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size);
         if (ret < 0)
@@ -640,9 +543,12 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
             goto cleanup;
           }
 
-        ret = _int_rsa_verify (pk_params, hash, tmp[0]);
+        ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0]));
+        if (ret == 0) 
+          ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+        else ret = 0;
+        
         _gnutls_mpi_release (&tmp[0]);
-        _gnutls_mpi_release (&hash);
         break;
       }
     default:
@@ -1077,9 +983,91 @@ wrap_nettle_pk_fixup (gnutls_pk_algorithm_t algo,
   return 0;
 }
 
+static int wrap_nettle_hash_algorithm (gnutls_pk_algorithm_t pk, 
+    const gnutls_datum_t * sig, gnutls_pk_params_st * issuer_params,
+    gnutls_digest_algorithm_t* hash_algo)
+{
+  uint8_t digest[MAX_HASH_SIZE];
+  uint8_t digest_info[MAX_HASH_SIZE*3];
+  gnutls_datum_t di;
+  unsigned digest_size;
+  mpz_t s;
+  struct rsa_public_key pub;
+  int ret;
+
+  mpz_init(s);
+
+  switch (pk)
+    {
+    case GNUTLS_PK_DSA:
+    case GNUTLS_PK_EC:
+
+      if (hash_algo)
+        *hash_algo = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL);
+
+      ret = 0;
+      break;
+    case GNUTLS_PK_RSA:
+      if (sig == NULL)
+        {                       /* return a sensible algorithm */
+          if (hash_algo)
+            *hash_algo = GNUTLS_DIG_SHA256;
+          return 0;
+        }
+
+      _rsa_params_to_pubkey (issuer_params, &pub);
+
+      digest_size = sizeof(digest);
+      
+      nettle_mpz_set_str_256_u(s, sig->size, sig->data);
+      
+      digest_size = sizeof (digest_info);
+      ret = rsa_pkcs1_sign_extract_digest_info( &pub, &digest_size, digest_info, s);
+      if (ret == 0)
+        {
+          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
+          gnutls_assert ();
+          goto cleanup;
+        }
+
+      di.data = digest_info;
+      di.size = digest_size;
+      
+      digest_size = sizeof(digest);
+      if ((ret =
+           decode_ber_digest_info (&di, hash_algo, digest,
+                                   &digest_size)) < 0)
+        {
+          gnutls_assert ();
+          goto cleanup;
+        }
+
+      if (digest_size != _gnutls_hash_get_algo_len (*hash_algo))
+        {
+          gnutls_assert ();
+          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
+          goto cleanup;
+        }
+
+      ret = 0;
+      break;
+
+    default:
+      gnutls_assert ();
+      ret = GNUTLS_E_INTERNAL_ERROR;
+    }
+
+cleanup:
+  mpz_clear(s);
+  return ret;
+
+}
+
+
 int crypto_pk_prio = INT_MAX;
 
 gnutls_crypto_pk_st _gnutls_pk_ops = {
+  .hash_algorithm = wrap_nettle_hash_algorithm,
   .encrypt = _wrap_nettle_pk_encrypt,
   .decrypt = _wrap_nettle_pk_decrypt,
   .sign = _wrap_nettle_pk_sign,
index e786fe67c21a404beb00b0843bb8704887f0f708..72bf7a9901bb935a7e838f7961c397abed13f84b 100644 (file)
@@ -121,10 +121,6 @@ void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node);
 void _cdk_kbnode_clone (cdk_kbnode_t node);
 
 /*-- sesskey.c --*/
-cdk_error_t _cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen,
-                                      int pk_algo,
-                                      const byte * md,
-                                      int digest_algo, unsigned nbits);
 cdk_error_t _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk);
 
 /*-- keydb.c --*/
index ab3d47cec0744abadff24e2648ad4d0bcf3f031e..492a0f2ef3066de6020bf9547fa908f6db4b4552 100644 (file)
@@ -26,6 +26,7 @@
 #include <gnutls_int.h>
 #include <gnutls_datum.h>
 #include <gnutls_pk.h>
+#include <gnutls_sig.h>
 #include <x509/common.h>
 #include "opencdk.h"
 #include "main.h"
@@ -72,13 +73,12 @@ sig_to_datum (gnutls_datum_t * r_sig, cdk_pkt_signature_t sig)
 cdk_error_t
 cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
 {
-  gnutls_datum_t s_sig;
+  gnutls_datum_t s_sig = { NULL, 0}, di = {NULL, 0};
   byte *encmd = NULL;
   size_t enclen;
   cdk_error_t rc;
   int ret, algo;
   unsigned int i;
-  gnutls_datum_t data;
   gnutls_pk_params_st params;
 
   if (!pk || !sig || !md)
@@ -104,22 +104,25 @@ cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
       goto leave;
     }
 
-  rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
-                                 sig->digest_algo, cdk_pk_get_nbits (pk));
-  if (rc)
+  rc = _gnutls_set_datum (&di, md, _gnutls_hash_get_algo_len (sig->digest_algo));
+  if (rc < 0)
     {
-      gnutls_assert ();
+      rc = gnutls_assert_val(CDK_Out_Of_Core);
       goto leave;
-    }
+    }  
 
-  data.data = encmd;
-  data.size = enclen;
+  rc = pk_prepare_hash (algo, sig->digest_algo, &di);
+  if (rc < 0)
+    {
+      rc = gnutls_assert_val(CDK_General_Error);
+      goto leave;
+    }
 
   params.params_nr = cdk_pk_get_npkey (pk->pubkey_algo);
   for (i = 0; i < params.params_nr; i++)
     params.params[i] = pk->mpi[i];
   params.flags = 0;
-  ret = _gnutls_pk_verify (algo, &data, &s_sig, &params);
+  ret = _gnutls_pk_verify (algo, &di, &s_sig, &params);
 
   if (ret < 0)
     {
@@ -132,6 +135,7 @@ cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
 
 leave:
   _gnutls_free_datum (&s_sig);
+  _gnutls_free_datum (&di);
   cdk_free (encmd);
   return rc;
 }
index 09863bf2b98a8d471c0791be3458b7b98e72878f..8d1d929211f04383cadb39b8b29996bbbaf5f676 100644 (file)
 #include "main.h"
 #include "packet.h"
 
-
-/* We encode the MD in this way:
- *
- * 0  1 PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
-static cdk_error_t
-do_encode_md (byte ** r_frame, size_t * r_flen, const byte * md, int algo,
-              size_t len, unsigned nbits, const byte * asn, size_t asnlen)
-{
-  byte *frame = NULL;
-  size_t nframe = (nbits + 7) / 8;
-  ssize_t i;
-  size_t n = 0;
-
-  if (!asn || !md || !r_frame || !r_flen)
-    return CDK_Inv_Value;
-
-  if (len + asnlen + 4 > nframe)
-    return CDK_General_Error;
-
-  frame = cdk_calloc (1, nframe);
-  if (!frame)
-    return CDK_Out_Of_Core;
-  frame[n++] = 0;
-  frame[n++] = 1;
-  i = nframe - len - asnlen - 3;
-  if (i < 0)
-    {
-      cdk_free (frame);
-      return CDK_Inv_Value;
-    }
-  memset (frame + n, 0xFF, i);
-  n += i;
-  frame[n++] = 0;
-  memcpy (frame + n, asn, asnlen);
-  n += asnlen;
-  memcpy (frame + n, md, len);
-  n += len;
-  if (n != nframe)
-    {
-      cdk_free (frame);
-      return CDK_Inv_Value;
-    }
-  *r_frame = frame;
-  *r_flen = n;
-  return 0;
-}
-
-static const byte md5_asn[18] = /* Object ID is 1.2.840.113549.2.5 */
-{ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
-  0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
-};
-
-static const byte sha1_asn[15] =        /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
-  0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-static const byte sha224_asn[19] =      /* Object ID is 2.16.840.1.101.3.4.2.4 */
-{ 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
-  0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
-  0x1C
-};
-
-static const byte sha256_asn[19] =      /* Object ID is  2.16.840.1.101.3.4.2.1 */
-{ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
-  0x00, 0x04, 0x20
-};
-
-static const byte sha512_asn[] =        /* Object ID is 2.16.840.1.101.3.4.2.3 */
-{
-  0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
-  0x00, 0x04, 0x40
-};
-
-static const byte sha384_asn[] =        /* Object ID is 2.16.840.1.101.3.4.2.2 */
-{
-  0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
-  0x00, 0x04, 0x30
-};
-
-static const byte rmd160_asn[15] =      /* Object ID is 1.3.36.3.2.1 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
-  0x02, 0x01, 0x05, 0x00, 0x04, 0x14
-};
-
-static int
-_gnutls_get_digest_oid (gnutls_digest_algorithm_t algo, const byte ** data)
-{
-  switch (algo)
-    {
-    case GNUTLS_DIG_MD5:
-      *data = md5_asn;
-      return sizeof (md5_asn);
-    case GNUTLS_DIG_SHA1:
-      *data = sha1_asn;
-      return sizeof (sha1_asn);
-    case GNUTLS_DIG_RMD160:
-      *data = rmd160_asn;
-      return sizeof (rmd160_asn);
-    case GNUTLS_DIG_SHA256:
-      *data = sha256_asn;
-      return sizeof (sha256_asn);
-    case GNUTLS_DIG_SHA384:
-      *data = sha384_asn;
-      return sizeof (sha384_asn);
-    case GNUTLS_DIG_SHA512:
-      *data = sha512_asn;
-      return sizeof (sha512_asn);
-    case GNUTLS_DIG_SHA224:
-      *data = sha224_asn;
-      return sizeof (sha224_asn);
-    default:
-      gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
-    }
-}
-
-
-/* Encode the given digest into a pkcs#1 compatible format. */
-cdk_error_t
-_cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
-                          const byte * md, int digest_algo, unsigned nbits)
-{
-  size_t dlen;
-
-  if (!md || !r_md || !r_mdlen)
-    return CDK_Inv_Value;
-
-  dlen = _gnutls_hash_get_algo_len (digest_algo);
-  if (dlen <= 0)
-    return CDK_Inv_Algo;
-  if (is_DSA (pk_algo))
-    {                           /* DSS does not use a special encoding. */
-      *r_md = cdk_malloc (dlen + 1);
-      if (!*r_md)
-        return CDK_Out_Of_Core;
-      *r_mdlen = dlen;
-      memcpy (*r_md, md, dlen);
-      return 0;
-    }
-  else
-    {
-      const byte *asn;
-      int asnlen;
-      cdk_error_t rc;
-
-      asnlen = _gnutls_get_digest_oid (digest_algo, &asn);
-      if (asnlen < 0)
-        return asnlen;
-
-      rc = do_encode_md (r_md, r_mdlen, md, digest_algo, dlen,
-                         nbits, asn, asnlen);
-      return rc;
-    }
-  return 0;
-}
-
-
 /**
  * cdk_s2k_new:
  * @ret_s2k: output for the new S2K object
index 9be87b02069cf043cdd909f41665bde25cbc7441..8870ef670737f312acb324531bb4c5789d93ee8f 100644 (file)
@@ -1281,7 +1281,7 @@ gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
 
 
   result =
-    _gnutls_soft_sign (pk_algorithm, &params, hash, signature);
+    _gnutls_pk_sign (pk_algorithm, signature, hash, &params);
 
   gnutls_pk_params_release(&params);
 
@@ -1351,22 +1351,12 @@ _gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key,
       return result;
     }
 
-  if (pk_algorithm != GNUTLS_PK_RSA)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  result =
-    _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, &params, 2);
+  result = _gnutls_pk_decrypt (pk_algorithm, plaintext, ciphertext, &params);
 
   gnutls_pk_params_release(&params);
 
   if (result < 0)
-    {
-      gnutls_assert ();
-      return result;
-    }
+    return gnutls_assert_val(result);
 
   return 0;
 }
index 4d622ccb6edec48debd9aec1b23df91e1257eae1..5f9496b365d03e1c24f209279329ad9dfa02d919 100644 (file)
@@ -1476,8 +1476,7 @@ _gnutls_x509_privkey_sign_hash2 (gnutls_x509_privkey_t signer,
       goto cleanup;
     }
 
-  ret = _gnutls_soft_sign (signer->pk_algorithm, &signer->params,
-                           &digest, signature);
+  ret = _gnutls_pk_sign (signer->pk_algorithm, signature, &digest, &signer->params);
 
   if (ret < 0)
     {
@@ -1521,8 +1520,8 @@ gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_soft_sign (key->pk_algorithm, &key->params,
-                              hash, signature);
+  result = _gnutls_pk_sign (key->pk_algorithm, signature, hash, &key->params);
+
   if (result < 0)
     {
       gnutls_assert ();
index 4a133d451e40ea2b25494689c0539aa338eb8ce2..ee520e45e6de533126ecac035236a3e1f6023bde 100644 (file)
@@ -682,70 +682,7 @@ _gnutls_x509_verify_algorithm (gnutls_digest_algorithm_t * hash,
                                gnutls_pk_algorithm_t pk,
                                gnutls_pk_params_st * issuer_params)
 {
-  uint8_t digest[MAX_HASH_SIZE];
-  gnutls_datum_t decrypted;
-  unsigned int digest_size;
-  int ret;
-
-  switch (pk)
-    {
-    case GNUTLS_PK_DSA:
-    case GNUTLS_PK_EC:
-
-      if (hash)
-        *hash = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL);
-
-      ret = 0;
-      break;
-    case GNUTLS_PK_RSA:
-      if (signature == NULL)
-        {                       /* return a sensible algorithm */
-          if (hash)
-            *hash = GNUTLS_DIG_SHA256;
-          return 0;
-        }
-
-      ret =
-        _gnutls_pkcs1_rsa_decrypt (&decrypted, signature,
-                                   issuer_params, 1);
-
-
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
-
-      digest_size = sizeof (digest);
-      if ((ret =
-           decode_ber_digest_info (&decrypted, hash, digest,
-                                   &digest_size)) != 0)
-        {
-          gnutls_assert ();
-          _gnutls_free_datum (&decrypted);
-          goto cleanup;
-        }
-
-      _gnutls_free_datum (&decrypted);
-      if (digest_size != _gnutls_hash_get_algo_len (*hash))
-        {
-          gnutls_assert ();
-          ret = GNUTLS_E_ASN1_GENERIC_ERROR;
-          goto cleanup;
-        }
-
-      ret = 0;
-      break;
-
-    default:
-      gnutls_assert ();
-      ret = GNUTLS_E_INTERNAL_ERROR;
-    }
-
-cleanup:
-
-  return ret;
-
+  return _gnutls_pk_hash_algorithm(pk, signature, issuer_params, hash);
 }
 
 /* verifies if the certificate is properly signed.
@@ -788,39 +725,6 @@ _gnutls_x509_verify_data (gnutls_digest_algorithm_t algo,
   return ret;
 }
 
-int
-_gnutls_x509_verify_hashed_data (const gnutls_datum_t * hash,
-                                 const gnutls_datum_t * signature,
-                                 gnutls_x509_crt_t issuer)
-{
-  gnutls_pk_params_st issuer_params;
-  int ret;
-
-  /* Read the MPI parameters from the issuer's certificate.
-   */
-  ret =
-    _gnutls_x509_crt_get_mpis (issuer, &issuer_params);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  ret =
-    pubkey_verify_hashed_data (gnutls_x509_crt_get_pk_algorithm (issuer, NULL),
-                               hash, signature, &issuer_params);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-    }
-
-  /* release all allocated MPIs
-   */
-  gnutls_pk_params_release(&issuer_params);
-
-  return ret;
-}
-
 /**
  * gnutls_x509_crt_list_verify:
  * @cert_list: is the certificate list to be verified
index e69bab63694afa0aa07b4443458b18ab17d18a2c..c8b0cec0b0b3a3e03160f14ea1f930ffe49df0d5 100644 (file)
@@ -2703,7 +2703,9 @@ gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, unsigned int flags,
                              const gnutls_datum_t * hash,
                              const gnutls_datum_t * signature)
 {
-  int result;
+  gnutls_pk_params_st params;
+  gnutls_digest_algorithm_t algo;
+  int ret;
 
   if (crt == NULL)
     {
@@ -2711,14 +2713,33 @@ gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_x509_verify_hashed_data (hash, signature, crt);
-  if (result < 0)
+  ret = gnutls_x509_crt_get_verify_algorithm (crt, signature, &algo);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  /* Read the MPI parameters from the issuer's certificate.
+   */
+  ret =
+    _gnutls_x509_crt_get_mpis (crt, &params);
+  if (ret < 0)
     {
       gnutls_assert ();
-      return result;
+      return ret;
     }
 
-  return result;
+  ret =
+    pubkey_verify_hashed_data (gnutls_x509_crt_get_pk_algorithm (crt, NULL), algo,
+                               hash, signature, &params);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+    }
+
+  /* release all allocated MPIs
+   */
+  gnutls_pk_params_release(&params);
+
+  return ret;
 }
 
 /**
index 19c2c1238bfcadb7326d7f04b5123a4715046cf4..3cc18e4bb0a2ef7f63c7bbda7ca106728e02296f 100644 (file)
@@ -151,10 +151,6 @@ int _gnutls_x509_verify_data (gnutls_digest_algorithm_t algo,
                               const gnutls_datum_t * signature,
                               gnutls_x509_crt_t issuer);
 
-int _gnutls_x509_verify_hashed_data (const gnutls_datum_t * hash,
-                                     const gnutls_datum_t * signature,
-                                     gnutls_x509_crt_t issuer);
-
 /* privkey.h */
 ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t *
                                                 raw_key,
index 9ac6b5d46653cea4e8bf9812c362e481195d4da7..7e0727cf1fd125e1af164bd87b04edd96b4fb541 100644 (file)
 
 #include "utils.h"
 
+static void
+tls_log_func (int level, const char *str)
+{
+  fprintf (stderr, "<%d> %s", level, str);
+}
+
 /* sha1 hash of "hello" string */
 const gnutls_datum_t hash_data = {
   (void *)
@@ -147,6 +153,7 @@ doit (void)
   gnutls_pubkey_t pubkey;
   gnutls_privkey_t privkey;
   gnutls_digest_algorithm_t hash_algo;
+  gnutls_sign_algorithm_t sign_algo;
   gnutls_datum_t signature;
   gnutls_datum_t signature2;
   int ret;
@@ -154,6 +161,10 @@ doit (void)
 
   gnutls_global_init ();
 
+  gnutls_global_set_log_function (tls_log_func);
+  if (debug)
+    gnutls_global_set_log_level (6);
+
   for (i = 0; i < sizeof (key_dat) / sizeof (key_dat[0]); i++)
     {
       if (debug)
@@ -210,7 +221,7 @@ doit (void)
 
       ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature);
       if (ret < 0)
-        fail ("gnutls_x509_privkey_verify_hash\n");
+        fail ("gnutls_x509_pubkey_verify_hash\n");
 
       ret =
         gnutls_pubkey_get_verify_algorithm (pubkey, &signature2, &hash_algo);
@@ -219,12 +230,24 @@ doit (void)
 
       ret = gnutls_pubkey_verify_hash (pubkey, 0, &hash_data, &signature2);
       if (ret < 0)
-        fail ("gnutls_x509_privkey_verify_hash (hashed data)\n");
+        fail ("gnutls_x509_pubkey_verify_hash-1 (hashed data)\n");
 
       /* should fail */
       ret = gnutls_pubkey_verify_hash (pubkey, 0, &invalid_hash_data, &signature2);
       if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
-        fail ("gnutls_x509_privkey_verify_hash (hashed data)\n");
+        fail ("gnutls_x509_pubkey_verify_hash-2 (hashed data)\n");
+        
+      sign_algo = gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm(pubkey, NULL),
+                                    GNUTLS_DIG_SHA1);
+
+      ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &hash_data, &signature2);
+      if (ret < 0)
+        fail ("gnutls_x509_pubkey_verify_hash2-1 (hashed data)\n");
+
+      /* should fail */
+      ret = gnutls_pubkey_verify_hash2 (pubkey, sign_algo, 0, &invalid_hash_data, &signature2);
+      if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
+        fail ("gnutls_x509_pubkey_verify_hash2-2 (hashed data)\n");
 
 
       gnutls_free(signature.data);