]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Applied patch by Cedric Bail to add functions gnutls_x509_crt_verify_hash() and gnutl...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 26 Mar 2009 18:36:49 +0000 (20:36 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 26 Mar 2009 18:36:49 +0000 (20:36 +0200)
lib/includes/gnutls/x509.h
lib/x509/verify.c
lib/x509/x509.c
lib/x509/x509_int.h

index 00c62a609b54f35e73f87166ec7696040b5b34f3..46038474dffe1882b5f8f04bcd00f97b22df53e1 100644 (file)
@@ -641,6 +641,14 @@ extern "C"
                                   unsigned int flags,
                                   const gnutls_datum_t * data,
                                   const gnutls_datum_t * signature);
+  int gnutls_x509_crt_verify_hash (gnutls_x509_crt_t crt,
+                                  unsigned int flags,
+                                  const gnutls_datum_t * hash,
+                                  const gnutls_datum_t * signature);
+
+  int gnutls_x509_crt_get_sig_algorithm(gnutls_digest_algorithm_t *hash,
+                                        const gnutls_x509_crt_t crt,
+                                        const gnutls_datum_t * signature);
 
   int gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key,
                                     const gnutls_datum_t * hash,
index 4b1252e85d675e63875edf89a8c6ce50bccc9d8c..3a1b1f00c4e459e54fd713f0b6d853c61286164f 100644 (file)
@@ -332,7 +332,7 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
     }
 
   ret =
-    _gnutls_x509_verify_signature (&cert_signed_data, &cert_signature,
+    _gnutls_x509_verify_signature (&cert_signed_data, NULL, &cert_signature,
                                   issuer);
   if (ret < 0)
     {
@@ -603,12 +603,13 @@ decode_ber_digest_info (const gnutls_datum_t * info,
  */
 static int
 _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
+                      const gnutls_datum_t * prehash,
                       const gnutls_datum_t * signature, bigint_t * params,
                       int params_len)
 {
   gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
   int ret;
-  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE];
+  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
   int digest_size;
   digest_hd_st hd;
   gnutls_datum_t decrypted;
@@ -641,17 +642,32 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
       return GNUTLS_E_ASN1_GENERIC_ERROR;
     }
 
-  ret = _gnutls_hash_init (&hd, hash);
-  if (ret < 0)
+  if (prehash && prehash->data && prehash->size == digest_size)
     {
-      gnutls_assert ();
-      return ret;
+       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;
     }
 
-  _gnutls_hash (&hd, text->data, text->size);
-  _gnutls_hash_deinit (&hd, md);
-
-  if (memcmp (md, digest, digest_size) != 0)
+  if (memcmp (cmp, digest, digest_size) != 0)
     {
       gnutls_assert ();
       return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -664,6 +680,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
  */
 static int
 dsa_verify_sig (const gnutls_datum_t * text,
+               const gnutls_datum_t * hash,
                const gnutls_datum_t * signature, bigint_t * params,
                int params_len)
 {
@@ -672,18 +689,25 @@ dsa_verify_sig (const gnutls_datum_t * text,
   gnutls_datum_t digest;
   digest_hd_st hd;
 
-  ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
-  if (ret < 0)
+  if (hash && hash->data && hash->size == 20)
     {
-      gnutls_assert ();
-      return ret;
+       digest = *hash;
+    }
+  else
+    {
+       ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
+       if (ret < 0)
+        {
+           gnutls_assert ();
+           return ret;
+        }
+
+       _gnutls_hash (&hd, text->data, text->size);
+       _gnutls_hash_deinit (&hd, _digest);
+
+       digest.data = _digest;
+       digest.size = 20;
     }
-
-  _gnutls_hash (&hd, text->data, text->size);
-  _gnutls_hash_deinit (&hd, _digest);
-
-  digest.data = _digest;
-  digest.size = 20;
 
   ret = _gnutls_dsa_verify (&digest, signature, params, params_len);
 
@@ -695,6 +719,7 @@ dsa_verify_sig (const gnutls_datum_t * text,
  */
 static int
 verify_sig (const gnutls_datum_t * tbs,
+           const gnutls_datum_t * hash,
            const gnutls_datum_t * signature,
            gnutls_pk_algorithm_t pk, bigint_t * issuer_params,
            int issuer_params_size)
@@ -705,7 +730,7 @@ verify_sig (const gnutls_datum_t * tbs,
     case GNUTLS_PK_RSA:
 
       if (_pkcs1_rsa_verify_sig
-         (tbs, signature, issuer_params, issuer_params_size) != 0)
+         (tbs, hash, signature, issuer_params, issuer_params_size) != 0)
        {
          gnutls_assert ();
          return 0;
@@ -716,7 +741,7 @@ verify_sig (const gnutls_datum_t * tbs,
 
     case GNUTLS_PK_DSA:
       if (dsa_verify_sig
-         (tbs, signature, issuer_params, issuer_params_size) != 0)
+         (tbs, hash, signature, issuer_params, issuer_params_size) != 0)
        {
          gnutls_assert ();
          return 0;
@@ -731,6 +756,66 @@ verify_sig (const gnutls_datum_t * tbs,
     }
 }
 
+int
+_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t *hash,
+                              const gnutls_datum_t * signature,
+                              const gnutls_x509_crt_t issuer)
+{
+  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
+  opaque digest[MAX_HASH_SIZE];
+  gnutls_datum_t decrypted;
+  int issuer_params_size;
+  int digest_size;
+  int ret;
+
+  switch (gnutls_x509_crt_get_pk_algorithm (issuer, NULL))
+    {
+    case GNUTLS_PK_DSA:
+      if (hash) *hash = GNUTLS_MAC_SHA1;
+      return 0;
+
+    case GNUTLS_PK_RSA:
+      issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
+      ret = _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size);
+      if (ret < 0)
+       {
+          gnutls_assert ();
+          return ret;
+       }
+
+      ret =
+       _gnutls_pkcs1_rsa_decrypt (&decrypted, signature,
+                                  issuer_params, issuer_params_size, 1);
+      if (ret < 0)
+       {
+          gnutls_assert ();
+          return ret;
+       }
+
+      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;
+       }
+
+      return 0;
+
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_INTERNAL_ERROR;
+    }
+}
+
 /* verifies if the certificate is properly signed.
  * returns 0 on failure and 1 on success.
  * 
@@ -739,6 +824,7 @@ verify_sig (const gnutls_datum_t * tbs,
  */
 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)
 {
@@ -757,7 +843,7 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
     }
 
   ret =
-    verify_sig (tbs, signature,
+    verify_sig (tbs, hash, signature,
                gnutls_x509_crt_get_pk_algorithm (issuer, NULL),
                issuer_params, issuer_params_size);
   if (ret < 0)
@@ -788,7 +874,7 @@ _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs,
 {
   int ret;
 
-  ret = verify_sig (tbs, signature, issuer->pk_algorithm,
+  ret = verify_sig (tbs, NULL, signature, issuer->pk_algorithm,
                    issuer->params, issuer->params_size);
   if (ret < 0)
     {
@@ -1073,7 +1159,7 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
     }
 
   ret =
-    _gnutls_x509_verify_signature (&crl_signed_data, &crl_signature, issuer);
+    _gnutls_x509_verify_signature (&crl_signed_data, NULL, &crl_signature, issuer);
   if (ret < 0)
     {
       gnutls_assert ();
index ca8cac5107a44c12ce0a8c5704028c0fe53090a3..1c6206af61600c709e381720cc33fce49566ba62 100644 (file)
@@ -2304,6 +2304,32 @@ gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
   return 0;                    /* not revoked. */
 }
 
+/**
+  * gnutls_x509_crt_get_sig_algorithm - This function will return the hash algorithm used during signature.
+  * @hash: The result of the call with the hash algorithm used for signature
+  * @crt: Holds the certificate
+  * @signature: contains the signature
+  *
+  * This function will read the certifcate and the signed data to
+  * determine the hash algorithm used to generate the signature.
+  *
+  * Returns: 0 if the hash algorithm was found. A negative value is
+  * returned on error.
+  **/
+int
+gnutls_x509_crt_get_sig_algorithm(gnutls_digest_algorithm_t *hash,
+                                  const gnutls_x509_crt_t crt,
+                                  const gnutls_datum_t * signature)
+{
+   if (crt == NULL)
+     {
+       gnutls_assert ();
+       return GNUTLS_E_INVALID_REQUEST;
+     }
+
+   return _gnutls_x509_verify_algorithm(hash, signature, crt);
+}
+
 /**
   * gnutls_x509_crt_verify_data - This function will verify the given signed data.
   * @crt: Holds the certificate
@@ -2330,7 +2356,43 @@ gnutls_x509_crt_verify_data (gnutls_x509_crt_t crt, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_x509_verify_signature (data, signature, crt);
+  result = _gnutls_x509_verify_signature (data, NULL, signature, crt);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return 0;
+    }
+
+  return result;
+}
+
+/**
+  * gnutls_x509_crt_verify_data - This function will verify the given signed data.
+  * @crt: Holds the certificate
+  * @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 certificate.
+  *
+  * Returns: In case of a verification failure 0 is returned, and 1 on
+  * success.
+  **/
+int
+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;
+
+  if (crt == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  result = _gnutls_x509_verify_signature (NULL, hash, signature, crt);
   if (result < 0)
     {
       gnutls_assert ();
index 2186e8c2876f62888b5da4783d879556cc268235..5a1497a4cdb2654466bb4af8b76761e74626aebf 100644 (file)
@@ -184,7 +184,11 @@ int _gnutls_parse_general_name (ASN1_TYPE src, const char *src_name,
 /* verify.c */
 int gnutls_x509_crt_is_issuer (gnutls_x509_crt_t cert,
                               gnutls_x509_crt_t issuer);
+int _gnutls_x509_verify_algorithm(gnutls_mac_algorithm_t *hash,
+                                 const gnutls_datum_t * signature,
+                                 const gnutls_x509_crt_t crt);
 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,