• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2index 8b8b758..882e356 100644
3--- a/nss/lib/ssl/ssl3con.c
4+++ b/nss/lib/ssl/ssl3con.c
5@@ -4975,6 +4975,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
6     PRBool           isTLS = PR_FALSE;
7     PRBool           requestingResume = PR_FALSE;
8     PRInt32          total_exten_len = 0;
9+    unsigned         paddingExtensionLen;
10     unsigned         numCompressionMethods;
11     PRInt32          flags;
12
13@@ -5241,6 +5242,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
14 	length += 1 + ss->ssl3.hs.cookieLen;
15     }
16
17+    /* A padding extension may be included to ensure that the record containing
18+     * the ClientHello doesn't have a length between 256 and 511 bytes
19+     * (inclusive). Initial, ClientHello records with such lengths trigger bugs
20+     * in F5 devices.
21+     *
22+     * This is not done for DTLS nor for renegotiation. */
23+    if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
24+        paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
25+        total_exten_len += paddingExtensionLen;
26+        length += paddingExtensionLen;
27+    } else {
28+        paddingExtensionLen = 0;
29+    }
30+
31     rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
32     if (rv != SECSuccess) {
33 	return rv;	/* err set by ssl3_AppendHandshake* */
34@@ -5360,6 +5375,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
35 	    return SECFailure;
36 	}
37 	maxBytes -= extLen;
38+
39+	extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
40+	if (extLen < 0) {
41+	    return SECFailure;
42+	}
43+	maxBytes -= extLen;
44+
45 	PORT_Assert(!maxBytes);
46     }
47     if (ss->ssl3.hs.sendingSCSV) {
48diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
49index 0415770..cdebcc9 100644
50--- a/nss/lib/ssl/ssl3ext.c
51+++ b/nss/lib/ssl/ssl3ext.c
52@@ -2297,3 +2297,56 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
53 loser:
54     return -1;
55 }
56+
57+unsigned int
58+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
59+{
60+    unsigned int recordLength = 1 /* handshake message type */ +
61+				3 /* handshake message length */ +
62+				clientHelloLength;
63+    unsigned int extensionLength;
64+
65+    if (recordLength < 256 || recordLength >= 512) {
66+	return 0;
67+    }
68+
69+     extensionLength = 512 - recordLength;
70+     /* Extensions take at least four bytes to encode. */
71+     if (extensionLength < 4) {
72+	 extensionLength = 4;
73+     }
74+
75+     return extensionLength;
76+}
77+
78+/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
79+ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
80+ * that we don't trigger bugs in F5 products. */
81+PRInt32
82+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
83+			    PRUint32 maxBytes)
84+{
85+    unsigned int paddingLen = extensionLen - 4;
86+    unsigned char padding[256];
87+
88+    if (extensionLen == 0) {
89+	return 0;
90+    }
91+
92+    if (extensionLen < 4 ||
93+	extensionLen > maxBytes ||
94+	paddingLen > sizeof(padding)) {
95+	PORT_Assert(0);
96+	return -1;
97+    }
98+
99+    if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
100+	return -1;
101+    if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
102+	return -1;
103+    memset(padding, 0, paddingLen);
104+    if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
105+	return -1;
106+
107+    return extensionLen;
108+}
109diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
110index 614eed1..9c789bf 100644
111--- a/nss/lib/ssl/sslimpl.h
112+++ b/nss/lib/ssl/sslimpl.h
113@@ -237,6 +237,13 @@ extern PRInt32
114 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
115                                const ssl3HelloExtensionSender *sender);
116
117+extern unsigned int
118+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
119+
120+extern PRInt32
121+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
122+			    PRUint32 maxBytes);
123+
124 /* Socket ops */
125 struct sslSocketOpsStr {
126     int         (*connect) (sslSocket *, const PRNetAddr *);
127diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
128index a8007d8..e4d188f 100644
129--- a/nss/lib/ssl/sslt.h
130+++ b/nss/lib/ssl/sslt.h
131@@ -205,9 +205,10 @@ typedef enum {
132     ssl_session_ticket_xtn           = 35,
133     ssl_next_proto_nego_xtn          = 13172,
134     ssl_channel_id_xtn               = 30031,
135+    ssl_padding_xtn                  = 35655,
136     ssl_renegotiation_info_xtn       = 0xff01	/* experimental number */
137 } SSLExtensionType;
138
139-#define SSL_MAX_EXTENSIONS             11
140+#define SSL_MAX_EXTENSIONS             11 /* doesn't include ssl_padding_xtn. */
141
142 #endif /* __sslt_h_ */
143