Reject tickets from the future.
This shouldn't happen, but it is good to check to avoid the potential
underflow in ssl_session_is_time_valid.
This required tweaking the mock clock in bssl_shim to stop going back in
time.
Change-Id: Id3ab8755139e989190d0b53d4bf90fe1ac203022
Reviewed-on: https://boringssl-review.googlesource.com/11841
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index c2396b1..2c20bc3 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -599,6 +599,12 @@
struct timeval now;
ssl_get_current_time(ssl, &now);
+
+ /* Reject tickets from the future to avoid underflow. */
+ if ((long)now.tv_sec < session->time) {
+ return 0;
+ }
+
return session->timeout >= (long)now.tv_sec - session->time;
}
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 1c4ba7f..55ac923 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -2047,6 +2047,9 @@
}
for (uint16_t version : kTLSVersions) {
+ static const int kStartTime = 1000;
+ g_current_time.tv_sec = kStartTime;
+
bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
if (!server_ctx || !client_ctx ||
@@ -2088,6 +2091,15 @@
fprintf(stderr, "Error resuming session (version = %04x).\n", version);
return false;
}
+
+ // Rewind the clock to before the session was minted.
+ g_current_time.tv_sec = kStartTime - 1;
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+ false /* expect session not reused */)) {
+ fprintf(stderr, "Error resuming session (version = %04x).\n", version);
+ return false;
+ }
}
return true;
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 2eee888..08b81f3 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -594,8 +594,10 @@
return config->psk.size();
}
+static timeval g_clock;
+
static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
- *out_clock = PacketedBioGetClock(GetTestState(ssl)->packeted_bio);
+ *out_clock = g_clock;
}
static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) {
@@ -923,9 +925,7 @@
SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
- if (config->is_dtls) {
- SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
- }
+ SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
@@ -1473,7 +1473,7 @@
return false;
}
if (config->is_dtls) {
- bssl::UniquePtr<BIO> packeted = PacketedBioCreate(!config->async);
+ bssl::UniquePtr<BIO> packeted = PacketedBioCreate(&g_clock, !config->async);
if (!packeted) {
return false;
}
@@ -1748,6 +1748,11 @@
return Usage(argv[0]);
}
+ // Some code treats the zero time special, so initialize the clock to a
+ // non-zero time.
+ g_clock.tv_sec = 1234;
+ g_clock.tv_usec = 1234;
+
bssl::UniquePtr<SSL_CTX> ssl_ctx = SetupCtx(&config);
if (!ssl_ctx) {
ERR_print_errors_fp(stderr);
diff --git a/ssl/test/packeted_bio.cc b/ssl/test/packeted_bio.cc
index f7267fc..8331b4b 100644
--- a/ssl/test/packeted_bio.cc
+++ b/ssl/test/packeted_bio.cc
@@ -31,10 +31,9 @@
const uint8_t kOpcodeTimeoutAck = 't';
struct PacketedBio {
- explicit PacketedBio(bool advance_clock_arg)
- : advance_clock(advance_clock_arg) {
+ PacketedBio(timeval *clock_arg, bool advance_clock_arg)
+ : clock(clock_arg), advance_clock(advance_clock_arg) {
memset(&timeout, 0, sizeof(timeout));
- memset(&clock, 0, sizeof(clock));
memset(&read_deadline, 0, sizeof(read_deadline));
}
@@ -47,14 +46,14 @@
return true;
}
- if (clock.tv_sec == read_deadline.tv_sec) {
- return clock.tv_usec < read_deadline.tv_usec;
+ if (clock->tv_sec == read_deadline.tv_sec) {
+ return clock->tv_usec < read_deadline.tv_usec;
}
- return clock.tv_sec < read_deadline.tv_sec;
+ return clock->tv_sec < read_deadline.tv_sec;
}
timeval timeout;
- timeval clock;
+ timeval *clock;
timeval read_deadline;
bool advance_clock;
};
@@ -66,10 +65,6 @@
return (PacketedBio *)bio->ptr;
}
-const PacketedBio *GetData(const BIO *bio) {
- return GetData(const_cast<BIO*>(bio));
-}
-
// ReadAll reads |len| bytes from |bio| into |out|. It returns 1 on success and
// 0 or -1 on error.
static int ReadAll(BIO *bio, uint8_t *out, size_t len) {
@@ -272,19 +267,15 @@
} // namespace
-bssl::UniquePtr<BIO> PacketedBioCreate(bool advance_clock) {
+bssl::UniquePtr<BIO> PacketedBioCreate(timeval *clock, bool advance_clock) {
bssl::UniquePtr<BIO> bio(BIO_new(&g_packeted_bio_method));
if (!bio) {
return nullptr;
}
- bio->ptr = new PacketedBio(advance_clock);
+ bio->ptr = new PacketedBio(clock, advance_clock);
return bio;
}
-timeval PacketedBioGetClock(const BIO *bio) {
- return GetData(bio)->clock;
-}
-
bool PacketedBioAdvanceClock(BIO *bio) {
PacketedBio *data = GetData(bio);
if (data == nullptr) {
@@ -295,10 +286,10 @@
return false;
}
- data->clock.tv_usec += data->timeout.tv_usec;
- data->clock.tv_sec += data->clock.tv_usec / 1000000;
- data->clock.tv_usec %= 1000000;
- data->clock.tv_sec += data->timeout.tv_sec;
+ data->clock->tv_usec += data->timeout.tv_usec;
+ data->clock->tv_sec += data->clock->tv_usec / 1000000;
+ data->clock->tv_usec %= 1000000;
+ data->clock->tv_sec += data->timeout.tv_sec;
memset(&data->timeout, 0, sizeof(data->timeout));
return true;
}
diff --git a/ssl/test/packeted_bio.h b/ssl/test/packeted_bio.h
index 07930d4..9d4cdcb 100644
--- a/ssl/test/packeted_bio.h
+++ b/ssl/test/packeted_bio.h
@@ -28,21 +28,18 @@
// PacketedBioCreate creates a filter BIO which implements a reliable in-order
-// blocking datagram socket. It internally maintains a clock and honors
-// |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| based on it.
+// blocking datagram socket. It uses the value of |*clock| as the clock and
+// honors |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| based on it.
//
// During a |BIO_read|, the peer may signal the filter BIO to simulate a
// timeout. If |advance_clock| is true, it automatically advances the clock and
// continues reading, subject to the read deadline. Otherwise, it fails
// immediately. The caller must then call |PacketedBioAdvanceClock| before
// retrying |BIO_read|.
-bssl::UniquePtr<BIO> PacketedBioCreate(bool advance_clock);
+bssl::UniquePtr<BIO> PacketedBioCreate(timeval *clock, bool advance_clock);
-// PacketedBioGetClock returns the current time for |bio|.
-timeval PacketedBioGetClock(const BIO *bio);
-
-// PacketedBioAdvanceClock advances |bio|'s internal clock and returns true if
-// there is a pending timeout. Otherwise, it returns false.
+// PacketedBioAdvanceClock advances |bio|'s clock and returns true if there is a
+// pending timeout. Otherwise, it returns false.
bool PacketedBioAdvanceClock(BIO *bio);