Add an interface for QUIC integration.

0-RTT support and APIs to consume NewSessionTicket will be added in a
follow-up.

Change-Id: Ib2b2c6b618b3e33a74355fb53fdbd2ffafcc5c56
Reviewed-on: https://boringssl-review.googlesource.com/c/31744
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 1f64865..5bd2442 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -781,6 +781,82 @@
 
 BIO *SSL_get_wbio(const SSL *ssl) { return ssl->wbio.get(); }
 
+size_t SSL_quic_max_handshake_flight_len(const SSL *ssl,
+                                         enum ssl_encryption_level_t level) {
+  // Limits flights to 16K by default when there are no large
+  // (certificate-carrying) messages.
+  static const size_t kDefaultLimit = 16384;
+
+  switch (level) {
+    case ssl_encryption_initial:
+      return kDefaultLimit;
+    case ssl_encryption_early_data:
+      // QUIC does not send EndOfEarlyData.
+      return 0;
+    case ssl_encryption_handshake:
+      if (ssl->server) {
+        // Servers may receive Certificate message if configured to request
+        // client certificates.
+        if (!!(ssl->config->verify_mode & SSL_VERIFY_PEER) &&
+            ssl->max_cert_list > kDefaultLimit) {
+          return ssl->max_cert_list;
+        }
+      } else {
+        // Clients may receive both Certificate message and a CertificateRequest
+        // message.
+        if (2*ssl->max_cert_list > kDefaultLimit) {
+          return 2*ssl->max_cert_list;
+        }
+      }
+      return kDefaultLimit;
+    case ssl_encryption_application:
+      // Note there is not actually a bound on the number of NewSessionTickets
+      // one may send in a row. This level may need more involved flow
+      // control. See https://github.com/quicwg/base-drafts/issues/1834.
+      return kDefaultLimit;
+  }
+
+  return 0;
+}
+
+enum ssl_encryption_level_t SSL_quic_read_level(const SSL *ssl) {
+  return ssl->s3->read_level;
+}
+
+enum ssl_encryption_level_t SSL_quic_write_level(const SSL *ssl) {
+  return ssl->s3->write_level;
+}
+
+int SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level,
+                          const uint8_t *data, size_t len) {
+  if (ssl->ctx->quic_method == nullptr) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  if (level != ssl->s3->read_level) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED);
+    return 0;
+  }
+
+  size_t new_len = (ssl->s3->hs_buf ? ssl->s3->hs_buf->length : 0) + len;
+  if (new_len < len ||
+      new_len > SSL_quic_max_handshake_flight_len(ssl, level)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+    return 0;
+  }
+
+  // Re-create the handshake buffer if needed.
+  if (!ssl->s3->hs_buf) {
+    ssl->s3->hs_buf.reset(BUF_MEM_new());
+    if (!ssl->s3->hs_buf) {
+      return 0;
+    }
+  }
+
+  return BUF_MEM_append(ssl->s3->hs_buf.get(), data, len);
+}
+
 int SSL_do_handshake(SSL *ssl) {
   ssl_reset_error_state(ssl);
 
@@ -961,6 +1037,11 @@
 }
 
 int SSL_peek(SSL *ssl, void *buf, int num) {
+  if (ssl->ctx->quic_method != nullptr) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
   int ret = ssl_read_impl(ssl);
   if (ret <= 0) {
     return ret;
@@ -977,6 +1058,11 @@
 int SSL_write(SSL *ssl, const void *buf, int num) {
   ssl_reset_error_state(ssl);
 
+  if (ssl->ctx->quic_method != nullptr) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
   if (ssl->do_handshake == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
     return -1;
@@ -1193,6 +1279,9 @@
       return SSL_ERROR_HANDBACK;
 
     case SSL_READING: {
+      if (ssl->ctx->quic_method) {
+        return SSL_ERROR_WANT_READ;
+      }
       BIO *bio = SSL_get_rbio(ssl);
       if (BIO_should_read(bio)) {
         return SSL_ERROR_WANT_READ;
@@ -2298,6 +2387,14 @@
   return buf;
 }
 
+int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method) {
+  if (ctx->method->is_dtls) {
+    return 0;
+  }
+  ctx->quic_method = quic_method;
+  return 1;
+}
+
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
                          CRYPTO_EX_dup *dup_unused, CRYPTO_EX_free *free_func) {
   int index;