]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Split pubkey_verify_sig() to pubkey_verify_hashed_data() and pubkey_verify_data().
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 4 Jun 2011 06:51:11 +0000 (08:51 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 4 Jun 2011 06:59:45 +0000 (08:59 +0200)
Added gnutls_pubkey_verify_data2() to allow verification of a signature when the
signature algorithm cannot be determined by the signature and the public key only.

14 files changed:
lib/abstract_int.h
lib/gnutls_pubkey.c
lib/gnutls_sig.c
lib/gnutls_sig.h
lib/includes/gnutls/abstract.h
lib/includes/gnutls/compat.h
lib/libgnutls.map
lib/x509/common.c
lib/x509/common.h
lib/x509/crq.c
lib/x509/privkey.c
lib/x509/verify.c
lib/x509/x509.c
lib/x509/x509_int.h

index 106067979743e4e380d55857d6f709edc8537dae..06318d3791f90a5c4359c73f0437aedf7b8b69c8 100644 (file)
@@ -14,4 +14,20 @@ 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_data (gnutls_pk_algorithm_t pk,
+                        gnutls_digest_algorithm_t algo,
+                       const gnutls_datum_t * data,
+                       const gnutls_datum_t * signature,
+                       gnutls_pk_params_st * issuer_params);
+
+
+
+gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, 
+  const gnutls_pk_params_st* params, int* hash_len);
+
 #endif
index 5dddae2b1cce8596604a76f10a41c5e6c76e5750..6352bbbeed7334cdc1078179f962defc9809301f 100644 (file)
@@ -30,6 +30,7 @@
 #include <gnutls_datum.h>
 #include <pkcs11_int.h>
 #include <gnutls/abstract.h>
+#include <gnutls_sig.h>
 #include <gnutls_pk.h>
 #include <x509_int.h>
 #include <openpgp/openpgp_int.h>
@@ -1119,7 +1120,49 @@ gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = pubkey_verify_sig( data, NULL, signature, pubkey->pk_algorithm, 
+  ret = pubkey_verify_data( pubkey->pk_algorithm, GNUTLS_DIG_UNKNOWN, data, signature,
+    &pubkey->params);
+  if (ret < 0)
+    {
+      gnutls_assert();
+    }
+
+  return ret;
+}
+
+/**
+ * gnutls_pubkey_verify_data2:
+ * @pubkey: Holds the public key
+ * @algo: The signature algorithm used
+ * @flags: should be 0 for now
+ * @data: holds the signed data
+ * @signature: contains the signature
+ *
+ * This function will verify the given signed data, using the
+ * parameters from the certificate.
+ *
+ * Returns: In case of a verification failure
+ *   %GNUTLS_E_PK_SIG_VERIFY_FAILED is returned, and a positive code
+ *   on success.
+ *
+ * Since: 2.12.0
+ **/
+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)
+{
+  int ret;
+
+  if (pubkey == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  ret = pubkey_verify_data( pubkey->pk_algorithm, _gnutls_sign_get_hash_algorithm(algo), data, signature,
     &pubkey->params);
   if (ret < 0)
     {
@@ -1158,7 +1201,7 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
     return _gnutls_rsa_verify (hash, signature, &key->params, 1);
   else
     {
-      return pubkey_verify_sig (NULL, hash, signature, key->pk_algorithm,
+      return pubkey_verify_hashed_data (key->pk_algorithm, hash, signature,
                        &key->params);
     }
 }
@@ -1250,3 +1293,266 @@ _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
 {
   return _gnutls_pk_params_copy(params, &key->params);
 }
+
+/* if hash==MD5 then we do RSA-MD5
+ * if hash==SHA then we do RSA-SHA
+ * params[0] is modulus
+ * params[1] is public key
+ */
+static int
+_pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
+                       const gnutls_datum_t * prehash,
+                       const gnutls_datum_t * signature, 
+                       gnutls_pk_params_st * params)
+{
+  gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
+  int ret;
+  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
+  int digest_size;
+  digest_hd_st hd;
+  gnutls_datum_t decrypted;
+
+  ret =
+    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, 1);
+  if (ret < 0)
+    {
+      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 && prehash->data && prehash->size == digest_size)
+    {
+      cmp = prehash->data;
+    }
+  else
+    {
+      if (!text)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_INVALID_REQUEST;
+        }
+
+      ret = _gnutls_hash_init (&hd, hash);
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          return ret;
+        }
+
+      _gnutls_hash (&hd, text->data, text->size);
+      _gnutls_hash_deinit (&hd, md);
+
+      cmp = md;
+    }
+
+  if (memcmp (cmp, digest, digest_size) != 0)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+    }
+
+  return 0;
+}
+
+/* Hashes input data and verifies a signature.
+ */
+static int
+dsa_verify_hashed_data (const gnutls_datum_t * hash,
+                const gnutls_datum_t * signature,
+                gnutls_pk_algorithm_t pk,
+                gnutls_pk_params_st* params)
+{
+  gnutls_datum_t digest;
+  gnutls_digest_algorithm_t algo;
+  int hash_len;
+
+  algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
+
+  /* SHA1 or better allowed */
+  if (!hash->data || hash->size < hash_len)
+    {
+      gnutls_assert();
+      _gnutls_debug_log("Hash size (%d) does not correspond to hash %s(%d) or better.\n", (int)hash->size, gnutls_mac_get_name(algo), hash_len);
+          
+      if (hash->size != 20) /* SHA1 is allowed */
+        return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+    }
+
+  digest.data = hash->data;
+  digest.size = hash->size;
+
+  return _gnutls_pk_verify (pk, &digest, signature, params);
+}
+
+static int
+dsa_verify_data (gnutls_pk_algorithm_t pk,
+                 gnutls_digest_algorithm_t algo,
+                 const gnutls_datum_t * data,
+                 const gnutls_datum_t * signature,
+                 gnutls_pk_params_st* params)
+{
+  int ret;
+  opaque _digest[MAX_HASH_SIZE];
+  gnutls_datum_t digest;
+  digest_hd_st hd;
+
+  if (algo == GNUTLS_DIG_UNKNOWN)
+    algo = _gnutls_dsa_q_to_hash (pk, params, NULL);
+
+  ret = _gnutls_hash_init (&hd, algo);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  _gnutls_hash (&hd, data->data, data->size);
+  _gnutls_hash_deinit (&hd, _digest);
+
+  digest.data = _digest;
+  digest.size = _gnutls_hash_get_algo_len(algo);
+
+  return _gnutls_pk_verify (pk, &digest, signature, params);
+}
+
+/* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if 
+ * not verified, or 1 otherwise.
+ */
+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)
+{
+
+  switch (pk)
+    {
+    case GNUTLS_PK_RSA:
+
+      if (_pkcs1_rsa_verify_sig
+          (NULL, hash, signature, issuer_params) != 0)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+        }
+
+      return 1;
+      break;
+
+    case GNUTLS_PK_ECC:
+    case GNUTLS_PK_DSA:
+      if (dsa_verify_hashed_data(hash, signature, pk, issuer_params) != 0)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+        }
+
+      return 1;
+      break;
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_INTERNAL_ERROR;
+
+    }
+}
+
+/* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if 
+ * not verified, or 1 otherwise.
+ */
+int
+pubkey_verify_data (gnutls_pk_algorithm_t pk,
+                    gnutls_digest_algorithm_t algo,
+                    const gnutls_datum_t * data,
+                    const gnutls_datum_t * signature,
+                    gnutls_pk_params_st * issuer_params)
+{
+
+  switch (pk)
+    {
+    case GNUTLS_PK_RSA:
+
+      if (_pkcs1_rsa_verify_sig
+          (data, NULL, signature, issuer_params) != 0)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+        }
+
+      return 1;
+      break;
+
+    case GNUTLS_PK_ECC:
+    case GNUTLS_PK_DSA:
+      if (dsa_verify_data(pk, algo, data, signature, issuer_params) != 0)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+        }
+
+      return 1;
+      break;
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_INTERNAL_ERROR;
+
+    }
+}
+
+gnutls_digest_algorithm_t
+_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params, int* hash_len)
+{
+  int bits = 0;
+  
+  if (algo == GNUTLS_PK_DSA)
+    bits = _gnutls_mpi_get_nbits (params->params[1]);
+  else if (algo == GNUTLS_PK_ECC)
+    bits = gnutls_ecc_curve_get_size(params->flags)*8;
+
+  if (bits <= 160)
+    {
+      if (hash_len) *hash_len = 20;
+      return GNUTLS_DIG_SHA1;
+    }
+  else if (bits <= 192)
+    {
+      if (hash_len) *hash_len = 24;
+      return GNUTLS_DIG_SHA256;
+    }
+  else if (bits <= 224)
+    {
+      if (hash_len) *hash_len = 28;
+      return GNUTLS_DIG_SHA256;
+    }
+  else if (bits <= 256)
+    {
+      if (hash_len) *hash_len = 32;
+      return GNUTLS_DIG_SHA256;
+    }
+  else if (bits <= 384)
+    {
+      if (hash_len) *hash_len = 48;
+      return GNUTLS_DIG_SHA384;
+    }
+  else
+    {
+      if (hash_len) *hash_len = 64;
+      return GNUTLS_DIG_SHA512;
+    }
+}
index b93aa40a8a2c3f9265f9285650da38708cb3943e..db8a071d22f08e974cd9f1f6368756e40908178b 100644 (file)
@@ -48,6 +48,11 @@ 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
  * other RSA signatures including one with the old MD5/SHA1-combined
@@ -732,6 +737,120 @@ cleanup:
   return ret;
 }
 
+
+/* 
+ * This function will do RSA PKCS #1 1.5 encoding
+ * on the given digest. The given digest must be allocated
+ * and will be freed if replacement is required.
+ */
+int
+pk_prepare_hash (gnutls_pk_algorithm_t pk,
+                 gnutls_digest_algorithm_t hash, gnutls_datum_t * digest)
+{
+  int ret;
+  gnutls_datum_t old_digest = { digest->data, digest->size };
+
+  switch (pk)
+    {
+    case GNUTLS_PK_RSA:
+      /* Encode the digest as a DigestInfo
+       */
+      if ((ret = encode_ber_digest_info (hash, &old_digest, digest)) != 0)
+        {
+          gnutls_assert ();
+          return ret;
+        }
+
+      _gnutls_free_datum (&old_digest);
+      break;
+    case GNUTLS_PK_DSA:
+    case GNUTLS_PK_ECC:
+      break;
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+    }
+
+  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_mac_algorithm_t * hash,
+                        opaque * digest, 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_oid2mac_algorithm (str);
+
+  if (*hash == GNUTLS_MAC_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;
+    }
+
+  result = asn1_read_value (dinfo, "digest", digest, digest_size);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&dinfo);
+      return _gnutls_asn2err (result);
+    }
+
+  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.
  */
@@ -818,39 +937,3 @@ encode_ber_digest_info (gnutls_digest_algorithm_t hash,
 
   return 0;
 }
-
-/* 
- * This function will do RSA PKCS #1 1.5 encoding
- * on the given digest. The given digest must be allocated
- * and will be freed if replacement is required.
- */
-int
-pk_prepare_hash (gnutls_pk_algorithm_t pk,
-                 gnutls_digest_algorithm_t hash, gnutls_datum_t * digest)
-{
-  int ret;
-  gnutls_datum_t old_digest = { digest->data, digest->size };
-
-  switch (pk)
-    {
-    case GNUTLS_PK_RSA:
-      /* Encode the digest as a DigestInfo
-       */
-      if ((ret = encode_ber_digest_info (hash, &old_digest, digest)) != 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      _gnutls_free_datum (&old_digest);
-      break;
-    case GNUTLS_PK_DSA:
-    case GNUTLS_PK_ECC:
-      break;
-    default:
-      gnutls_assert ();
-      return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-    }
-
-  return 0;
-}
index 3b6957ac5835e40c4f58525eb8b5c7332fda9c57..e3865b9a2ae0fd603364042c6182aebecfadcd72 100644 (file)
@@ -67,4 +67,9 @@ _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_mac_algorithm_t * hash,
+                        opaque * digest, int *digest_size);
+
 #endif
index eec013cffcfb5f897fb6f2e6eca9772d350ab84a..078ab60897957f512942128947e9e34b89e8689e 100644 (file)
@@ -95,6 +95,12 @@ int gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey,
                                    unsigned int flags,
                                    const gnutls_datum_t * data,
                                    const gnutls_datum_t * signature);
+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);
 
 /* Private key operations */
 
index e6b92776a7e3aab60ec748cf88d7540b698d74c2..fb88179c520c1731086cf4339f22acf3be6d9b36 100644 (file)
@@ -202,16 +202,6 @@ gnutls_sign_callback_get (gnutls_session_t session, void **userdata)
                                        gnutls_datum_t * signature)
                                        _GNUTLS_GCC_ATTR_DEPRECATED;
 
-
-/* Deprecated because verify_* functions are moved to public
- * keys. Check abstract.h for similar functionality.
- */
-  int gnutls_x509_privkey_verify_data (gnutls_x509_privkey_t key,
-                                       unsigned int flags,
-                                       const gnutls_datum_t * data,
-                                       const gnutls_datum_t * signature)
-                                       _GNUTLS_GCC_ATTR_DEPRECATED;
-
 /* we support the gnutls_privkey_sign_data() instead.
  */
   int gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key,
index 042b2f95cbfc8a17c5c4ef5a544ff574803fb0f7..5c47ea3b57019b1d540961db5df0f351d675e5a1 100644 (file)
@@ -508,7 +508,6 @@ GNUTLS_1_4
     gnutls_x509_privkey_init;
     gnutls_x509_privkey_sign_data;
     gnutls_x509_privkey_sign_hash;
-    gnutls_x509_privkey_verify_data;
     gnutls_x509_rdn_get;
     gnutls_x509_rdn_get_by_oid;
     gnutls_x509_rdn_get_oid;
@@ -710,6 +709,7 @@ GNUTLS_3_0_0 {
        gnutls_pubkey_get_pk_ecc_raw;
        gnutls_x509_privkey_export_ecc_raw;
        gnutls_x509_privkey_import_ecc_raw;
+       gnutls_pubkey_verify_data2;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
index 788b33503007f87f63ed7f8e5a4503abcd782d9d..16cd3e42f5db7e1cd95386a44a55f1369d72ce9b 100644 (file)
@@ -1344,6 +1344,43 @@ cleanup:
   return result;
 }
 
+/**
+ * gnutls_x509_crt_get_signature_algorithm:
+ * @cert: should contain a #gnutls_x509_crt_t structure
+ *
+ * This function will return a value of the #gnutls_sign_algorithm_t
+ * enumeration that is the signature algorithm that has been used to
+ * sign this certificate.
+ *
+ * Returns: a #gnutls_sign_algorithm_t value, or a negative value on
+ *   error.
+ **/
+int
+_gnutls_x509_get_signature_algorithm (ASN1_TYPE src, const char *src_name)
+{
+  int result;
+  gnutls_datum_t sa;
+
+  /* Read the signature algorithm. Note that parameters are not
+   * read. They will be read from the issuer's certificate if needed.
+   */
+  result =
+    _gnutls_x509_read_value (src, src_name, &sa, 0);
+
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+  result = _gnutls_x509_oid2sign_algorithm (sa.data);
+
+  _gnutls_free_datum (&sa);
+
+  return result;
+}
+
+
 /* Reads the DER signature from the certificate and allocates space and
  * returns them into signed_data.
  */
index 0e96337e72bea7d0f2d0ae28138008aa75046731..aebe33864148660a9ff9d52dc61ce781fc30ffdc 100644 (file)
@@ -128,6 +128,9 @@ int _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct,
 int _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name,
                                    unsigned int *bits);
 
+int
+_gnutls_x509_get_signature_algorithm (ASN1_TYPE src, const char *src_name);
+
 int _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
                                              const char *dst_name,
                                              gnutls_pk_algorithm_t
@@ -140,8 +143,6 @@ int _gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name,
 int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name,
                                 gnutls_datum_t * signature);
 
-gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, 
-  const gnutls_pk_params_st* params, int* hash_len);
 
 int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
                           gnutls_pk_params_st * params);
@@ -153,12 +154,6 @@ int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, gnutls_pk_params_st*,
 void _asnstr_append_name (char *name, size_t name_size, const char *part1,
                           const char *part2);
 
-int pubkey_verify_sig (const gnutls_datum_t * tbs,
-                       const gnutls_datum_t * hash,
-                       const gnutls_datum_t * signature,
-                       gnutls_pk_algorithm_t pk, 
-                       gnutls_pk_params_st * issuer_params);
-
 int
 check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
 
index c61b3c4043a8017f608224f8a2f72f5612100955..27dee3ed8e4c682e6f4a680977872bab050b847c 100644 (file)
@@ -2523,6 +2523,7 @@ gnutls_x509_crq_verify (gnutls_x509_crq_t crq,
 gnutls_datum data = { NULL, 0 };
 gnutls_datum signature = { NULL, 0 };
 gnutls_pk_params_st params;
+gnutls_digest_algorithm_t algo;
 int ret;
 
   gnutls_pk_params_init(&params);
@@ -2534,6 +2535,15 @@ int ret;
       gnutls_assert ();
       return ret;
     }
+    
+  ret = _gnutls_x509_get_signature_algorithm(crq->crq, "signatureAlgorithm.algorithm");
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+  
+  algo = _gnutls_sign_get_hash_algorithm(ret);
 
   ret = _gnutls_x509_get_signature (crq->crq, "signature", &signature);
   if (ret < 0)
@@ -2550,9 +2560,8 @@ int ret;
       goto cleanup;
     }
 
-  ret = pubkey_verify_sig(&data, NULL, &signature,
-                          gnutls_x509_crq_get_pk_algorithm (crq, NULL),
-                          &params);
+  ret = pubkey_verify_data(gnutls_x509_crq_get_pk_algorithm (crq, NULL), algo,
+                           &data, &signature, &params);
   if (ret < 0)
     {
       gnutls_assert ();
index 08d89b562109384daeafeb9692aed532dae920a7..99f626f1d66b6c0277a848b57dd5c3b6b7290030 100644 (file)
@@ -1640,45 +1640,6 @@ gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key,
 }
 
 
-/**
- * gnutls_x509_privkey_verify_data:
- * @key: Holds the key
- * @flags: should be 0 for now
- * @data: holds the data to be signed
- * @signature: contains the signature
- *
- * This function will verify the given signed data, using the
- * parameters in the private key.
- *
- * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
- * is returned, and a positive code on success.
- *
- * Deprecated: Use gnutls_pubkey_verify_data().
- */
-int
-gnutls_x509_privkey_verify_data (gnutls_x509_privkey_t key,
-                                 unsigned int flags,
-                                 const gnutls_datum_t * data,
-                                 const gnutls_datum_t * signature)
-{
-  int result;
-
-  if (key == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  result = _gnutls_x509_privkey_verify_signature (data, signature, key);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      return result;
-    }
-
-  return result;
-}
-
 /**
  * gnutls_x509_privkey_fix:
  * @key: Holds the key
index 4ae970677653eb0542bf61178b63bb40b2348ef5..2adb3dd5f67b7688dce6d9d6d310cf261f35fffc 100644 (file)
@@ -369,7 +369,7 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
   gnutls_datum_t cert_signed_data = { NULL, 0 };
   gnutls_datum_t cert_signature = { NULL, 0 };
   gnutls_x509_crt_t issuer = NULL;
-  int issuer_version, result;
+  int issuer_version, result, hash_algo;
   unsigned int out = 0;
 
   if (output)
@@ -442,8 +442,17 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
       goto cleanup;
     }
 
+  result = _gnutls_x509_get_signature_algorithm(cert->cert, "signatureAlgorithm.algorithm");
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  hash_algo = _gnutls_sign_get_hash_algorithm(result);
+
   result =
-    _gnutls_x509_verify_signature (&cert_signed_data, NULL, &cert_signature,
+    _gnutls_x509_verify_data (hash_algo, &cert_signed_data, &cert_signature,
                                    issuer);
   if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED)
     {
@@ -666,301 +675,6 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
   return 0;
 }
 
-
-/* Reads the digest information.
- * we use DER here, although we should use BER. It works fine
- * anyway.
- */
-static int
-decode_ber_digest_info (const gnutls_datum_t * info,
-                        gnutls_mac_algorithm_t * hash,
-                        opaque * digest, 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_oid2mac_algorithm (str);
-
-  if (*hash == GNUTLS_MAC_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;
-    }
-
-  result = asn1_read_value (dinfo, "digest", digest, digest_size);
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&dinfo);
-      return _gnutls_asn2err (result);
-    }
-
-  asn1_delete_structure (&dinfo);
-
-  return 0;
-}
-
-/* if hash==MD5 then we do RSA-MD5
- * if hash==SHA then we do RSA-SHA
- * params[0] is modulus
- * params[1] is public key
- */
-static int
-_pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
-                       const gnutls_datum_t * prehash,
-                       const gnutls_datum_t * signature, 
-                       gnutls_pk_params_st * params)
-{
-  gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
-  int ret;
-  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
-  int digest_size;
-  digest_hd_st hd;
-  gnutls_datum_t decrypted;
-
-  ret =
-    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, 1);
-  if (ret < 0)
-    {
-      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 && prehash->data && prehash->size == digest_size)
-    {
-      cmp = prehash->data;
-    }
-  else
-    {
-      if (!text)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_INVALID_REQUEST;
-        }
-
-      ret = _gnutls_hash_init (&hd, hash);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      _gnutls_hash (&hd, text->data, text->size);
-      _gnutls_hash_deinit (&hd, md);
-
-      cmp = md;
-    }
-
-  if (memcmp (cmp, digest, digest_size) != 0)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-    }
-
-  return 0;
-}
-
-/* Hashes input data and verifies a signature.
- */
-static int
-dsa_verify_sig (const gnutls_datum_t * text,
-                const gnutls_datum_t * hash,
-                const gnutls_datum_t * signature,
-                gnutls_pk_algorithm_t pk,
-                gnutls_pk_params_st* params)
-{
-  int ret;
-  opaque _digest[MAX_HASH_SIZE];
-  gnutls_datum_t digest;
-  digest_hd_st hd;
-  gnutls_digest_algorithm_t algo;
-  int hash_len;
-
-  algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
-  if (hash)
-    {
-      /* SHA1 or better allowed */
-      if (!hash->data || hash->size < hash_len)
-        {
-          gnutls_assert();
-          _gnutls_debug_log("Hash size (%d) does not correspond to hash %s(%d) or better.\n", (int)hash->size, gnutls_mac_get_name(algo), hash_len);
-          
-          if (hash->size != 20) /* SHA1 is allowed */
-            return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
-        }
-
-      digest.data = hash->data;
-      digest.size = hash->size;
-    }
-  else
-    {
-      ret = _gnutls_hash_init (&hd, algo);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      _gnutls_hash (&hd, text->data, text->size);
-      _gnutls_hash_deinit (&hd, _digest);
-
-      digest.data = _digest;
-      digest.size = _gnutls_hash_get_algo_len(algo);
-    }
-
-  ret = _gnutls_pk_verify (pk, &digest, signature, params);
-
-  return ret;
-}
-
-/* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if 
- * not verified, or 1 otherwise.
- */
-int
-pubkey_verify_sig (const gnutls_datum_t * tbs,
-                   const gnutls_datum_t * hash,
-                   const gnutls_datum_t * signature,
-                   gnutls_pk_algorithm_t pk,
-                   gnutls_pk_params_st * issuer_params)
-{
-
-  switch (pk)
-    {
-    case GNUTLS_PK_RSA:
-
-      if (_pkcs1_rsa_verify_sig
-          (tbs, hash, signature, issuer_params) != 0)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-        }
-
-      return 1;
-      break;
-
-    case GNUTLS_PK_ECC:
-    case GNUTLS_PK_DSA:
-      if (dsa_verify_sig(tbs, hash, signature, pk, issuer_params) != 0)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_PK_SIG_VERIFY_FAILED;
-        }
-
-      return 1;
-      break;
-    default:
-      gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
-
-    }
-}
-
-gnutls_digest_algorithm_t
-_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params, int* hash_len)
-{
-  int bits = 0;
-  
-  if (algo == GNUTLS_PK_DSA)
-    bits = _gnutls_mpi_get_nbits (params->params[1]);
-  else if (algo == GNUTLS_PK_ECC)
-    bits = gnutls_ecc_curve_get_size(params->flags)*8;
-
-  if (bits <= 160)
-    {
-      if (hash_len) *hash_len = 20;
-      return GNUTLS_DIG_SHA1;
-    }
-  else if (bits <= 192)
-    {
-      if (hash_len) *hash_len = 24;
-      return GNUTLS_DIG_SHA256;
-    }
-  else if (bits <= 224)
-    {
-      if (hash_len) *hash_len = 28;
-      return GNUTLS_DIG_SHA256;
-    }
-  else if (bits <= 256)
-    {
-      if (hash_len) *hash_len = 32;
-      return GNUTLS_DIG_SHA256;
-    }
-  else if (bits <= 384)
-    {
-      if (hash_len) *hash_len = 48;
-      return GNUTLS_DIG_SHA384;
-    }
-  else
-    {
-      if (hash_len) *hash_len = 64;
-      return GNUTLS_DIG_SHA512;
-    }
-}
-
 /* This will return the appropriate hash to verify the given signature.
  * If signature is NULL it will return an (or the) appropriate hash for
  * the given parameters.
@@ -1040,14 +754,14 @@ cleanup:
 /* verifies if the certificate is properly signed.
  * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
  * 
- * 'tbs' is the signed data
+ * 'data' is the signed data
  * 'signature' is the signature!
  */
 int
-_gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
-                               const gnutls_datum_t * hash,
-                               const gnutls_datum_t * signature,
-                               gnutls_x509_crt_t issuer)
+_gnutls_x509_verify_data (gnutls_digest_algorithm_t algo,
+                          const gnutls_datum_t * data,
+                          const gnutls_datum_t * signature,
+                          gnutls_x509_crt_t issuer)
 {
   gnutls_pk_params_st issuer_params;
   int ret;
@@ -1063,9 +777,8 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
     }
 
   ret =
-    pubkey_verify_sig (tbs, hash, signature,
-                       gnutls_x509_crt_get_pk_algorithm (issuer, NULL),
-                       &issuer_params);
+    pubkey_verify_data (gnutls_x509_crt_get_pk_algorithm (issuer, NULL), algo,
+                        data, signature, &issuer_params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1078,26 +791,36 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
   return ret;
 }
 
-/* verifies if the certificate is properly signed.
- * returns GNUTLS_E_PK_VERIFY_SIG_FAILED on failure and 1 on success.
- * 
- * 'tbs' is the signed data
- * 'signature' is the signature!
- */
 int
-_gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs,
-                                       const gnutls_datum_t * signature,
-                                       gnutls_x509_privkey_t issuer)
+_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;
 
-  ret = pubkey_verify_sig (tbs, NULL, signature, issuer->pk_algorithm,
-                           &issuer->params);
+  /* 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;
 }
 
@@ -1329,7 +1052,7 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
   gnutls_datum_t crl_signed_data = { NULL, 0 };
   gnutls_datum_t crl_signature = { NULL, 0 };
   gnutls_x509_crt_t issuer;
-  int result;
+  int result, hash_algo;
 
   if (output)
     *output = 0;
@@ -1381,8 +1104,17 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
       goto cleanup;
     }
 
+  result = _gnutls_x509_get_signature_algorithm(crl->crl, "signatureAlgorithm.algorithm");
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  hash_algo = _gnutls_sign_get_hash_algorithm(result);
+
   result =
-    _gnutls_x509_verify_signature (&crl_signed_data, NULL, &crl_signature,
+    _gnutls_x509_verify_data (hash_algo, &crl_signed_data, &crl_signature,
                                    issuer);
   if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED)
     {
index 810057a0491816259a3493be5417719ee2a5682b..582968f8e6c5a1398822651022fec38eb5f2ebdb 100644 (file)
@@ -475,33 +475,7 @@ gnutls_x509_crt_get_dn_oid (gnutls_x509_crt_t cert,
 int
 gnutls_x509_crt_get_signature_algorithm (gnutls_x509_crt_t cert)
 {
-  int result;
-  gnutls_datum_t sa;
-
-  if (cert == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  /* Read the signature algorithm. Note that parameters are not
-   * read. They will be read from the issuer's certificate if needed.
-   */
-  result =
-    _gnutls_x509_read_value (cert->cert, "signatureAlgorithm.algorithm",
-                             &sa, 0);
-
-  if (result < 0)
-    {
-      gnutls_assert ();
-      return result;
-    }
-
-  result = _gnutls_x509_oid2sign_algorithm (sa.data);
-
-  _gnutls_free_datum (&sa);
-
-  return result;
+  return _gnutls_x509_get_signature_algorithm(cert->cert, "signatureAlgorithm.algorithm");
 }
 
 /**
@@ -2613,7 +2587,7 @@ gnutls_x509_crt_verify_data (gnutls_x509_crt_t crt, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_x509_verify_signature (data, NULL, signature, crt);
+  result = _gnutls_x509_verify_data (GNUTLS_DIG_UNKNOWN, data, signature, crt);
   if (result < 0)
     {
       gnutls_assert ();
@@ -2651,7 +2625,7 @@ gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_x509_verify_signature (NULL, hash, signature, crt);
+  result = _gnutls_x509_verify_hashed_data (hash, signature, crt);
   if (result < 0)
     {
       gnutls_assert ();
index 4df028befe781f6cae8a345a350ef52f10eeaac5..41ed58277be4751ebfb4344e984ecbaa0d353aac 100644 (file)
@@ -182,13 +182,14 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                                gnutls_pk_algorithm_t pk,
                                gnutls_pk_params_st * issuer_params);
 
-int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
-                                   const gnutls_datum_t * hash,
-                                   const gnutls_datum_t * signature,
-                                   gnutls_x509_crt_t issuer);
-int _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs,
-                                           const gnutls_datum_t * signature,
-                                           gnutls_x509_privkey_t issuer);
+int _gnutls_x509_verify_data (gnutls_digest_algorithm_t algo,
+                              const gnutls_datum_t * data,
+                              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 *