summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Rescorla <ekr@rtfm.com>2014-08-22 14:53:03 -0700
committerEric Rescorla <ekr@rtfm.com>2014-08-22 14:53:03 -0700
commit4f744cce049ddc65c81fd5776eefc1ee83c58df3 (patch)
tree0a8a2338d5de144d6d6ea5a25b2e40baad297fc3
parent3f8b5a6b86ff780d9fefde8b492f44b10e52f1a5 (diff)
downloadnss-hg-4f744cce049ddc65c81fd5776eefc1ee83c58df3.tar.gz
Bug 1057465: Negotiate TLS 1.3 draft and use extension to make sure we
have matching draft versions. r=mt,wtc.
-rw-r--r--lib/ssl/config.mk5
-rw-r--r--lib/ssl/dtlscon.c7
-rw-r--r--lib/ssl/ssl3ext.c99
-rw-r--r--lib/ssl/ssl3prot.h5
-rw-r--r--lib/ssl/sslimpl.h4
-rw-r--r--lib/ssl/sslproto.h4
-rw-r--r--lib/ssl/sslt.h5
7 files changed, 126 insertions, 3 deletions
diff --git a/lib/ssl/config.mk b/lib/ssl/config.mk
index da8b9ef77..40b1c301e 100644
--- a/lib/ssl/config.mk
+++ b/lib/ssl/config.mk
@@ -7,6 +7,11 @@ ifdef NISCC_TEST
DEFINES += -DNISCC_TEST
endif
+# Allow build-time configuration of TLS 1.3 (Experimental)
+ifdef NSS_ENABLE_TLS_1_3
+DEFINES += -DNSS_ENABLE_TLS_1_3
+endif
+
ifdef NSS_NO_PKCS11_BYPASS
DEFINES += -DNO_PKCS11_BYPASS
else
diff --git a/lib/ssl/dtlscon.c b/lib/ssl/dtlscon.c
index 4e3846199..89315eee0 100644
--- a/lib/ssl/dtlscon.c
+++ b/lib/ssl/dtlscon.c
@@ -52,6 +52,7 @@ static const ssl3CipherSuite nonDTLSSuites[] = {
* TLS DTLS
* 1.1 (0302) 1.0 (feff)
* 1.2 (0303) 1.2 (fefd)
+ * 1.3 (0304) 1.3 (fefc)
*/
SSL3ProtocolVersion
dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
@@ -62,6 +63,9 @@ dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
if (tlsv == SSL_LIBRARY_VERSION_TLS_1_2) {
return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
}
+ if (tlsv == SSL_LIBRARY_VERSION_TLS_1_3) {
+ return SSL_LIBRARY_VERSION_DTLS_1_3_WIRE;
+ }
/* Anything other than TLS 1.1 or 1.2 is an error, so return
* the invalid version 0xffff. */
@@ -85,6 +89,9 @@ dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
return SSL_LIBRARY_VERSION_TLS_1_2;
}
+ if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_3_WIRE) {
+ return SSL_LIBRARY_VERSION_TLS_1_3;
+ }
/* Return a fictional higher version than we know of */
return SSL_LIBRARY_VERSION_TLS_1_2 + 1;
diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
index 1d1f39cce..247f1f8f1 100644
--- a/lib/ssl/ssl3ext.c
+++ b/lib/ssl/ssl3ext.c
@@ -82,6 +82,11 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append,
static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
SECItem *data);
+static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
+static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data);
+
/*
* Write bytes. Using this function means the SECItem structure
* cannot be freed. The caller is expected to call this function
@@ -245,6 +250,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
{ ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
{ ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
{ ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
+ { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn },
{ -1, NULL }
};
@@ -286,7 +292,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
{ ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
{ ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
{ ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
/* any extra entries will appear as { 0, NULL } */
};
@@ -2421,3 +2428,93 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
return extensionLen;
}
+
+/* ssl3_ClientSendDraftVersionXtn sends the TLS 1.3 temporary draft
+ * version extension.
+ * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
+static PRInt32
+ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+{
+ PRInt32 extension_length;
+
+ if (ss->version != SSL_LIBRARY_VERSION_TLS_1_3) {
+ return 0;
+ }
+
+ extension_length = 6; /* Type + length + number */
+ if (append && maxBytes >= extension_length) {
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_draft_version_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_1_3_DRAFT_VERSION, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_tls13_draft_version_xtn;
+ } else if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ return extension_length;
+
+loser:
+ return -1;
+}
+
+/* ssl3_ServerHandleDraftVersionXtn handles the TLS 1.3 temporary draft
+ * version extension.
+ * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
+static SECStatus
+ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type,
+ SECItem *data)
+{
+ PRInt32 draft_version;
+
+ /* Ignore this extension if we aren't doing TLS 1.3 */
+ if (ss->version != SSL_LIBRARY_VERSION_TLS_1_3) {
+ return SECSuccess;
+ }
+
+ if (data->len != 2)
+ goto loser;
+
+ /* Get the draft version out of the handshake */
+ draft_version = ssl3_ConsumeHandshakeNumber(ss, 2,
+ &data->data, &data->len);
+ if (draft_version < 0) {
+ goto loser;
+ }
+
+ /* Keep track of negotiated extensions. */
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+
+ /* Compare the version */
+ if (draft_version != TLS_1_3_DRAFT_VERSION) {
+ SSL_TRC(30, ("%d: SSL3[%d]: Incompatible version of TLS 1.3 (%d), "
+ "expected %d",
+ SSL_GETPID(), ss->fd, draft_version, TLS_1_3_DRAFT_VERSION));
+ goto loser;
+ }
+
+ return SECSuccess;
+
+loser:
+ /*
+ * Incompatible/broken TLS 1.3 implementation. Fall back to TLS 1.2.
+ * TODO(ekr@rtfm.com): It's not entirely clear it's safe to roll back
+ * here. Need to double-check.
+ * TODO(ekr@rtfm.com): Currently we fall back even on broken extensions.
+ * because SECFailure does not cause handshake failures. See bug
+ * 753136.
+ */
+ SSL_TRC(30, ("%d: SSL3[%d]: Rolling back to TLS 1.2", SSL_GETPID(), ss->fd));
+ ss->version = SSL_LIBRARY_VERSION_TLS_1_2;
+
+ return SECSuccess;
+}
+
diff --git a/lib/ssl/ssl3prot.h b/lib/ssl/ssl3prot.h
index 223b240df..485d7dd38 100644
--- a/lib/ssl/ssl3prot.h
+++ b/lib/ssl/ssl3prot.h
@@ -14,6 +14,11 @@ typedef PRUint8 SSL3Opaque;
typedef PRUint16 SSL3ProtocolVersion;
/* version numbers are defined in sslproto.h */
+/* The TLS 1.3 draft version. Used to avoid negotiating
+ * between incompatible pre-standard TLS 1.3 drafts.
+ * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
+#define TLS_1_3_DRAFT_VERSION 3
+
typedef PRUint16 ssl3CipherSuite;
/* The cipher suites are defined in sslproto.h */
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index 7a4bd6109..858ae0cc9 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -1536,7 +1536,11 @@ extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch,
* runtime to determine which versions are supported by the version of libssl
* in use.
*/
+#ifdef NSS_ENABLE_TLS_1_3
+#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_3
+#else
#define SSL_LIBRARY_VERSION_MAX_SUPPORTED SSL_LIBRARY_VERSION_TLS_1_2
+#endif
/* Rename this macro SSL_ALL_VERSIONS_DISABLED when SSL 2.0 is removed. */
#define SSL3_ALL_VERSIONS_DISABLED(vrange) \
diff --git a/lib/ssl/sslproto.h b/lib/ssl/sslproto.h
index fff0ab8cb..e02442c09 100644
--- a/lib/ssl/sslproto.h
+++ b/lib/ssl/sslproto.h
@@ -16,9 +16,12 @@
#define SSL_LIBRARY_VERSION_TLS_1_0 0x0301
#define SSL_LIBRARY_VERSION_TLS_1_1 0x0302
#define SSL_LIBRARY_VERSION_TLS_1_2 0x0303
+#define SSL_LIBRARY_VERSION_TLS_1_3 0x0304
+
/* Note: this is the internal format, not the wire format */
#define SSL_LIBRARY_VERSION_DTLS_1_0 0x0302
#define SSL_LIBRARY_VERSION_DTLS_1_2 0x0303
+#define SSL_LIBRARY_VERSION_DTLS_1_3 0x0304
/* deprecated old name */
#define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0
@@ -26,6 +29,7 @@
/* The DTLS versions used in the spec */
#define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE ((~0x0100) & 0xffff)
#define SSL_LIBRARY_VERSION_DTLS_1_2_WIRE ((~0x0102) & 0xffff)
+#define SSL_LIBRARY_VERSION_DTLS_1_3_WIRE ((~0x0103) & 0xffff)
/* Header lengths of some of the messages */
#define SSL_HL_ERROR_HBYTES 3
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
index c22c820cd..1d28feb16 100644
--- a/lib/ssl/sslt.h
+++ b/lib/ssl/sslt.h
@@ -191,9 +191,10 @@ typedef enum {
ssl_padding_xtn = 21,
ssl_session_ticket_xtn = 35,
ssl_next_proto_nego_xtn = 13172,
- ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ ssl_renegotiation_info_xtn = 0xff01,
+ ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */
} SSLExtensionType;
-#define SSL_MAX_EXTENSIONS 10 /* doesn't include ssl_padding_xtn. */
+#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
#endif /* __sslt_h_ */