Convert the session ticket extension to the new system.
Change-Id: I3893db92e87c0c041fe4ab489e867706902f1c43
Reviewed-on: https://boringssl-review.googlesource.com/5361
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 63bba59..f857bc9 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1185,6 +1185,86 @@
return 1;
}
+
+/* Session tickets.
+ *
+ * https://tools.ietf.org/html/rfc5077 */
+
+static int ext_ticket_add_clienthello(SSL *ssl, CBB *out) {
+ if (SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
+ return 1;
+ }
+
+ const uint8_t *ticket_data = NULL;
+ int ticket_len = 0;
+
+ /* Renegotiation does not participate in session resumption. However, still
+ * advertise the extension to avoid potentially breaking servers which carry
+ * over the state from the previous handshake, such as OpenSSL servers
+ * without upstream's 3c3f0259238594d77264a78944d409f2127642c4. */
+ if (!ssl->s3->initial_handshake_complete &&
+ ssl->session != NULL &&
+ ssl->session->tlsext_tick != NULL) {
+ ticket_data = ssl->session->tlsext_tick;
+ ticket_len = ssl->session->tlsext_ticklen;
+ }
+
+ CBB ticket;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
+ !CBB_add_u16_length_prefixed(out, &ticket) ||
+ !CBB_add_bytes(&ticket, ticket_data, ticket_len) ||
+ !CBB_flush(out)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+ CBS *contents) {
+ ssl->tlsext_ticket_expected = 0;
+
+ if (contents == NULL) {
+ return 1;
+ }
+
+ /* If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
+ * this function should never be called, even if the server tries to send the
+ * extension. */
+ assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
+
+ if (CBS_len(contents) != 0) {
+ return 0;
+ }
+
+ ssl->tlsext_ticket_expected = 1;
+ return 1;
+}
+
+static int ext_ticket_parse_clienthello(SSL *ssl, uint8_t *out_alert, CBS *contents) {
+ /* This function isn't used because the ticket extension from the client is
+ * handled in ssl_sess.c. */
+ return 1;
+}
+
+static int ext_ticket_add_serverhello(SSL *ssl, CBB *out) {
+ if (!ssl->tlsext_ticket_expected) {
+ return 1;
+ }
+
+ /* If |SSL_OP_NO_TICKET| is set, |tlsext_ticket_expected| should never be
+ * true. */
+ assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
+
+ if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
+ !CBB_add_u16(out, 0 /* length */)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
/* kExtensions contains all the supported extensions. */
static const struct tls_extension kExtensions[] = {
{
@@ -1214,6 +1294,14 @@
ext_ems_parse_clienthello,
ext_ems_add_serverhello,
},
+ {
+ TLSEXT_TYPE_session_ticket,
+ NULL,
+ ext_ticket_add_clienthello,
+ ext_ticket_parse_serverhello,
+ ext_ticket_parse_clienthello,
+ ext_ticket_add_serverhello,
+ },
};
#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
@@ -1310,30 +1398,6 @@
ret += CBB_len(&cbb);
CBB_cleanup(&cbb);
- if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
- int ticklen = 0;
- /* Renegotiation does not participate in session resumption. However, still
- * advertise the extension to avoid potentially breaking servers which carry
- * over the state from the previous handshake, such as OpenSSL servers
- * without upstream's 3c3f0259238594d77264a78944d409f2127642c4. */
- if (!s->s3->initial_handshake_complete && s->session != NULL &&
- s->session->tlsext_tick != NULL) {
- ticklen = s->session->tlsext_ticklen;
- }
-
- /* Check for enough room 2 for extension type, 2 for len rest for
- * ticket. */
- if ((long)(limit - ret - 4 - ticklen) < 0) {
- return NULL;
- }
- s2n(TLSEXT_TYPE_session_ticket, ret);
- s2n(ticklen, ret);
- if (ticklen) {
- memcpy(ret, s->session->tlsext_tick, ticklen);
- ret += ticklen;
- }
- }
-
if (ssl3_version_from_wire(s, s->client_version) >= TLS1_2_VERSION) {
size_t salglen;
const uint8_t *salg;
@@ -1605,14 +1669,6 @@
}
/* Currently the server should not respond with a SupportedCurves extension */
- if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) {
- if ((long)(limit - ret - 4) < 0) {
- return NULL;
- }
- s2n(TLSEXT_TYPE_session_ticket, ret);
- s2n(0, ret);
- }
-
if (s->s3->tmp.certificate_status_expected) {
if ((long)(limit - ret - 4) < 0) {
return NULL;
@@ -2011,7 +2067,6 @@
* systematically reset on a new handshake; perhaps allocate it fresh each
* time so it's not even kept around post-handshake. */
s->s3->next_proto_neg_seen = 0;
- s->tlsext_ticket_expected = 0;
s->s3->tmp.certificate_status_expected = 0;
s->srtp_profile = NULL;
@@ -2092,13 +2147,6 @@
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- } else if (type == TLSEXT_TYPE_session_ticket) {
- if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || CBS_len(&extension) > 0) {
- *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
- return 0;
- }
-
- s->tlsext_ticket_expected = 1;
} else if (type == TLSEXT_TYPE_status_request) {
/* The extension MUST be empty and may only sent if we've requested a
* status request message. */