diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c index 8b8b758..882e356 100644 --- a/nss/lib/ssl/ssl3con.c +++ b/nss/lib/ssl/ssl3con.c @@ -4975,6 +4975,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) PRBool isTLS = PR_FALSE; PRBool requestingResume = PR_FALSE; PRInt32 total_exten_len = 0; + unsigned paddingExtensionLen; unsigned numCompressionMethods; PRInt32 flags; @@ -5241,6 +5242,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) { return rv; /* err set by ssl3_AppendHandshake* */ @@ -5360,6 +5375,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); } if (ss->ssl3.hs.sendingSCSV) { diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c index 0415770..cdebcc9 100644 --- a/nss/lib/ssl/ssl3ext.c +++ b/nss/lib/ssl/ssl3ext.c @@ -2297,3 +2297,56 @@ 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; + 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; + memset(padding, 0, paddingLen); + if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen)) + return -1; + + return extensionLen; +} diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h index 614eed1..9c789bf 100644 --- a/nss/lib/ssl/sslimpl.h +++ b/nss/lib/ssl/sslimpl.h @@ -237,6 +237,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/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h index a8007d8..e4d188f 100644 --- a/nss/lib/ssl/sslt.h +++ b/nss/lib/ssl/sslt.h @@ -205,9 +205,10 @@ typedef enum { ssl_session_ticket_xtn = 35, ssl_next_proto_nego_xtn = 13172, ssl_channel_id_xtn = 30031, + ssl_padding_xtn = 35655, ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ } SSLExtensionType; -#define SSL_MAX_EXTENSIONS 11 +#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */ #endif /* __sslt_h_ */