Adding NewSessionTicket.

We will now send tickets as a server and accept them as a
client. Correctly offering and resuming them in the handshake will be
implemented in a follow-up.

Now that we're actually processing draft 14 tickets, bump the draft
version.

Change-Id: I304320a29c4ffe564fa9c00642a4ace96ff8d871
Reviewed-on: https://boringssl-review.googlesource.com/8982
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index d844338..b15d56d 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -43,6 +43,8 @@
   state_process_client_certificate,
   state_process_client_certificate_verify,
   state_process_client_finished,
+  state_send_new_session_ticket,
+  state_flush_new_session_ticket,
   state_done,
 };
 
@@ -506,10 +508,55 @@
   }
 
   ssl->method->received_flight(ssl);
-  hs->state = state_done;
+  hs->state = state_send_new_session_ticket;
   return ssl_hs_ok;
 }
 
+static enum ssl_hs_wait_t do_send_new_session_ticket(SSL *ssl,
+                                                     SSL_HANDSHAKE *hs) {
+  SSL_SESSION *session = ssl->s3->new_session;
+  session->ticket_lifetime_hint = session->timeout;
+  session->ticket_flags = SSL_TICKET_ALLOW_DHE_RESUMPTION;
+  if (!RAND_bytes((uint8_t *)&session->ticket_age_add,
+                  sizeof(session->ticket_age_add))) {
+    return 0;
+  }
+  session->ticket_age_add_valid = 1;
+
+  CBB cbb, body, ticket;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_NEW_SESSION_TICKET) ||
+      !CBB_add_u32(&body, session->ticket_lifetime_hint) ||
+      !CBB_add_u32(&body, session->ticket_flags) ||
+      !CBB_add_u32(&body, session->ticket_age_add) ||
+      !CBB_add_u16(&body, 0 /* no ticket extensions */) ||
+      !CBB_add_u16_length_prefixed(&body, &ticket) ||
+      !ssl_encrypt_ticket(ssl, &ticket, session) ||
+      !ssl->method->finish_message(ssl, &cbb)) {
+    CBB_cleanup(&cbb);
+    return ssl_hs_error;
+  }
+
+  hs->session_tickets_sent++;
+
+  hs->state = state_flush_new_session_ticket;
+  return ssl_hs_write_message;
+}
+
+/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
+ * client makes several connections before getting a renewal. */
+static const int kNumTickets = 2;
+
+static enum ssl_hs_wait_t do_flush_new_session_ticket(SSL *ssl,
+                                                      SSL_HANDSHAKE *hs) {
+  if (hs->session_tickets_sent >= kNumTickets) {
+    hs->state = state_done;
+  } else {
+    hs->state = state_send_new_session_ticket;
+  }
+  return ssl_hs_flush;
+}
+
 enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
   SSL_HANDSHAKE *hs = ssl->s3->hs;
 
@@ -562,6 +609,12 @@
       case state_process_client_finished:
         ret = do_process_client_finished(ssl, hs);
         break;
+      case state_send_new_session_ticket:
+        ret = do_send_new_session_ticket(ssl, hs);
+        break;
+      case state_flush_new_session_ticket:
+        ret = do_flush_new_session_ticket(ssl, hs);
+        break;
       case state_done:
         ret = ssl_hs_ok;
         break;