ClientHello Padding for Fast Radio Opening in 3G.
The ClientHello record is padded to 1024 bytes when
fastradio_padding is enabled. As a result, the 3G cellular radio
is fast forwarded to DCH (high data rate) state. This mechanism
leads to a substantial redunction in terms of TLS handshake
latency, and benefits mobile apps that are running on top of TLS.
Change-Id: I3d55197b6d601761c94c0f22871774b5a3dad614
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 535baeb..219cbf5 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3139,3 +3139,8 @@
{
return s->server;
}
+
+void SSL_enable_fastradio_padding(SSL *s, char on_off)
+ {
+ s->fastradio_padding = on_off;
+ }
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index fa506bd..4f93bda 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1144,17 +1144,33 @@
}
#ifdef TLSEXT_TYPE_padding
- /* Add padding to workaround bugs in F5 terminators.
- * See https://tools.ietf.org/html/draft-agl-tls-padding-03
- *
- * NB: because this code works out the length of all existing
- * extensions it MUST always appear last. */
if (header_len > 0)
{
+ size_t clienthello_minsize = 0;
header_len += ret - orig;
if (header_len > 0xff && header_len < 0x200)
{
- size_t padding_len = 0x200 - header_len;
+ /* Add padding to workaround bugs in F5 terminators.
+ * See https://tools.ietf.org/html/draft-agl-tls-padding-03
+ *
+ * NB: because this code works out the length of all existing
+ * extensions it MUST always appear last. */
+ clienthello_minsize = 0x200;
+ }
+ if (s->fastradio_padding)
+ {
+ /* Pad the ClientHello record to 1024 bytes to fast forward
+ * the radio into DCH (high data rate) state in 3G networks.
+ * Note that when fastradio_padding is enabled, even if the
+ * header_len is less than 255 bytes, the padding will be
+ * applied regardless. This is slightly different from the TLS
+ * padding extension suggested in
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03 */
+ clienthello_minsize = 0x400;
+ }
+ if (header_len < clienthello_minsize)
+ {
+ size_t padding_len = clienthello_minsize - header_len;
/* Extensions take at least four bytes to encode. Always
* include least one byte of data if including the
* extension. WebSphere Application Server 7.0 is
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 30cdab7..e04e44b 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -429,6 +429,7 @@
BIO_print_errors_fp(stdout);
return 1;
}
+ SSL_enable_fastradio_padding(ssl, config->fastradio_padding);
BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
if (bio == NULL) {
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 628c208..90c5294 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -582,6 +582,10 @@
// to require that all ClientHellos match in offered version
// across a renego.
RequireSameRenegoClientVersion bool
+
+ // RequireFastradioPadding, if true, requires that ClientHello messages
+ // be at least 1000 bytes long.
+ RequireFastradioPadding bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 4bdede1..284f314 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -120,6 +120,9 @@
c.sendAlert(alertUnexpectedMessage)
return false, unexpectedMessageError(hs.clientHello, msg)
}
+ if config.Bugs.RequireFastradioPadding && len(hs.clientHello.raw) < 1000 {
+ return false, errors.New("tls: ClientHello record size should be larger than 1000 bytes when padding enabled.")
+ }
if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest {
// Per RFC 6347, the version field in HelloVerifyRequest SHOULD
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 421940d..ecf80db 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -2156,6 +2156,29 @@
})
}
+func addFastRadioPaddingTests() {
+ testCases = append(testCases, testCase {
+ protocol: tls,
+ name: "FastRadio-Padding",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireFastradioPadding: true,
+ },
+ },
+ flags: []string{"-fastradio-padding"},
+ })
+ testCases = append(testCases, testCase {
+ protocol: dtls,
+ name: "FastRadio-Padding",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireFastradioPadding: true,
+ },
+ },
+ flags: []string{"-fastradio-padding"},
+ })
+}
+
var testHashes = []struct {
name string
id uint8
@@ -2337,6 +2360,7 @@
addRenegotiationTests()
addDTLSReplayTests()
addSigningHashTests()
+ addFastRadioPaddingTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index e8034ce..59874ef 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -65,6 +65,7 @@
{ "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
{ "-enable-signed-cert-timestamps",
&TestConfig::enable_signed_cert_timestamps },
+ { "-fastradio-padding", &TestConfig::fastradio_padding },
};
const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
@@ -124,7 +125,8 @@
renegotiate(false),
allow_unsafe_legacy_renegotiation(false),
enable_ocsp_stapling(false),
- enable_signed_cert_timestamps(false) {
+ enable_signed_cert_timestamps(false),
+ fastradio_padding(false) {
}
bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 5f050a8..f778c28 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -63,6 +63,7 @@
std::string expected_ocsp_response;
bool enable_signed_cert_timestamps;
std::string expected_signed_cert_timestamps;
+ bool fastradio_padding;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);