Add |SSL_CTX_get0_chain|.

This is the getter counterpart to |SSL_CTX_set_chain_and_key|. There's
no |SSL*| because a) we didn't need it and b) then you have to worry
about config discarding and it doesn't end up being very useful.

Change-Id: Iba75d0165d7e555d0f793687b1f5e1e6c6f7c738
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40264
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 234b088..23489dd 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1098,6 +1098,20 @@
     SSL *ssl, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey,
     const SSL_PRIVATE_KEY_METHOD *privkey_method);
 
+// SSL_CTX_get0_chain returns the list of |CRYPTO_BUFFER|s that were set by
+// |SSL_CTX_set_chain_and_key|. Reference counts are not incremented by this
+// call. The return value may be |NULL| if no chain has been set.
+//
+// (Note: if a chain was configured by non-|CRYPTO_BUFFER|-based functions then
+// the return value is undefined and, even if not NULL, the stack itself may
+// contain nullptrs. Thus you shouldn't mix this function with
+// non-|CRYPTO_BUFFER| functions for manipulating the chain.)
+//
+// There is no |SSL*| version of this function because connections discard
+// configuration after handshaking, thus making it of questionable utility.
+OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER)*
+    SSL_CTX_get0_chain(const SSL_CTX *ctx);
+
 // SSL_CTX_use_RSAPrivateKey sets |ctx|'s private key to |rsa|. It returns one
 // on success and zero on failure.
 OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
diff --git a/ssl/ssl_cert.cc b/ssl/ssl_cert.cc
index 4f80382..6bac3a9 100644
--- a/ssl/ssl_cert.cc
+++ b/ssl/ssl_cert.cc
@@ -896,6 +896,10 @@
                                 privkey_method);
 }
 
+const STACK_OF(CRYPTO_BUFFER)* SSL_CTX_get0_chain(const SSL_CTX *ctx) {
+  return ctx->cert->chain.get();
+}
+
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
                                  const uint8_t *der) {
   UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(der, der_len, NULL));
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index cc6fdee..9ccab18 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -3284,6 +3284,8 @@
   bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_with_buffers_method()));
   ASSERT_TRUE(server_ctx);
 
+  ASSERT_EQ(nullptr, SSL_CTX_get0_chain(server_ctx.get()));
+
   bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
   ASSERT_TRUE(key);
   bssl::UniquePtr<CRYPTO_BUFFER> leaf = GetChainTestCertificateBuffer();
@@ -3297,6 +3299,9 @@
   ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
                                         chain.size(), key.get(), nullptr));
 
+  ASSERT_EQ(chain.size(),
+            sk_CRYPTO_BUFFER_num(SSL_CTX_get0_chain(server_ctx.get())));
+
   SSL_CTX_set_custom_verify(
       client_ctx.get(), SSL_VERIFY_PEER,
       [](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {