Add APIs to query authentication properties of SSL_SESSIONs.

This is so Chromium can verify the session before offering it, rather
than doing it after the handshake (at which point it's too late to punt
the session) as we do today. This should, in turn, allow us to finally
verify certificates off a callback and order it correctly relative to
CertificateRequest in TLS 1.3.

(It will also order "correctly" in TLS 1.2, but this is useless. TLS 1.2
does not bind the CertificateRequest to the certificate at the point the
client needs to act on it.)

Bug: chromium:347402
Change-Id: I0daac2868c97b820aead6c3a7e4dc30d8ba44dc4
Reviewed-on: https://boringssl-review.googlesource.com/28405
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>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 81a45c7..9544bbe 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1697,6 +1697,26 @@
 OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) *
     SSL_SESSION_get0_peer_certificates(const SSL_SESSION *session);
 
+// SSL_SESSION_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to
+// point to |*out_len| bytes of SCT information stored in |session|. This is
+// only valid for client sessions. The SCT information is a
+// SignedCertificateTimestampList (including the two leading length bytes). See
+// https://tools.ietf.org/html/rfc6962#section-3.3 If no SCT was received then
+// |*out_len| will be zero on return.
+//
+// WARNING: the returned data is not guaranteed to be well formed.
+OPENSSL_EXPORT void SSL_SESSION_get0_signed_cert_timestamp_list(
+    const SSL_SESSION *session, const uint8_t **out, size_t *out_len);
+
+// SSL_SESSION_get0_ocsp_response sets |*out| and |*out_len| to point to
+// |*out_len| bytes of an OCSP response from the server. This is the DER
+// encoding of an OCSPResponse type as defined in RFC 2560.
+//
+// WARNING: the returned data is not guaranteed to be well formed.
+OPENSSL_EXPORT void SSL_SESSION_get0_ocsp_response(const SSL_SESSION *session,
+                                                   const uint8_t **out,
+                                                   size_t *out_len);
+
 // SSL_SESSION_get_master_key writes up to |max_out| bytes of |session|'s master
 // secret to |out| and returns the number of bytes written. If |max_out| is
 // zero, it returns the size of the master secret.
@@ -1864,7 +1884,11 @@
 
 // SSL_set_session, for a client, configures |ssl| to offer to resume |session|
 // in the initial handshake and returns one. The caller retains ownership of
-// |session|.
+// |session|. Note that configuring a session assumes the authentication in the
+// session is valid. For callers that wish to revalidate the session before
+// offering, see |SSL_SESSION_get0_peer_certificates|,
+// |SSL_SESSION_get0_signed_cert_timestamp_list|, and
+// |SSL_SESSION_get0_ocsp_response|.
 //
 // It is an error to call this function after the handshake has begun.
 OPENSSL_EXPORT int SSL_set_session(SSL *ssl, SSL_SESSION *session);
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index d8f3bbd..e31df68 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -922,6 +922,29 @@
   return session->certs;
 }
 
+void SSL_SESSION_get0_signed_cert_timestamp_list(const SSL_SESSION *session,
+                                                 const uint8_t **out,
+                                                 size_t *out_len) {
+  if (session->signed_cert_timestamp_list) {
+    *out = CRYPTO_BUFFER_data(session->signed_cert_timestamp_list);
+    *out_len = CRYPTO_BUFFER_len(session->signed_cert_timestamp_list);
+  } else {
+    *out = nullptr;
+    *out_len = 0;
+  }
+}
+
+void SSL_SESSION_get0_ocsp_response(const SSL_SESSION *session,
+                                    const uint8_t **out, size_t *out_len) {
+  if (session->ocsp_response) {
+    *out = CRYPTO_BUFFER_data(session->ocsp_response);
+    *out_len = CRYPTO_BUFFER_len(session->ocsp_response);
+  } else {
+    *out = nullptr;
+    *out_len = 0;
+  }
+}
+
 size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
                                   size_t max_out) {
   // TODO(davidben): Fix master_key_length's type and remove these casts.