From 6e76e9b9fa845b76b0b9a45f05f4b54a052578ff Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@redhat.com>
Date: Mon, 19 Jan 2015 09:29:31 +0100
Subject: [PATCH] on certificate import check whether the two signature algorithms match

---
 lib/x509/x509.c |   19 ++++++++++++++++++-
 1 files changed, 18 insertions(+), 1 deletions(-)

Index: gnutls-2.4.1/lib/x509/x509.c
===================================================================
--- gnutls-2.4.1.orig/lib/x509/x509.c	2008-06-30 22:45:51.000000000 +0200
+++ gnutls-2.4.1/lib/x509/x509.c	2015-03-21 13:06:27.312062569 +0100
@@ -168,6 +168,7 @@ gnutls_x509_crt_import (gnutls_x509_crt_
   int result = 0, need_free = 0;
   gnutls_datum_t _data;
   opaque *signature = NULL;
+  int s2;
 
   if (cert == NULL)
     {
@@ -218,6 +219,23 @@ gnutls_x509_crt_import (gnutls_x509_crt_
       goto cleanup;
     }
 
+	result = _gnutls_x509_get_signature_algorithm(cert->cert,
+						      "signatureAlgorithm.algorithm");
+	if (result < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+	s2 = _gnutls_x509_get_signature_algorithm(cert->cert,
+						  "tbsCertificate.signature.algorithm");
+	if (result != s2) {
+		_gnutls_debug_log("signatureAlgorithm.algorithm differs from tbsCertificate.signature.algorithm: %s, %s\n",
+			gnutls_sign_get_name(result), gnutls_sign_get_name(s2));
+		gnutls_assert();
+		result = GNUTLS_E_CERTIFICATE_ERROR;
+		goto cleanup;
+	}
+
   /* Since we do not want to disable any extension
    */
   cert->use_extensions = 1;
Index: gnutls-2.4.1/lib/x509/common.c
===================================================================
--- gnutls-2.4.1.orig/lib/x509/common.c	2015-03-21 13:06:27.088059413 +0100
+++ gnutls-2.4.1/lib/x509/common.c	2015-03-21 13:06:27.313062583 +0100
@@ -1412,6 +1412,42 @@ 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: gnutls-2.4.1/lib/x509/common.h
===================================================================
--- gnutls-2.4.1.orig/lib/x509/common.h	2008-06-30 22:45:51.000000000 +0200
+++ gnutls-2.4.1/lib/x509/common.h	2015-03-21 13:06:27.313062583 +0100
@@ -113,6 +113,9 @@ int _gnutls_x509_decode_and_read_attribu
 
 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,
Index: gnutls-2.4.1/includes/gnutls/gnutls.h.in
===================================================================
--- gnutls-2.4.1.orig/includes/gnutls/gnutls.h.in	2015-03-21 13:06:27.185060780 +0100
+++ gnutls-2.4.1/includes/gnutls/gnutls.h.in	2015-03-21 14:55:56.956678042 +0100
@@ -396,6 +396,7 @@ extern "C"
   const char *gnutls_kx_get_name (gnutls_kx_algorithm_t algorithm);
   const char *gnutls_certificate_type_get_name (gnutls_certificate_type_t
 						type);
+  const char *gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm);
 
   gnutls_mac_algorithm_t gnutls_mac_get_id (const char* name);
   gnutls_compression_method_t gnutls_compression_get_id (const char* name);
Index: gnutls-2.4.1/lib/gnutls_algorithms.c
===================================================================
--- gnutls-2.4.1.orig/lib/gnutls_algorithms.c	2015-03-21 13:06:27.133060047 +0100
+++ gnutls-2.4.1/lib/gnutls_algorithms.c	2015-03-21 14:54:16.985249305 +0100
@@ -1968,6 +1968,27 @@ static const gnutls_sign_entry sign_algo
   GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
 
 /**
+ * gnutls_sign_get_name - Get name string for a #gnutls_sign_algorithm_t
+ * @algorithm: is a public key signature algorithm
+ *
+ * Convert a #gnutls_sign_algorithm_t value to a string.
+ *
+ * Returns: a pointer to a string that contains the name of the
+ *   specified public key signature algorithm, or %NULL.
+ *
+ * Since: 2.6.0
+ **/
+const char *
+gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm)
+{
+  const char *ret = "SIGN_UNKNOWN";
+
+  GNUTLS_SIGN_LOOP (if (p->id == algorithm) ret = p->name);
+
+  return ret;
+}
+
+/**
  * gnutls_sign_algorithm_get_name - Returns a string with the name of the specified sign algorithm
  * @algorithm: is a sign algorithm
  *
