]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Corrected signature generation and verification
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 11 Feb 2011 23:05:31 +0000 (00:05 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 11 Feb 2011 23:05:31 +0000 (00:05 +0100)
in the Certificate Verify message when in TLS 1.2. Reported
by Todd A. Ouska.

NEWS
lib/gnutls_extensions.c
lib/gnutls_sig.c

diff --git a/NEWS b/NEWS
index 027f775ef881c85b264b55834fb0b5854c86886e..819b03ca6ec95878e2fa3ec57e4e6adc2511bfb3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ See the end for copying conditions.
 
 * Version 2.99.0 (unreleased)
 
+** libgnutls: Corrected signature generation and verification
+in the Certificate Verify message when in TLS 1.2. Reported
+by Todd A. Ouska.
+
 ** libgnutlsxx: The C++ interface returns exception on
 every error and not only on fatal ones. This allows easier
 handling of errors.
index 451065184f9c7e7f452560cad94d317f3088a847..e14abc4a23b0f97e0ce76f6544f33915ced30c34 100644 (file)
@@ -651,7 +651,7 @@ _gnutls_ext_get_session_data (gnutls_session_t session,
           return 0;
         }
     }
-  return GNUTLS_E_INVALID_REQUEST;
+  return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
 }
 
 int
index e7fbf440b267c9eb33b9483e39f8509cedad65a2..2719c57cddcbc3543a6ede1bcc06feb2fbf76b42 100644 (file)
@@ -43,7 +43,7 @@
 #include <x509/common.h>
 
 static int
-_gnutls_tls_sign (gnutls_session_t session,
+sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
                   gnutls_cert * cert, gnutls_privkey_t pkey,
                   const gnutls_datum_t * hash_concat,
                   gnutls_datum_t * signature);
@@ -55,72 +55,6 @@ _gnutls_tls_sign (gnutls_session_t session,
  */
 #define MAX_SIG_SIZE 19 + MAX_HASH_SIZE
 
-/* Create a DER-encoded value as a opaque signature when RSA is used.
- * See RFC 5246 DigitallySigned for the actual format.
- */
-static int
-_gnutls_rsa_encode_sig (gnutls_mac_algorithm_t algo,
-                        const gnutls_datum_t * hash,
-                        gnutls_datum_t * signature)
-{
-  ASN1_TYPE di;
-  const char *oid;
-  int result, signature_size;
-
-  oid = _gnutls_x509_mac_to_oid (algo);
-  if (!oid)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
-    }
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.DigestInfo", &di)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  if ((result = asn1_write_value (di, "digestAlgorithm.algorithm",
-                                  oid, strlen (oid))) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&di);
-      return _gnutls_asn2err (result);
-    }
-
-  /* Use NULL parameters. */
-  if ((result = asn1_write_value (di, "digestAlgorithm.parameters",
-                                  ASN1_NULL, ASN1_NULL_SIZE)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&di);
-      return _gnutls_asn2err (result);
-    }
-
-  if ((result = asn1_write_value (di, "digest",
-                                  hash->data, hash->size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&di);
-      return _gnutls_asn2err (result);
-    }
-
-  signature_size = signature->size;
-  result = asn1_der_coding (di, "", signature->data, &signature_size, NULL);
-  asn1_delete_structure (&di);
-
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  signature->size = signature_size;
-
-  return 0;
-}
-
 static int 
 get_hash_algo(gnutls_session_t session, gnutls_cert* cert, 
   gnutls_sign_algorithm_t sign_algo,
@@ -218,17 +152,12 @@ _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert,
           dconcat.size = 36;
         }
       else
-        {                       /* TLS 1.2 way */
-          gnutls_datum_t hash;
+        { /* TLS 1.2 way */
 
           _gnutls_hash_deinit (&td_sha, concat);
 
-          hash.data = concat;
-          hash.size = _gnutls_hash_get_algo_len (hash_algo);
           dconcat.data = concat;
-          dconcat.size = sizeof concat;
-
-          _gnutls_rsa_encode_sig (hash_algo, &hash, &dconcat);
+          dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
         }
       break;
     case GNUTLS_PK_DSA:
@@ -250,7 +179,7 @@ _gnutls_handshake_sign_data (gnutls_session_t session, gnutls_cert * cert,
       return GNUTLS_E_INTERNAL_ERROR;
     }
 
-  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
+  ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -305,11 +234,12 @@ _gnutls_soft_sign (gnutls_pk_algorithm_t algo, bigint_t * params,
  * it supports signing.
  */
 static int
-_gnutls_tls_sign (gnutls_session_t session,
+sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo,
                   gnutls_cert * cert, gnutls_privkey_t pkey,
                   const gnutls_datum_t * hash_concat,
                   gnutls_datum_t * signature)
 {
+  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
   /* If our certificate supports signing
    */
@@ -335,11 +265,14 @@ _gnutls_tls_sign (gnutls_session_t session,
         }
     }
 
-  return _gnutls_privkey_sign_hash (pkey, hash_concat, signature);
+   if (!_gnutls_version_has_selectable_sighash (ver))
+    return _gnutls_privkey_sign_hash (pkey, hash_concat, signature);
+  else
+    return gnutls_privkey_sign_hash2 (pkey, hash_algo, 0, hash_concat, signature);
 }
 
 static int
-_gnutls_verify_sig (gnutls_cert * cert,
+verify_tls_hash (gnutls_protocol_t ver, gnutls_cert * cert,
                     const gnutls_datum_t * hash_concat,
                     gnutls_datum_t * signature, size_t sha1pos,
                     gnutls_pk_algorithm_t pk_algo)
@@ -374,8 +307,14 @@ _gnutls_verify_sig (gnutls_cert * cert,
       vdata.size = hash_concat->size;
 
       /* verify signature */
-      if ((ret = _gnutls_rsa_verify (&vdata, signature, cert->params,
-                                     cert->params_size, 1)) < 0)
+      if (!_gnutls_version_has_selectable_sighash (ver))
+        ret = _gnutls_rsa_verify (&vdata, signature, cert->params,
+                                     cert->params_size, 1);
+      else
+        ret = pubkey_verify_sig( NULL, &vdata, signature, pk_algo, 
+          cert->params, cert->params_size);
+
+      if (ret < 0)
         {
           gnutls_assert ();
           return ret;
@@ -387,16 +326,16 @@ _gnutls_verify_sig (gnutls_cert * cert,
       vdata.data = &hash_concat->data[sha1pos];
       vdata.size = hash_concat->size - sha1pos;
 
+      ret = pubkey_verify_sig( NULL, &vdata, signature, pk_algo, 
+        cert->params, cert->params_size);
       /* verify signature */
-      if ((ret = _gnutls_dsa_verify (&vdata, signature, cert->params,
-                                     cert->params_size)) < 0)
+      if (ret < 0)
         {
           gnutls_assert ();
           return ret;
         }
 
       break;
-
     default:
       gnutls_assert ();
       return GNUTLS_E_INTERNAL_ERROR;
@@ -476,19 +415,13 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_cert * cert,
     }
   else
     {
-      gnutls_datum_t hash;
-
       _gnutls_hash_deinit (&td_sha, concat);
 
-      hash.data = concat;
-      hash.size = _gnutls_hash_get_algo_len (hash_algo);
       dconcat.data = concat;
-      dconcat.size = sizeof concat;
-
-      _gnutls_rsa_encode_sig (hash_algo, &hash, &dconcat);
+      dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
     }
 
-  ret = _gnutls_verify_sig (cert, &dconcat, signature,
+  ret = verify_tls_hash (ver, cert, &dconcat, signature,
                             dconcat.size -
                             _gnutls_hash_get_algo_len (hash_algo),
                             _gnutls_sign_get_pk_algorithm (algo));
@@ -520,6 +453,7 @@ _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
   gnutls_sign_algorithm_t _sign_algo;
   gnutls_digest_algorithm_t hash_algo;
   digest_hd_st *handshake_td;
+  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
 
   handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
   hash_algo = handshake_td->algorithm;
@@ -552,7 +486,7 @@ _gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
   dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
 
   ret =
-    _gnutls_verify_sig (cert, &dconcat, signature, 0,
+    verify_tls_hash (ver, cert, &dconcat, signature, 0,
                         cert->subject_pk_algorithm);
   if (ret < 0)
     {
@@ -651,7 +585,7 @@ _gnutls_handshake_verify_cert_vrfy (gnutls_session_t session,
   dconcat.size = 20 + 16;       /* md5+ sha */
 
   ret =
-    _gnutls_verify_sig (cert, &dconcat, signature, 16,
+    verify_tls_hash (ver, cert, &dconcat, signature, 16,
                         cert->subject_pk_algorithm);
   if (ret < 0)
     {
@@ -728,7 +662,7 @@ _gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
   dconcat.data = concat;
   dconcat.size = _gnutls_hash_get_algo_len (hash_algo);
 
-  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
+  ret = sign_tls_hash (session, hash_algo, cert, pkey, &dconcat, signature);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -838,7 +772,7 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
       gnutls_assert ();
       return GNUTLS_E_INTERNAL_ERROR;
     }
-  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
+  ret = sign_tls_hash (session, GNUTLS_DIG_NULL, cert, pkey, &dconcat, signature);
   if (ret < 0)
     {
       gnutls_assert ();