GNUTLS handshake errors and memory leaks (ECDHE related?)

Nikos Mavrogiannopoulos nmav at gnutls.org
Tue Jan 10 14:35:55 CET 2012


On Tue, Jan 10, 2012 at 11:44 AM, Yaroslav <yarosla at gmail.com> wrote:
> Hi!
> I have added SSL support to my web server (nxweb) using GNUTLS. The server
> has asynchronous architecture (based on epoll), where 4 threads run almost
> independently accepting and servicing client http connections. Therefore I
> am using GNUTLS in non-blocking mode.
> Platform: Ubuntu 11.10, x64, 4-core CPU.
> Linked with latest GNUTLS 3.0.11.
> Most of the time everything works fine. Benchmarks show significant speed
> advantage over nginx (which is build on OpenSSL). But sometimes there are
> handshake errors and also memory leaks, which might be bound to those
> errors.

Hello Yaroslav,
 Reply inline.

> I am attaching full valgrind log. Here are some excerpts:
> % valgrind --leak-check=full --show-reachable=yes
> dist/Debug/GNU-Linux-x86/nxweb
> ...
> 2012-01-10 13:47:25 [28704:0x71b9700]: gnutls handshake error -110 fatal=1

This error is GNUTLS_E_PREMATURE_TERMINATION and is returned if the
client does not properly terminate the session (using a closure alert
message) and instead terminates the tcp connection. GnuTLS reports it
as an error, but you could ignore it, if premature termination attacks
are not an issue.

> 2012-01-10 13:47:25 [28704:0x71b9700]: gnutls handshake error -10 fatal=1
This is GNUTLS_E_INVALID_SESSION. It might be returned when trying to
send or received from a session that is already terminated or
invalidated for a reason (if you could set a log level of 2 and set
the log function I could provide more details on the reason). It might
also be a good idea to use gnutls_strerror() to convert the numeric
errors to strings.

> 2012-01-10 13:46:51 [28704:0x71b9700]: gnutls handshake error -24 fatal=1

This is GNUTLS_E_DECRYPTION_FAILED. This is pretty strange to happen.
Could you provide more information with a log level of 2?

> ==28704== 47,952 bytes in 999 blocks are definitely lost in loss record 11
> of 11
> ==28704==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
> ==28704==    by 0x5F28908: __gmp_default_allocate (in
> /usr/lib/libgmp.so.10.0.1)
> ==28704==    by 0x5F3CF39: __gmpz_mul (in /usr/lib/libgmp.so.10.0.1)
> ==28704==    by 0x50ED444: ecc_projective_check_point
> (ecc_projective_check_point.c:60)

It seems there is an issue in ecc_project_check_point. Could you try
the attached patch?

> There are also other leaks related to gnutls_dh_params_generate2 and some

Those should have been fixed in the repository.

> error messages related to gnutls_certificate_set_x509_key_file but those are
> of less importance to me as they happen only once on server startup.

I'll check about gnutls_certificate_set_x509_key_file() later.

> The problems might be related to ECDHE algorithm. There were no handshake
> errors when 'PERFORMANCE:%SERVER_PRECEDENCE' priority string was used.

With which string did you see the errors? Do you know which
ciphersuite was negotiated? (gnutls_cipher_suite_get_name)

> And there seemed to be no such leaks when there were no handshake erros.

btw. from the logs I see that the version of libtasn1 you have doesn't
compile well with
the gcc you have. You can use the included libtasn1 to avoid the
valgrind warnings.

I would be interested on your results in performance. Do you use a CPU
with AES-NI or padlock for the tests?

regards,
Nikos
-------------- next part --------------
diff --git a/lib/nettle/ecc_projective_check_point.c b/lib/nettle/ecc_projective_check_point.c
index 42abeea..5649779 100644
--- a/lib/nettle/ecc_projective_check_point.c
+++ b/lib/nettle/ecc_projective_check_point.c
@@ -42,17 +42,17 @@ int ecc_projective_check_point (ecc_point * P, mpz_t b, mpz_t modulus)
     if (P == NULL || b == NULL || modulus == NULL)
 	return -1;
 
-    if ((err = mp_init_multi (&t1, &t2, &t3, NULL)) != 0)
-      {
-	  return err;
-      }
-
     if (mpz_cmp_ui (P->z, 1) != 0)
       {
 	  gnutls_assert ();
 	  return -1;
       }
 
+    if ((err = mp_init_multi (&t1, &t2, &t3, NULL)) != 0)
+      {
+	  return err;
+      }
+
     /* t1 = Z * Z */
     mpz_mul (t1, P->y, P->y);
     mpz_mod (t1, t1, modulus);	/* t1 = y^2 */
@@ -95,12 +95,16 @@ int ecc_projective_check_point (ecc_point * P, mpz_t b, mpz_t modulus)
 
     if (mpz_cmp_ui (t1, 0) != 0)
       {
-	  return -1;
+	  err = -1;
       }
     else
       {
-	  return 0;
+	  err = 0;
       }
+
+    mp_clear_multi(&t1, &t2, &t3, NULL);
+    
+    return err;
 }
 
 #endif


More information about the Gnutls-devel mailing list