diff options
author | Eric Rescorla <ekr@rtfm.com> | 2014-08-22 14:53:03 -0700 |
---|---|---|
committer | Eric Rescorla <ekr@rtfm.com> | 2014-08-22 14:53:03 -0700 |
commit | 4f744cce049ddc65c81fd5776eefc1ee83c58df3 (patch) | |
tree | 0a8a2338d5de144d6d6ea5a25b2e40baad297fc3 | |
parent | 3f8b5a6b86ff780d9fefde8b492f44b10e52f1a5 (diff) | |
download | nss-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.mk | 5 | ||||
-rw-r--r-- | lib/ssl/dtlscon.c | 7 | ||||
-rw-r--r-- | lib/ssl/ssl3ext.c | 99 | ||||
-rw-r--r-- | lib/ssl/ssl3prot.h | 5 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 4 | ||||
-rw-r--r-- | lib/ssl/sslproto.h | 4 | ||||
-rw-r--r-- | lib/ssl/sslt.h | 5 |
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_ */ |