summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@chromium.org>2014-01-13 19:47:44 -0800
committerAdam Langley <agl@chromium.org>2014-01-13 19:47:44 -0800
commitee4467cf05108949099bc3faad71187c7e508975 (patch)
tree0bd7ac9d897165f576b6319265fd3527986ed175
parentd7fcd4f1d234e9c3d5a54f9e0045ed39ec74617c (diff)
downloadnss-hg-ee4467cf05108949099bc3faad71187c7e508975.tar.gz
Bug 944157: Implement the TLS padding extension, r=briansmith, r=wtc
-rw-r--r--lib/ssl/ssl3con.c22
-rw-r--r--lib/ssl/ssl3ext.c52
-rw-r--r--lib/ssl/sslimpl.h7
-rw-r--r--lib/ssl/sslt.h3
4 files changed, 83 insertions, 1 deletions
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index a7144ea9a..4509ba581 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -4840,6 +4840,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
int actual_count = 0;
PRBool isTLS = PR_FALSE;
PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
unsigned numCompressionMethods;
PRInt32 flags;
@@ -5113,6 +5114,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
length += 1 + ss->ssl3.hs.cookieLen;
}
+ /* A padding extension may be included to ensure that the record containing
+ * the ClientHello doesn't have a length between 256 and 511 bytes
+ * (inclusive). Initial, ClientHello records with such lengths trigger bugs
+ * in F5 devices.
+ *
+ * This is not done for DTLS nor for renegotiation. */
+ if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
+ paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
+ total_exten_len += paddingExtensionLen;
+ length += paddingExtensionLen;
+ } else {
+ paddingExtensionLen = 0;
+ }
+
rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
if (rv != SECSuccess) {
if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); }
@@ -5247,6 +5262,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
return SECFailure;
}
maxBytes -= extLen;
+
+ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+ if (extLen < 0) {
+ return SECFailure;
+ }
+ maxBytes -= extLen;
+
PORT_Assert(!maxBytes);
}
diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c
index da42bfd48..d75d458b6 100644
--- a/lib/ssl/ssl3ext.c
+++ b/lib/ssl/ssl3ext.c
@@ -2141,3 +2141,55 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
loser:
return -1;
}
+
+unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+{
+ unsigned int recordLength = 1 /* handshake message type */ +
+ 3 /* handshake message length */ +
+ clientHelloLength;
+ unsigned int extensionLength;
+
+ if (recordLength < 256 || recordLength >= 512) {
+ return 0;
+ }
+
+ extensionLength = 512 - recordLength;
+ /* Extensions take at least four bytes to encode. */
+ if (extensionLength < 4) {
+ extensionLength = 4;
+ }
+
+ return extensionLength;
+}
+
+/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
+ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
+ * that we don't trigger bugs in F5 products. */
+PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes)
+{
+ unsigned int paddingLen = extensionLen - 4;
+ static unsigned char padding[256];
+
+ if (extensionLen == 0) {
+ return 0;
+ }
+
+ if (extensionLen < 4 ||
+ extensionLen > maxBytes ||
+ paddingLen > sizeof(padding)) {
+ PORT_Assert(0);
+ return -1;
+ }
+
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
+ return -1;
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
+ return -1;
+ if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
+ return -1;
+
+ return extensionLen;
+}
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index eaf17af3f..3750c2134 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -226,6 +226,13 @@ extern PRInt32
ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
const ssl3HelloExtensionSender *sender);
+extern unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
+
+extern PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes);
+
/* Socket ops */
struct sslSocketOpsStr {
int (*connect) (sslSocket *, const PRNetAddr *);
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
index 6b9362934..350c1bbd7 100644
--- a/lib/ssl/sslt.h
+++ b/lib/ssl/sslt.h
@@ -189,9 +189,10 @@ typedef enum {
ssl_use_srtp_xtn = 14,
ssl_session_ticket_xtn = 35,
ssl_next_proto_nego_xtn = 13172,
+ ssl_padding_xtn = 35655,
ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
} SSLExtensionType;
-#define SSL_MAX_EXTENSIONS 9
+#define SSL_MAX_EXTENSIONS 9 /* doesn't include ssl_padding_xtn. */
#endif /* __sslt_h_ */