Promote certificate-related ctrl macros to functions.

Also document them in the process. Almost done!

BUG=404754

Change-Id: I3333c7e9ea6b4a4844f1cfd02bff8b5161b16143
Reviewed-on: https://boringssl-review.googlesource.com/5355
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 74a20f4..99bacea 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -494,8 +494,13 @@
 
 /* Configuring certificates and private keys.
  *
- * TODO(davidben): Move the other, more conventional, certificate and key
- * configuration functions here. */
+ * These functions configure the connection's leaf certificate, private key, and
+ * certificate chain. The certificate chain is ordered leaf to root (as sent on
+ * the wire) but does not include the leaf. Both client and server certificates
+ * use these functions.
+ *
+ * Certificates and keys may be configured before the handshake or dynamically
+ * in the early callback and certificate callback. */
 
 /* SSL_CTX_use_certificate sets |ctx|'s leaf certificate to |x509|. It returns
  * one on success and zero on failure. */
@@ -513,6 +518,58 @@
  * success and zero on failure. */
 OPENSSL_EXPORT int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
 
+/* SSL_CTX_set0_chain sets |ctx|'s certificate chain, excluding the leaf, to
+ * |chain|. On success, it returns one and takes ownership of |chain|.
+ * Otherwise, it returns zero. */
+OPENSSL_EXPORT int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain);
+
+/* SSL_CTX_set1_chain sets |ctx|'s certificate chain, excluding the leaf, to
+ * |chain|. It returns one on success and zero on failure. The caller retains
+ * ownership of |chain| and may release it freely. */
+OPENSSL_EXPORT int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain);
+
+/* SSL_set0_chain sets |ssl|'s certificate chain, excluding the leaf, to
+ * |chain|. On success, it returns one and takes ownership of |chain|.
+ * Otherwise, it returns zero. */
+OPENSSL_EXPORT int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain);
+
+/* SSL_set1_chain sets |ssl|'s certificate chain, excluding the leaf, to
+ * |chain|. It returns one on success and zero on failure. The caller retains
+ * ownership of |chain| and may release it freely. */
+OPENSSL_EXPORT int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain);
+
+/* SSL_CTX_add0_chain_cert appends |x509| to |ctx|'s certificate chain. On
+ * success, it returns one and takes ownership of |x509|. Otherwise, it returns
+ * zero. */
+OPENSSL_EXPORT int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509);
+
+/* SSL_CTX_add1_chain_cert appends |x509| to |ctx|'s certificate chain. It
+ * returns one on success and zero on failure. The caller retains ownership of
+ * |x509| and may release it freely. */
+OPENSSL_EXPORT int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509);
+
+/* SSL_add0_chain_cert appends |x509| to |ctx|'s certificate chain. On success,
+ * it returns one and takes ownership of |x509|. Otherwise, it returns zero. */
+OPENSSL_EXPORT int SSL_add0_chain_cert(SSL *ssl, X509 *x509);
+
+/* SSL_CTX_add_extra_chain_cert calls |SSL_CTX_add0_chain_cert|. */
+OPENSSL_EXPORT int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509);
+
+/* SSL_add1_chain_cert appends |x509| to |ctx|'s certificate chain. It returns
+ * one on success and zero on failure. The caller retains ownership of |x509|
+ * and may release it freely. */
+OPENSSL_EXPORT int SSL_add1_chain_cert(SSL *ssl, X509 *x509);
+
+/* SSL_CTX_clear_chain_certs clears |ctx|'s certificate chain and returns
+ * one. */
+OPENSSL_EXPORT int SSL_CTX_clear_chain_certs(SSL_CTX *ctx);
+
+/* SSL_CTX_clear_extra_chain_certs calls |SSL_CTX_clear_chain_certs|. */
+OPENSSL_EXPORT int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx);
+
+/* SSL_clear_chain_certs clears |ssl|'s certificate chain and returns one. */
+OPENSSL_EXPORT int SSL_clear_chain_certs(SSL *ssl);
+
 /* SSL_CTX_set_cert_cb sets a callback that is called to select a certificate.
  * The callback returns one on success, zero on internal error, and a negative
  * number on failure or to pause the handshake. If the handshake is paused,
@@ -546,6 +603,26 @@
 /* SSL_get_certificate returns |ssl|'s leaf certificate. */
 OPENSSL_EXPORT X509 *SSL_get_certificate(const SSL *ssl);
 
+/* SSL_CTX_get0_privatekey returns |ctx|'s private key. */
+OPENSSL_EXPORT EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
+
+/* SSL_get_privatekey returns |ssl|'s private key. */
+OPENSSL_EXPORT EVP_PKEY *SSL_get_privatekey(const SSL *ssl);
+
+/* SSL_CTX_get0_chain_certs sets |*out_chain| to |ctx|'s certificate chain and
+ * returns one. */
+OPENSSL_EXPORT int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx,
+                                            STACK_OF(X509) **out_chain);
+
+/* SSL_CTX_get_extra_chain_certs calls |SSL_CTX_get0_chain_certs|. */
+OPENSSL_EXPORT int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
+                                                 STACK_OF(X509) **out_chain);
+
+/* SSL_get0_chain_certs sets |*out_chain| to |ssl|'s certificate chain and
+ * returns one. */
+OPENSSL_EXPORT int SSL_get0_chain_certs(const SSL *ssl,
+                                        STACK_OF(X509) **out_chain);
+
 
 /* Certificate and private key convenience functions. */
 
@@ -1836,14 +1913,6 @@
 #define SSL_ERROR_PENDING_CERTIFICATE 12
 #define SSL_ERROR_WANT_PRIVATE_KEY_OPERATION 13
 
-#define SSL_CTRL_EXTRA_CHAIN_CERT 14
-
-#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82
-#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83
-
-#define SSL_CTRL_CHAIN 88
-#define SSL_CTRL_CHAIN_CERT 89
-
 #define SSL_CTRL_GET_CURVES 90
 #define SSL_CTRL_SET_CURVES 91
 #define SSL_CTRL_SET_CURVES_LIST 92
@@ -1857,8 +1926,6 @@
 #define SSL_CTRL_SET_CHAIN_CERT_STORE 107
 #define SSL_CTRL_GET_EC_POINT_FORMATS 111
 
-#define SSL_CTRL_GET_CHAIN_CERTS 115
-
 /* DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a
  * timeout in progress, it sets |*out| to the time remaining and returns one.
  * Otherwise, it returns zero.
@@ -1946,25 +2013,6 @@
 OPENSSL_EXPORT size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out,
                                              size_t max_out);
 
-#define SSL_CTX_add_extra_chain_cert(ctx, x509) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, (char *)x509)
-#define SSL_CTX_get_extra_chain_certs(ctx, px509) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_GET_EXTRA_CHAIN_CERTS, 0, px509)
-#define SSL_CTX_clear_extra_chain_certs(ctx) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0, NULL)
-
-#define SSL_CTX_set0_chain(ctx, sk) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN, 0, (char *)sk)
-#define SSL_CTX_set1_chain(ctx, sk) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN, 1, (char *)sk)
-#define SSL_CTX_add0_chain_cert(ctx, x509) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 0, (char *)x509)
-#define SSL_CTX_add1_chain_cert(ctx, x509) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 1, (char *)x509)
-#define SSL_CTX_get0_chain_certs(ctx, px509) \
-  SSL_CTX_ctrl(ctx, SSL_CTRL_GET_CHAIN_CERTS, 0, px509)
-#define SSL_CTX_clear_chain_certs(ctx) SSL_CTX_set0_chain(ctx, NULL)
-
 #define SSL_CTX_set0_verify_cert_store(ctx, st) \
   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, (char *)st)
 #define SSL_CTX_set1_verify_cert_store(ctx, st) \
@@ -1974,16 +2022,6 @@
 #define SSL_CTX_set1_chain_cert_store(ctx, st) \
   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_CHAIN_CERT_STORE, 1, (char *)st)
 
-#define SSL_set0_chain(ctx, sk) SSL_ctrl(ctx, SSL_CTRL_CHAIN, 0, (char *)sk)
-#define SSL_set1_chain(ctx, sk) SSL_ctrl(ctx, SSL_CTRL_CHAIN, 1, (char *)sk)
-#define SSL_add0_chain_cert(ctx, x509) \
-  SSL_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 0, (char *)x509)
-#define SSL_add1_chain_cert(ctx, x509) \
-  SSL_ctrl(ctx, SSL_CTRL_CHAIN_CERT, 1, (char *)x509)
-#define SSL_get0_chain_certs(ctx, px509) \
-  SSL_ctrl(ctx, SSL_CTRL_GET_CHAIN_CERTS, 0, px509)
-#define SSL_clear_chain_certs(ctx) SSL_set0_chain(ctx, NULL)
-
 #define SSL_set0_verify_cert_store(s, st) \
   SSL_ctrl(s, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, (char *)st)
 #define SSL_set1_verify_cert_store(s, st) \
@@ -2604,10 +2642,16 @@
 
 #define DTLS_CTRL_GET_TIMEOUT doesnt_exist
 #define DTLS_CTRL_HANDLE_TIMEOUT doesnt_exist
+#define SSL_CTRL_CHAIN doesnt_exist
+#define SSL_CTRL_CHAIN_CERT doesnt_exist
 #define SSL_CTRL_CHANNEL_ID doesnt_exist
+#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS doesnt_exist
 #define SSL_CTRL_CLEAR_MODE doesnt_exist
 #define SSL_CTRL_CLEAR_OPTIONS doesnt_exist
+#define SSL_CTRL_EXTRA_CHAIN_CERT doesnt_exist
+#define SSL_CTRL_GET_CHAIN_CERTS doesnt_exist
 #define SSL_CTRL_GET_CHANNEL_ID doesnt_exist
+#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS doesnt_exist
 #define SSL_CTRL_GET_MAX_CERT_LIST doesnt_exist
 #define SSL_CTRL_GET_NUM_RENEGOTIATIONS doesnt_exist
 #define SSL_CTRL_GET_READ_AHEAD doesnt_exist
@@ -2644,9 +2688,16 @@
 
 #define DTLSv1_get_timeout DTLSv1_get_timeout
 #define DTLSv1_handle_timeout DTLSv1_handle_timeout
+#define SSL_CTX_add0_chain_cert SSL_CTX_add0_chain_cert
+#define SSL_CTX_add1_chain_cert SSL_CTX_add1_chain_cert
+#define SSL_CTX_add_extra_chain_cert SSL_CTX_add_extra_chain_cert
+#define SSL_CTX_clear_extra_chain_certs SSL_CTX_clear_extra_chain_certs
+#define SSL_CTX_clear_chain_certs SSL_CTX_clear_chain_certs
 #define SSL_CTX_clear_mode SSL_CTX_clear_mode
 #define SSL_CTX_clear_options SSL_CTX_clear_options
 #define SSL_CTX_enable_tls_channel_id SSL_CTX_enable_tls_channel_id
+#define SSL_CTX_get0_chain_certs SSL_CTX_get0_chain_certs
+#define SSL_CTX_get_extra_chain_certs SSL_CTX_get_extra_chain_certs
 #define SSL_CTX_get_max_cert_list SSL_CTX_get_max_cert_list
 #define SSL_CTX_get_mode SSL_CTX_get_mode
 #define SSL_CTX_get_options SSL_CTX_get_options
@@ -2657,6 +2708,8 @@
 #define SSL_CTX_sess_get_cache_size SSL_CTX_sess_get_cache_size
 #define SSL_CTX_sess_number SSL_CTX_sess_number
 #define SSL_CTX_sess_set_cache_size SSL_CTX_sess_set_cache_size
+#define SSL_CTX_set0_chain SSL_CTX_set0_chain
+#define SSL_CTX_set1_chain SSL_CTX_set1_chain
 #define SSL_CTX_set1_tls_channel_id SSL_CTX_set1_tls_channel_id
 #define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list
 #define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment
@@ -2673,9 +2726,13 @@
 #define SSL_CTX_set_tmp_dh SSL_CTX_set_tmp_dh
 #define SSL_CTX_set_tmp_ecdh SSL_CTX_set_tmp_ecdh
 #define SSL_CTX_set_tmp_rsa SSL_CTX_set_tmp_rsa
+#define SSL_add0_chain_cert SSL_add0_chain_cert
+#define SSL_add1_chain_cert SSL_add1_chain_cert
+#define SSL_clear_chain_certs SSL_clear_chain_certs
 #define SSL_clear_mode SSL_clear_mode
 #define SSL_clear_options SSL_clear_options
 #define SSL_enable_tls_channel_id SSL_enable_tls_channel_id
+#define SSL_get0_chain_certs SSL_get0_chain_certs
 #define SSL_get_max_cert_list SSL_get_max_cert_list
 #define SSL_get_mode SSL_get_mode
 #define SSL_get_options SSL_get_options
@@ -2685,6 +2742,8 @@
 #define SSL_need_tmp_RSA SSL_need_tmp_RSA
 #define SSL_num_renegotiations SSL_num_renegotiations
 #define SSL_session_reused SSL_session_reused
+#define SSL_set0_chain SSL_set0_chain
+#define SSL_set1_chain SSL_set1_chain
 #define SSL_set1_tls_channel_id SSL_set1_tls_channel_id
 #define SSL_set_max_cert_list SSL_set_max_cert_list
 #define SSL_set_max_send_fragment SSL_set_max_send_fragment
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index dc8d2e0..877f88d 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -375,25 +375,6 @@
   int ret = 0;
 
   switch (cmd) {
-    case SSL_CTRL_CHAIN:
-      if (larg) {
-        return ssl_cert_set1_chain(s->cert, (STACK_OF(X509) *)parg);
-      } else {
-        return ssl_cert_set0_chain(s->cert, (STACK_OF(X509) *)parg);
-      }
-
-    case SSL_CTRL_CHAIN_CERT:
-      if (larg) {
-        return ssl_cert_add1_chain_cert(s->cert, (X509 *)parg);
-      } else {
-        return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
-      }
-
-    case SSL_CTRL_GET_CHAIN_CERTS:
-      *(STACK_OF(X509) **)parg = s->cert->chain;
-      ret = 1;
-      break;
-
     case SSL_CTRL_GET_CURVES: {
       const uint16_t *clist = s->s3->tmp.peer_ellipticcurvelist;
       size_t clistlen = s->s3->tmp.peer_ellipticcurvelist_length;
@@ -483,33 +464,6 @@
     case SSL_CTRL_SET_CHAIN_CERT_STORE:
       return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
 
-    case SSL_CTRL_EXTRA_CHAIN_CERT:
-      return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
-
-    case SSL_CTRL_GET_EXTRA_CHAIN_CERTS:
-    case SSL_CTRL_GET_CHAIN_CERTS:
-      *(STACK_OF(X509) **)parg = ctx->cert->chain;
-      break;
-
-    case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS:
-      sk_X509_pop_free(ctx->cert->chain, X509_free);
-      ctx->cert->chain = NULL;
-      break;
-
-    case SSL_CTRL_CHAIN:
-      if (larg) {
-        return ssl_cert_set1_chain(ctx->cert, (STACK_OF(X509) *)parg);
-      } else {
-        return ssl_cert_set0_chain(ctx->cert, (STACK_OF(X509) *)parg);
-      }
-
-    case SSL_CTRL_CHAIN_CERT:
-      if (larg) {
-        return ssl_cert_add1_chain_cert(ctx->cert, (X509 *)parg);
-      } else {
-        return ssl_cert_add0_chain_cert(ctx->cert, (X509 *)parg);
-      }
-
     default:
       return 0;
   }
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 3e22582..afa4cec 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -809,3 +809,66 @@
   }
   return 1;
 }
+
+int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+  return ssl_cert_set0_chain(ctx->cert, chain);
+}
+
+int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+  return ssl_cert_set1_chain(ctx->cert, chain);
+}
+
+int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
+  return ssl_cert_set0_chain(ssl->cert, chain);
+}
+
+int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
+  return ssl_cert_set1_chain(ssl->cert, chain);
+}
+
+int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  return ssl_cert_add0_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  return ssl_cert_add1_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  return SSL_CTX_add0_chain_cert(ctx, x509);
+}
+
+int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
+  return ssl_cert_add0_chain_cert(ssl->cert, x509);
+}
+
+int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
+  return ssl_cert_add1_chain_cert(ssl->cert, x509);
+}
+
+int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
+  return SSL_CTX_set0_chain(ctx, NULL);
+}
+
+int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
+  return SSL_CTX_clear_chain_certs(ctx);
+}
+
+int SSL_clear_chain_certs(SSL *ssl) {
+  return SSL_set0_chain(ssl, NULL);
+}
+
+int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
+  *out_chain = ctx->cert->chain;
+  return 1;
+}
+
+int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
+                                  STACK_OF(X509) **out_chain) {
+  return SSL_CTX_get0_chain_certs(ctx, out_chain);
+}
+
+int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
+  *out_chain = ssl->cert->chain;
+  return 1;
+}