#35 TLSv1.3 support (WIP)
Closed 6 years ago by rcritten. Opened 7 years ago by cheimes.
cheimes/mod_nss tls13  into  master

file modified
+1 -1
@@ -22,7 +22,7 @@ 

  

  ## Set the includes and libraries needed

  AM_CPPFLAGS = -I@apache_inc@ @nspr_inc@ @nss_inc@ @apr_inc@

- LIBS = @nspr_lib@ @nss_lib@ -lssl3 -lsmime3 -lnss3 -lplc4 -lplds4 -lnspr4

+ LIBS = @nspr_lib@ @nss_lib@ -lssl3 -lsmime3 -lnss3 -lplc4 -lplds4 -lnspr4 -lnssutil3

  EXTRA_CPPFLAGS=@extra_cppflags@

  

  install-libLTLIBRARIES: libmodnss.la

file modified
+7
@@ -175,6 +175,13 @@ 

  typedef int nss_opt_t;

  

  /*

+  * TLS 1.3 is available since NSS 3.28

+  */

+ #if (((NSS_VMAJOR == 3) && (NSS_VMINOR >= 28)) || (NSS_VMAJOR > 3))

+   #define NSS_SUPPORTS_TLS_1_3 1

+ #endif

+ 

+ /*

   * Define the SSL requirement structure

   */

  typedef struct {

file modified
+2 -2
@@ -26,7 +26,7 @@ 

  URL: http://directory.fedora.redhat.com/

  Source: %{name}-%{version}.tar.gz

  BuildRoot: %{_tmppath}/%{name}-%{version}-root

- BuildPreReq: httpd-devel,apr-devel

+ BuildRequires: httpd-devel,apr-devel,nss-devel,flex,byacc

  # Without Autoreq: 0, rpmbuild finds all sorts of crazy

  # dependencies that we don't care about, and refuses to install

  Autoreq: 0
@@ -56,7 +56,7 @@ 

  

  # configure requires nspr, nss, ldapsdk, adminutil

  # if can't find apxs, use --with-apxs=/path/to/apxs

- ./configure --with-apr-config --with-nspr-inc=%{nsprincdir} --with-nspr-lib=%{nsprlibdir} --with-nss-inc=%{nssincdir} --with-nss-lib=%{nsslibdir}

+ ./configure --with-apr-config --with-nspr-inc=%{nsprincdir} --with-nspr-lib=%{nsprlibdir} --with-nss-inc=%{nssincdir} --with-nss-lib=%{nsslibdir} --enable-ecc

  CFLAGS="$flag $mycflags" make

  

  %install

file modified
+14 -3
@@ -123,6 +123,15 @@ 

      {"ecdhe_ecdsa_chacha20_poly1305_sha_256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "ECDHE-ECDSA-CHACHA20-POLY1305", SSL_kEECDH|SSL_aECDSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256},

      {"dhe_rsa_chacha20_poly1305_sha_256", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "DHE-RSA-CHACHA20-POLY1305", SSL_kEDH|SSL_aRSA|SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_2, SSL_HIGH, 256, 256},

  #endif

+ #ifdef NSS_SUPPORTS_TLS_1_3

+     /* Special TLS 1.3 cipher suites that really just specify AEAD

+      * TLS 1.3 ciphers don't specify key exchange and authentication.

+      */

+     {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256, "TLS13-AES-128-GCM-SHA256", SSL_AES128GCM|SSL_AEAD, TLSV1_3, SSL_HIGH, 128, 128, NULL},

+     /* OpenSSL has not agreed on names for AES 256 and ChaCha20 TLS 1.3 ciphers yet */

+     {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384, "TLS13-AES-256-GCM-SHA384", SSL_AES256GCM|SSL_AEAD, TLSV1_3, SSL_HIGH, 256, 256, NULL},

+     {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256, "TLS13-CHACHA20-POLY1305", SSL_CHACHA20POLY1305|SSL_AEAD, TLSV1_3, SSL_HIGH, 256, 256},

+ #endif

  };

  

  #define CIPHERNUM sizeof(ciphers_def) / sizeof(cipher_properties)
@@ -170,11 +179,11 @@ 

          rv = parse_nss_ciphers(s, ciphers, cipher_list);

      } else {

          rv = parse_openssl_ciphers(s, ciphers, cipher_list);

-         if (rv == 0 && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {

+         if (rv == 0 && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3)) {

              rv = parse_nss_ciphers(s, ciphers, cipher_list);

          }

      }

-     if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2)) {

+     if (0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3)) {

          ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,

                       "no cipher match");

      }
@@ -406,6 +415,8 @@ 

                      protocol |= TLSV1;

                  } else if (!strcmp(cipher, "TLSv1.2")) {

                      protocol |= TLSV1_2;

+                 } else if (!strcmp(cipher, "TLSv1.3")) {

+                     protocol |= TLSV1_3;

                  } else if (!strcmp(cipher, "HIGH")) {

                      strength |= SSL_HIGH;

                  } else if (!strcmp(cipher, "MEDIUM")) {
@@ -493,7 +504,7 @@ 

              cipher = ciphers;

  

      }

-     if (found && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2))

+     if (found && 0 == countciphers(cipher_list, SSLV3|TLSV1|TLSV1_2|TLSV1_3))

          return 1; /* no matching ciphers */

      return 0;

  }

file modified
+1
@@ -86,6 +86,7 @@ 

  #define SSLV3              0x00000002L

  #define TLSV1              SSLV3

  #define TLSV1_2            0x00000004L

+ #define TLSV1_3            0x00000005L

  

  /* the table itself is defined in nss_engine_cipher.c */

  #if 0

file modified
+57 -4
@@ -744,6 +744,9 @@ 

                                    modnss_ctx_t *mctx)

  {

      int ssl3, tls, tls1_1, tls1_2;

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+     int tls1_3 = 0;

+ #endif

      char *protocol_marker = NULL;

      char *lprotocols = NULL;

      SECStatus stat;
@@ -766,16 +769,27 @@ 

      }

  

      if (mctx->auth.protocols == NULL) {

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,

+             "%s value not set; using: TLSv1.0, TLSv1.1, TLSv1.2, and TLSv1.3",

+             protocol_marker);

+         tls = tls1_1 = tls1_2 = tls1_3 = 1;

+ #else

          ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,

-             "%s value not set; using: TLSv1.0, TLSv1.1 and TLSv1.2",

+             "%s value not set; using: TLSv1.0, TLSv1.1, and TLSv1.2",

              protocol_marker);

          tls = tls1_1 = tls1_2 = 1;

+ #endif

      } else {

          lprotocols = strdup(mctx->auth.protocols);

          ap_str_tolower(lprotocols);

  

          if (strstr(lprotocols, "all") != NULL) {

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+             ssl3 = tls = tls1_1 = tls1_2 = tls1_3 = 1;

+ #else

              ssl3 = tls = tls1_1 = tls1_2 = 1;

+ #endif

          } else {

              char *protocol_list = NULL;

              char *saveptr = NULL;
@@ -823,6 +837,13 @@ 

                                   "%s:  Enabling TLSv1.2",

                                   protocol_marker);

                      tls1_2 = 1;

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+                 } else if (strcmp(token, "tlsv1.3") == 0) {

+                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

+                                  "%s:  Enabling TLSv1.3",

+                                  protocol_marker);

+                     tls1_3 = 1;

+ #endif

                  } else {

                      ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,

                                   "%s:  Unknown protocol '%s' not supported",
@@ -837,12 +858,21 @@ 

           * if FIPS mode is enabled with no TLS protocols,

           * enable ALL TLS protocols.

           */

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+         if ((mctx->sc->fips) && (tls == 0) && (tls1_1 == 0) && (tls1_2 == 0) && (tls1_3 == 0)) {

+             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,

+                 "%s: FIPS mode no valid protocols set, enabling TLSv1.0, TLSv1.1, TLSv1.2 and TLSv1.3",

+                 protocol_marker);

+             tls = tls1_1 = tls1_2 = tls1_3 = 1;

+         }

+ #else

          if ((mctx->sc->fips) && (tls == 0) && (tls1_1 == 0) && (tls1_2 == 0)) {

              ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,

-                 "%s: FIPS mode no valid protocols set, enabling TLSv1.0, TLSv1.1 and TLSv1.2",

+                 "%s: FIPS mode no valid protocols set, enabling TLSv1.0, TLSv1.1, and TLSv1.2",

                  protocol_marker);

              tls = tls1_1 = tls1_2 = 1;

          }

+ #endif

      }

  

      stat = SSL_OptionSet(mctx->model, SSL_ENABLE_SSL2, PR_FALSE);
@@ -869,7 +899,7 @@ 

      if (stat == SECSuccess) {

          /* Set minimum protocol version (lowest -> highest)

           *

-          *     SSL 3.0 -> TLS 1.0 -> TLS 1.1 -> TLS 1.2

+          *     SSL 3.0 -> TLS 1.0 -> TLS 1.1 -> TLS 1.2 -> TLS 1.3

           */

          if (ssl3 == 1) {

              enabledVersions.min = SSL_LIBRARY_VERSION_3_0;
@@ -891,6 +921,13 @@ 

              ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

                           "%s:  [TLS 1.2] (minimum)",

                           protocol_marker);

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+         } else if (tls1_3 == 1) {

+             enabledVersions.min = SSL_LIBRARY_VERSION_TLS_1_3;

+             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

+                          "%s:  [TLS 1.3] (minimum)",

+                          protocol_marker);

+ #endif

          } else {

              /* Set default minimum protocol version to SSL 3.0 */

              enabledVersions.min = SSL_LIBRARY_VERSION_3_0;
@@ -901,9 +938,18 @@ 

  

          /* Set maximum protocol version (highest -> lowest)

           *

-          *     TLS 1.2 -> TLS 1.1 -> TLS 1.0 -> SSL 3.0

+          *     TLS 1.3 -> TLS 1.2 -> TLS 1.1 -> TLS 1.0 -> SSL 3.0

           */

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+         if (tls1_3 == 1) {

+             enabledVersions.max = SSL_LIBRARY_VERSION_TLS_1_3;

+             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

+                          "%s:  [TLS 1.3] (maximum)",

+                          protocol_marker);

+         } else if (tls1_2 == 1) {

+ #else

          if (tls1_2 == 1) {

+ #endif

              enabledVersions.max = SSL_LIBRARY_VERSION_TLS_1_2;

              ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

                           "%s:  [TLS 1.2] (maximum)",
@@ -938,12 +984,19 @@ 

          ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,

                  "%s:  SSL/TLS protocol initialization failed.",

                  protocol_marker);

+         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,

+                 "Enabled versions: min 0x%04x, max 0x%04x",

+                 enabledVersions.min, enabledVersions.max);

          nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);

          nss_die();

      }

  

      mctx->ssl3 = ssl3;

+ #ifdef  NSS_SUPPORTS_TLS_1_3

+     mctx->tls = tls || tls1_1 || tls1_2 || tls1_3;

+ #else

      mctx->tls = tls || tls1_1 || tls1_2;

+ #endif

  

      ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,

          "%sabling TLS Session Tickets", mctx->sc->session_tickets == PR_TRUE ? "En" : "Dis");

file modified
+5
@@ -775,6 +775,11 @@ 

                  case SSL_LIBRARY_VERSION_TLS_1_2:

                      result = "TLSv1.2";

                      break;

+ #ifdef NSS_SUPPORTS_TLS_1_3

+                 case SSL_LIBRARY_VERSION_TLS_1_3:

+                     result = "TLSv1.3";

+                     break;

+ #endif

              }

          }

      }

Starting with NSS 3.28, TLS 1.3 support is available in upstream. TLS
1.3 needs both a new configuration constant and a set of new ciphers.
The latest version of TLS does not have any cipher suites in common with
TLS 1.2 and older.

The patch is based on initial work by Franziskus.

NSS 3.28 in Fedora has TLS 1.3 disabled, https://pagure.io/mod_nss/issue/27#comment-143043

Closes: https://pagure.io/mod_nss/issue/27
Signed-off-by: Christian Heimes cheimes@redhat.com

rebased

7 years ago

I created some experimental builds of NSS, mod_nss and python-nss in my personal COPR https://copr.fedorainfracloud.org/coprs/cheimes/nss/ . After some adjustments I'm successfully able to create TLS 1.3 connections from python-nss and Firefox nightly builds.

The require safe renegotiation option is causing problems with TLS 1.3. I reported the problem in https://bugzilla.redhat.com/show_bug.cgi?id=1423401

NSSRequireSafeNegotiation off
NSSCipherSuite +aes_128_gcm_sha_256,+chacha20_poly1305_sha_256
NSSProtocol TLSv1.3
$ venv/bin/python doc/examples/ssl_cipher_info.py -d /home/heimes/redhat/pki-vagans/ipa/inventory/nssdb -H master.ipa.example -E
SSL connect to: master.ipa.example
try connecting to: 192.168.121.252
connected to: 192.168.121.252
handshake complete, peer = 192.168.121.252, negotiated host = master.ipa.example
Connection Info:
SSL Protocol Version: 3.4 (tls1.3)
Cipher:               128-bit AES-GCM
MAC:                  128-bit AEAD
Auth:                 2048-bit TLS 1.3
Key Exchange:         255-bit TLS 1.3
Compression:          NULL

Channel:
--------
Protocol Version:      3.4 (tls1.3)
Cipher Suite:          TLS_AES_128_GCM_SHA256 (0x1301)
Auth Key Bits:         2048
Key Exchange Key Bits: 255
Creation Time:         1970-01-01 01:00:00
Last Access Time:      1970-01-01 01:00:00
Expiration Time:       1970-01-01 01:00:00
Compression Method:    NULL (0x0)
Session ID:

Suite:
------
Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Auth Algorithm:               TLS 1.3 (0xa)
    Key Exchange Type:            TLS 1.3 (0x7)
    Symmetric Cipher:             AES-GCM (0xa)
    Symmetric Key Bits:           128
    Effective Symmetric Key Bits: 128
    Symmetric Key Space:          128
    MAC Algorithm:                AEAD (0x6)
    MAC Bits:                     128
    FIPS:                         True
    Exportable:                   False
    Nonstandard:                  False

This generally looks good. I think I'd like to wait until at least the BZ gets fixed before committing upstream.

No movement on the BZ yet. Reconfirmed that it is still broken.

The safe renegotiation bug seems to be fixed in NSS 3.33:
https://bugzilla.mozilla.org/show_bug.cgi?id=1375837

I pushed this manually along with an update to the documentation.

Pull-Request has been closed by rcritten

6 years ago