Emulate the client_cert_cb with cert_cb.
This avoids needing a extra state around client certificates to avoid
calling the callbacks twice. This does, however, come with a behavior
change: configuring both callbacks won't work. No consumer does this.
(Except bssl_shim which needed slight tweaks.)
Change-Id: Ia5426ed2620e40eecdcf352216c4a46764e31a9a
Reviewed-on: https://boringssl-review.googlesource.com/12690
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index c0bdb5c..d1ad4ec 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -674,33 +674,6 @@
return CBB_flush(cbb);
}
-int ssl_do_client_cert_cb(SSL *ssl, int *out_should_retry) {
- if (ssl_has_certificate(ssl) || ssl->ctx->client_cert_cb == NULL) {
- return 1;
- }
-
- X509 *x509 = NULL;
- EVP_PKEY *pkey = NULL;
- int ret = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
- if (ret < 0) {
- *out_should_retry = 1;
- return 0;
- }
-
- if (ret != 0) {
- if (!SSL_use_certificate(ssl, x509) ||
- !SSL_use_PrivateKey(ssl, pkey)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- *out_should_retry = 0;
- return 0;
- }
- }
-
- X509_free(x509);
- EVP_PKEY_free(pkey);
- return 1;
-}
-
static int set_cert_store(X509_STORE **store_ptr, X509_STORE *new_store, int take_ref) {
X509_STORE_free(*store_ptr);
*store_ptr = new_store;
@@ -852,3 +825,35 @@
EVP_PKEY_free(pkey);
return ret;
}
+
+static int do_client_cert_cb(SSL *ssl, void *arg) {
+ if (ssl_has_certificate(ssl) || ssl->ctx->client_cert_cb == NULL) {
+ return 1;
+ }
+
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int ret = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (ret != 0) {
+ if (!SSL_use_certificate(ssl, x509) ||
+ !SSL_use_PrivateKey(ssl, pkey)) {
+ return 0;
+ }
+ }
+
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ return 1;
+}
+
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl,
+ X509 **out_x509,
+ EVP_PKEY **out_pkey)) {
+ /* Emulate the old client certificate callback with the new one. */
+ SSL_CTX_set_cert_cb(ctx, do_client_cert_cb, NULL);
+ ctx->client_cert_cb = cb;
+}