GnuTLS 3.6.7 cipher strings
authorJeremy Harris <jgh146exb@wizmail.org>
Thu, 25 Apr 2019 16:07:35 +0000 (17:07 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Thu, 25 Apr 2019 16:59:39 +0000 (17:59 +0100)
doc/doc-txt/ChangeLog
src/src/tls-gnu.c
test/log/5821
test/runtest

index 2c57ce64b63d38f20b4e9c612bf63cae42f9eb25..a85841af63f60f462d5a49611a0396814abd94a8 100644 (file)
@@ -80,6 +80,15 @@ HS/02 Bug 2392: exigrep does case sensitive *option* processing (as it
 JH/15 Use unsigned when creating bitmasks in macros, to avoid build errors
       on some platforms for bit 31.
 
 JH/15 Use unsigned when creating bitmasks in macros, to avoid build errors
       on some platforms for bit 31.
 
+JH/16 GnuTLS: rework ciphersuite strings under recent library versions.  Thanks
+      to changes apparently associated with TLS1.3 handling some of the APIs
+      previously used were either nonfunctional or inappropriate.  Strings
+      like TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM__AEAD:256
+      and TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_128_CBC__SHA256:128 replace
+      the previous TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 .
+      This affects log line X= elements, the $tls_{in,out}_cipher variables,
+      and the use of specific cipher names in the encrypted= ACL condition.
+
 
 Exim version 4.92
 -----------------
 
 Exim version 4.92
 -----------------
index 7fc88c002a3c3926b0ff35e8da713e074b44dbd1..abf2c25b8058f589f1d2366fcca6e178fe66669d 100644 (file)
@@ -1516,11 +1516,40 @@ state->peerdn = NULL;
 cipher = gnutls_cipher_get(state->session);
 protocol = gnutls_protocol_get_version(state->session);
 mac = gnutls_mac_get(state->session);
 cipher = gnutls_cipher_get(state->session);
 protocol = gnutls_protocol_get_version(state->session);
 mac = gnutls_mac_get(state->session);
-kx = gnutls_kx_get(state->session);
+kx = protocol < GNUTLS_TLS1_3 ? gnutls_kx_get(state->session) : 0;
 
 old_pool = store_pool;
   {
   store_pool = POOL_PERM;
 
 old_pool = store_pool;
   {
   store_pool = POOL_PERM;
+
+#ifdef SUPPORT_GNUTLS_SESS_DESC
+    {
+    gstring * g = NULL;
+    uschar * s = US gnutls_session_get_desc(state->session), c;
+
+    /* Nikos M suggests we use this by preference.  It returns like:
+    (TLS1.3)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
+
+    For partial back-compat, put a colon after the TLS version, replace the
+    )-( grouping with __, replace in-group - with _ and append the :keysize. */
+
+    /* debug_printf("peer_status: gnutls_session_get_desc %s\n", s); */
+
+    for (s++; (c = *s) && c != ')'; s++) g = string_catn(g, s, 1);
+    g = string_catn(g, US":", 1);
+    if (*s) s++;               /* now on _ between groups */
+    while ((c = *s))
+      {
+      for (*++s && ++s; (c = *s) && c != ')'; s++) g = string_catn(g, c == '-' ? US"_" : s, 1);
+      /* now on ) closing group */
+      if ((c = *s) && *++s == '-') g = string_catn(g, US"__", 2);
+      /* now on _ between groups */
+      }
+    g = string_catn(g, US":", 1);
+    g = string_cat(g, string_sprintf("%d", (int) gnutls_cipher_get_key_size(cipher) * 8));
+    state->ciphersuite = string_from_gstring(g);
+    }
+#else
   state->ciphersuite = string_sprintf("%s:%s:%d",
       gnutls_protocol_get_name(protocol),
       gnutls_cipher_suite_get_name(kx, cipher, mac),
   state->ciphersuite = string_sprintf("%s:%s:%d",
       gnutls_protocol_get_name(protocol),
       gnutls_cipher_suite_get_name(kx, cipher, mac),
@@ -1531,7 +1560,12 @@ old_pool = store_pool;
   releases did return "TLS 1.0"; play it safe, just in case. */
 
   for (uschar * p = state->ciphersuite; *p; p++) if (isspace(*p)) *p = '-';
   releases did return "TLS 1.0"; play it safe, just in case. */
 
   for (uschar * p = state->ciphersuite; *p; p++) if (isspace(*p)) *p = '-';
+#endif
+
+/* debug_printf("peer_status: ciphersuite %s\n", state->ciphersuite); */
+
   state->tlsp->cipher = state->ciphersuite;
   state->tlsp->cipher = state->ciphersuite;
+  state->tlsp->bits = gnutls_cipher_get_key_size(cipher) * 8;
 
   state->tlsp->cipher_stdname = cipher_stdname_kcm(kx, cipher, mac);
   }
 
   state->tlsp->cipher_stdname = cipher_stdname_kcm(kx, cipher, mac);
   }
index d94c7c6fdabc94da8f76c4faaf928b9bd7308bd0..98282ecc2e88ec8205109586ac8d7a520ffe07c6 100644 (file)
@@ -8,7 +8,7 @@
 1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@localhost.test.ex R=client T=send_to_server H=localhost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane256ee.test.ex
 1999-03-02 09:44:33 10HmbB-0005vi-00 => CALLER@localhost.test.ex R=client T=send_to_server H=localhost.test.ex [127.0.0.1] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=yes DN="CN=server1.example.com" C="250 OK id=10HmbC-0005vi-00"
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for CALLER@dane256ee.test.ex
-1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane256ee.test.ex R=client T=send_to_server H=dane256ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.2:RSA_CAMELLIA_256_GCM_SHA384:256 CV=dane DN="CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
+1999-03-02 09:44:33 10HmbD-0005vi-00 => CALLER@dane256ee.test.ex R=client T=send_to_server H=dane256ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256 CV=dane DN="CN=server1.example.com" C="250 OK id=10HmbE-0005vi-00"
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
 
 ******** SERVER ********
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
 
 ******** SERVER ********
@@ -26,6 +26,6 @@
 1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@localhost.test.ex> R=server
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 "rcpt ACL"
 1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@localhost.test.ex> R=server
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 "rcpt ACL"
-1999-03-02 09:44:33 10HmbE-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.2:RSA_CAMELLIA_256_GCM_SHA384:256 CV=no S=sss id=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane256ee.test.ex
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256 CV=no S=sss id=E10HmbD-0005vi-00@myhost.test.ex for CALLER@dane256ee.test.ex
 1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@dane256ee.test.ex> R=server
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbE-0005vi-00 => :blackhole: <CALLER@dane256ee.test.ex> R=server
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
index 3b572c1559f42af914debf6c5efbf6183d73c8ef..d7e4325e3999adbb94ed2bb8d082d86df7a7e0fe 100755 (executable)
@@ -604,11 +604,18 @@ RESET_AFTER_EXTRA_LINE_READ:
 
   # GnuTLS have seen:
   #   TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256
 
   # GnuTLS have seen:
   #   TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256
+  #   TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM__AEAD:256
+  #   TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256
+  #   TLS1.3:ECDHE_PSK_SECP256R1__AES_256_GCM__AEAD:256
   #
   #   TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256
   #   TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128
   #   TLS1.2:RSA_AES_256_CBC_SHA1:256 (canonical)
   #   TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128
   #
   #   TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256
   #   TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128
   #   TLS1.2:RSA_AES_256_CBC_SHA1:256 (canonical)
   #   TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128
+  #   TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_256_GCM:256
+  #   TLS1.2:ECDHE_SECP256R1__RSA_SHA256__AES_128_CBC__SHA256:128
+  #   TLS1.2:ECDHE_SECP256R1__ECDSA_SHA512__AES_256_GCM:256
+  #   TLS1.2:RSA__CAMELLIA_256_GCM:256 (leave the cipher name)
   #
   #   X=TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256
   #   X=TLS1.2:RSA_AES_256_CBC_SHA1:256
   #
   #   X=TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256
   #   X=TLS1.2:RSA_AES_256_CBC_SHA1:256
@@ -620,7 +627,17 @@ RESET_AFTER_EXTRA_LINE_READ:
   #   DHE-RSA-AES256-SHA
   # picking latter as canonical simply because regex easier that way.
   s/\bDHE_RSA_AES_128_CBC_SHA1:128/RSA-AES256-SHA1:256/g;
   #   DHE-RSA-AES256-SHA
   # picking latter as canonical simply because regex easier that way.
   s/\bDHE_RSA_AES_128_CBC_SHA1:128/RSA-AES256-SHA1:256/g;
-  s/TLS1.[0123]:((EC)?DHE_)?(RSA|ECDSA)_AES_(256|128)_(CBC|GCM)_SHA(1|256|384):(256|128)/TLS1.x:ke-$3-AES256-SHAnnn:xxx/g;
+  s/TLS1.[0123]:                                               # TLS version
+       ((EC)?DHE(_((?<psk>PSK)_)?(SECP256R1|X25519))?__?)?     # key-exchange
+       ((?<auth>RSA|ECDSA)((_PSS_RSAE)?_SHA(512|256))?__?)?    # authentication
+       AES_(256|128)_(CBC|GCM)                                 # cipher
+       (__?SHA(1|256|384))?:                                   # PRF
+       (256|128)                                               # cipher strength
+    /"TLS1.x:ke-"
+       . (defined($+{psk}) ? $+{psk} : "")
+       . (defined($+{auth}) ? $+{auth} : "")
+       . "-AES256-SHAnnn:xxx"/genx;
+  s/TLS1.2:RSA__CAMELLIA_256_GCM(_SHA384)?:256/TLS1.2:RSA_CAMELLIA_256_GCM-SHAnnn:256/g;
   s/\b(ECDHE-(RSA|ECDSA)-AES256-SHA|DHE-RSA-AES256-SHA256)\b/ke-$2-AES256-SHAnnn/g;
 
   # GnuTLS library error message changes
   s/\b(ECDHE-(RSA|ECDSA)-AES256-SHA|DHE-RSA-AES256-SHA256)\b/ke-$2-AES256-SHAnnn/g;
 
   # GnuTLS library error message changes